[英]Hibernate is using wrong table name for order by expression with three level inheritance
在我们的项目中,我们有不同类别的不同用户类型。 我们有一个BaseEntity类作为@MappedSuperclass。 当我们尝试使用带有InheritanceType.JOINED的用户类时,hibernate会创建一个我们认为错误的sql。
基本实体:
@MappedSuperclass
public abstract class BaseEntity implements java.io.Serializable {
private Integer id;
private Date createdDate = new Date();
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "CREATED_DATE", nullable = true)
public Date getCreatedDate() {
return createdDate;
}
public void setCreatedDate(Date createdDate) {
this.createdDate = createdDate;
}
}
基本用户
@Entity
@Table(name = "BASE_USER")
@Inheritance(strategy = InheritanceType.JOINED)
@AttributeOverride(name = "id", column = @Column(name = "ID", nullable = false, insertable = false, updatable = false))
public abstract class BaseUser extends BaseEntity{
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq")
@SequenceGenerator(name = "seq", sequenceName = "USER_SEQ", allocationSize = 1)
public Integer getId() {
return super.getId();
}
}
用户
@Entity
@Table(name = "FIRM_USER")
public class FirmUser extends BaseUser {
private String name;
@Column(name = "name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
示例代码
public class HibernateUtil {
private static final SessionFactory sessionFactory;
static {
try {
sessionFactory = new AnnotationConfiguration()
.addAnnotatedClass(FirmUser.class)
.addAnnotatedClass(BaseUser.class)
.addAnnotatedClass(BaseEntity.class)
.configure()
.buildSessionFactory();
} catch (Throwable ex) {
throw new ExceptionInInitializerError(ex);
}
}
public static Session getSession() throws HibernateException {
return sessionFactory.openSession();
}
public static void main(String[] args) {
getSession().save(new FirmUser());
Query query = getSession().createQuery("select distinct a from FirmUser a ORDER BY a.id");
query.list();
}
}
对于这个hql
select distinct a from FirmUser a ORDER BY a.id
hibernate创建这个sql
select distinct firmuser0_.ID as ID1_0_,
firmuser0_1_.CREATED_DATE as CREATED_2_0_,
firmuser0_.name as name1_1_
from FIRM_USER firmuser0_
inner join BASE_USER firmuser0_1_ on firmuser0_.ID=firmuser0_1_.ID
order by firmuser0_1_.ID
“由firmuser0_1_.ID排序”导致
HSQLDB : ORDER BY item should be in the SELECT DISTINCT list:
要么
ORACLE : ORA-01791: not a SELECTed expression
但是firmuser0_.ID在select子句中,我们实际上尝试按FirmUser(firmuser0_)的ID排序而不是BaseUser(firmuser0_1_)
如果我们不使用BaseEntity,它按预期工作。
为什么hibernate使用join类进行排序,以防它继承自另一个类?
我复制了你的测试用例,你可以在GitHub上找到它。
必须存在Hibernate错误,因为当您使用别名时,select子句使用子类ID,而ORDER BY使用基类id,因为它不在select子句中,所以抛出异常:
SELECT inheritanc0_.id AS ID1_0_,
inheritanc0_1_.created_date AS CREATED_2_0_,
inheritanc0_.NAME AS name1_1_
FROM firm_user inheritanc0_
INNER JOIN base_user inheritanc0_1_
ON inheritanc0_.id = inheritanc0_1_.id
ORDER BY inheritanc0_1_.id
注意ORDER BY inheritanc0_1_.id
,它应该是ORDER BY inheritanc0_.id
。
重写不带别名的查询:
List<FirmUser> result1 = (List<FirmUser>) session.createQuery("from FirmUser order by id").list();
正确生成SQL:
SELECT inheritanc0_.id AS ID1_0_,
inheritanc0_1_.created_date AS CREATED_2_0_,
inheritanc0_.NAME AS name1_1_
FROM firm_user inheritanc0_
INNER JOIN base_user inheritanc0_1_
ON inheritanc0_.id = inheritanc0_1_.id
ORDER BY inheritanc0_1_.id
或指定subclass.id,但这会产生子类和子类实体元组的数组:
List<Object[]> result2 = (List<Object[]>) session.createQuery("select distinct a, a.id from FirmUser a order by id").list();
给出以下SQL:
SELECT DISTINCT inheritanc0_1_.id AS col_0_0_,
inheritanc0_1_.id AS col_1_0_,
inheritanc0_.id AS ID1_0_,
inheritanc0_1_.created_date AS CREATED_2_0_,
inheritanc0_.NAME AS name1_1_
FROM firm_user inheritanc0_
INNER JOIN base_user inheritanc0_1_
ON inheritanc0_.id = inheritanc0_1_.id
ORDER BY inheritanc0_1_.id
像往常一样,本机查询为您提供对任何元组关联的最终控制:
List<FirmUser> result3 = (List<FirmUser>) session.createSQLQuery(
"select * " +
"from FIRM_USER a " +
"LEFT JOIN BASE_USER b ON a.id = b.id " +
"order by a.id"
)
.addEntity("a", FirmUser.class)
.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
.list();
你应该为这个问题填写一个Hibernate问题,因为它的行为并不像它应该的那样。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.