Hibernate - byNaturalId不工作

时间:2014-10-27 16:11:29

标签: java hibernate

我有一个由两个自然ID标识的用户实体,类似于

@Entity
@Table(name = "user", uniqueConstraints =
{ @UniqueConstraint(columnNames = "email"),
    @UniqueConstraint(columnNames = "nick") })
public User()
{}

@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "id", unique = true, nullable = false)
private id;

@Column(name = "email", unique = true, nullable = false, length = 31)
@NaturalId(mutable = true)
private String email;   

@Column(name = "nick", unique = true, nullable = false, length = 31)
@NaturalId(mutable = false)
private String nick;

但是,当我尝试执行

session.byNaturalId(User.class).with(LockOptions.READ).using("email", "admin@mail.com").load();

它抛出异常

org.hibernate.HibernateException: Entity [pervasive.com.gmail.tigerjack89.forum.shared.model.entities.User] defines its natural-id with 2 properties but only 1 were specified
at org.hibernate.event.spi.ResolveNaturalIdEvent.<init>(ResolveNaturalIdEvent.java:75)
at org.hibernate.event.spi.ResolveNaturalIdEvent.<init>(ResolveNaturalIdEvent.java:52)
at org.hibernate.internal.SessionImpl$BaseNaturalIdLoadAccessImpl.resolveNaturalId(SessionImpl.java:2607)
at org.hibernate.internal.SessionImpl$NaturalIdLoadAccessImpl.load(SessionImpl.java:2722)
at pervasive.com.gmail.tigerjack89.forum.server.model.orm.StorageManager.getByNaturalId(StorageManager.java:217)
at pervasive.com.gmail.tigerjack89.test.local.MyHibernateTest.test1(MyHibernateTest.java:37)
at pervasive.com.gmail.tigerjack89.test.local.MyHibernateTest.main(MyHibernateTest.java:23)

这是为什么?我认为这也是由于Hibernate生成的SQL语法的日志。实际上,这一点很奇怪(多余),我认为这是异常的原因

Hibernate: 
    alter table user 
        add constraint UK_t8tbwelrnviudxdaggwr1kd9b  unique (email, nick)
Hibernate: 
    alter table user 
        add constraint UK_ob8kqyqqgmefl0aco34akdtpe  unique (email)
Hibernate: 
    alter table user 
        add constraint UK_pvnbxcfihb58o5n2n1fnc7fh1  unique (nick)

编辑:再次阅读代码,我认为问题可能与@UniqueConstraints注释有关。但是,即使我尝试删除其中一个,Hibernate仍继续使用上述SQL语法。

2 个答案:

答案 0 :(得分:0)

我会将电子邮件地址单独设为NaturalId,然后您的查询就可以了。

当两列被识别为NaturalId时,它会创建一个复合键。

Nick仍然可以用作外键。

答案 1 :(得分:0)

您拥有复合的naturalId键(电子邮件,昵称),因此您可以使用简单的电子邮件arg获得倍数结果。 你使用

session
   .byNaturalId(User.class)
   .with(LockOptions.READ)
   .using("email", "admin@mail.com")
   .using("nick", "admin")
   .load();

您也可以使用Metamodel

session
   .byNaturalId(User.class)
   .with(LockOptions.READ)
   .using(User_.email.getName(), "admin@mail.com")
   .using(User_.nick.getName(), "admin")
   .load();