Hibernate从3升级到4:Criteria事务停止运行

时间:2014-02-26 15:23:51

标签: java hibernate migration criteria

我最近在一个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继续询问那里的类型,而不是强迫'查看'类型。

1 个答案:

答案 0 :(得分:0)

最后,由于我在EDIT块中指定的提示,我找到了解决方案。

解决方案来自于在基类中建立公式:

@DiscriminatorFormula("case when type in ('viewing','directory') then 1 else 2 end")

然后在查看资源中更改鉴别器值注释:

@DiscriminatorValue("1")

我真的不知道为什么在Hibernate 3中我得到了歧视中的所有值,而在Hibernate 4中,值只是这一个,因为代码根本没有改变。因此,如果将来有人看到类似的行为,也许这个技巧可以帮助你。