我最近在一个Web应用程序的一般升级中将Spring 2.5升级到3.2,将Hibernate 3升级到4.2.8。大多数事情现在都在运作,但有一个Criteria交易无效,令我感到困惑。新版本不返回任何结果(但没有错误),而旧版本正确检索到请求的值。
旧版本和新版本的代码是相同的,我已经验证到达它的参数是相同的。这是Java代码:
Criteria criteria = sessionFactory.getCurrentSession().createCriteria(ViewingResource.class);
criteria.createCriteria("viewings","currentViewings");
criteria.add(Property.forName("currentViewings.id").eq(viewingId));
ViewingResource result = (ViewingResource)criteria.uniqueResult();
ViewingResource是我的实体,定义如下:
@Entity
@DiscriminatorValue("viewing")
public class ViewingResource extends AbstractInformationResource {
private static final long serialVersionUID = -4569093742552159052L;
@OneToOne(targetEntity = Attribute.class, fetch = FetchType.LAZY)
@JoinColumn
private Attribute primaryAttribute;
@OneToMany(targetEntity = Viewing.class, cascade = {CascadeType.PERSIST, CascadeType.MERGE}, orphanRemoval=true)
@Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE})
@JoinTable(name = "informationresource_viewings")
@OrderBy("sort")
private Set<ResourceViewing> viewings;
public Set<ResourceViewing> getViewings() {
return viewings;
}
public Attribute getPrimaryAttribute() {
return primaryAttribute;
}
}
至于它扩展的抽象类:
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(
name = "type",
discriminatorType = DiscriminatorType.STRING
)
@Table(name = "informationresource")
abstract public class AbstractInformationResource extends PersistentEntity<String> {
private static final long serialVersionUID = 8709376067232042462L;
@Id @GeneratedValue(generator="system-uuid")
@GenericGenerator(name="system-uuid", strategy = "uuid")
private String id;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private int sort;
public String getId() {
return id;
}
public String getName() {
return name;
}
public int getSort() {
return sort;
}
}
原始的PersistentEntity只是Serializable的扩展,带有id而没有注释。
我启用了Hibernate日志,发现问题可能在Hibernate 3和4之间的注释工作方式,因为Hibernate生成的SQL字符串以这种方式不同:
Hibernate 3:
select
... (maps to all columns)
from
informationresource this_
inner join
informationresource_viewings viewings3_
on this_.id=viewings3_.informationresource_id
inner join
Viewing currentvie1_
on viewings3_.viewings_id=currentvie1_.id
where
this_.type in (
'viewing', 'directory'
)
and currentvie1_.id=?
而在Hibernate 4中,生成的SQL不执行连接:
select
... (maps to all columns, except type, attributeType and fieldName)
from
informationresource this_,
informationresource_viewings viewings3_,
Viewing currentvie1_
where
this_.id=viewings3_.informationresource_id
and viewings3_.viewings_id=currentvie1_.id
and this_.type='viewing'
and currentvie1_.id=?
任何可能有助于我解决此问题的提示?我目前的猜测是,我可能会跳过一些自Hibernate 3以来已经更改或修改过的注释定义,但到目前为止,我还没有找到任何违反我声明它们的方式 - 我试图修改@Join到目前为止没有成功。
EDIT。在玩了一段时间之后,我发现问题可能与抽象类的@DiscriminatorColumn有关。我发现问题在于我的这种请求的类型永远不会“查看”,而是“目录”。在旧生成的SQL中,我生成了两种类型:
this_.type in (
'viewing', 'directory'
)
但是在新的sql中,这被限制为“查看”:
and this_.type='viewing'
我已在新行中更改了此行,并返回了我需要的正确值。列类型只有那两个值,'viewing'和'directory'。所以我现在的问题是如何让Criteria继续询问那里的类型,而不是强迫'查看'类型。
答案 0 :(得分:0)
最后,由于我在EDIT块中指定的提示,我找到了解决方案。
解决方案来自于在基类中建立公式:
@DiscriminatorFormula("case when type in ('viewing','directory') then 1 else 2 end")
然后在查看资源中更改鉴别器值注释:
@DiscriminatorValue("1")
我真的不知道为什么在Hibernate 3中我得到了歧视中的所有值,而在Hibernate 4中,值只是这一个,因为代码根本没有改变。因此,如果将来有人看到类似的行为,也许这个技巧可以帮助你。