@ManyToOne将ColumnName引用到UniqueField但不引用PrimaryKey

时间:2015-12-17 13:58:18

标签: hibernate jpa many-to-one unique-key

@ManyToOne引用非主键字段时,我发现了一种奇怪的行为。

部分。 1参考不是PrimaryKey

数据库表:

Sessions
ID number         (pk)
SESSIONID varchar (unique, not null) 

History
ID number         (pk)
SESSIONID varchar (fk to Sessions.SESSIONID)

Entityes:

 @Entity
 @Table(name = "SESSIONS@ESAD_DB_LINK", schema = "ESAD_OWNER", 
 uniqueConstraints = {@UniqueConstraint(columnNames = {"sessionid"})})
 public class Sessions implements Serializable {
   private static final long serialVersionUID = 1L;    
   @Id
   @Basic(optional = false)
   @NotNull
   @Column(name = "ID")
   private BigInteger id;      
   @Basic(optional = false)
   @NotNull
   @Size(min = 1, max = 40)
   @Column(name = "SESSIONID", unique = true)
   private String sessionid;   
   @OneToMany(mappedBy = "session", fetch = FetchType.LAZY)
   private List<History> history;
   .........
}

@Entity
  @Table(name = "HISTORY@ESAD_DB_LINK", schema = "ESAD_OWNER")
  public class History implements Serializable {
  private static final long serialVersionUID = 1L;    
  @Id
  @Basic(optional = false)
  @NotNull
  @Column(name = "ID")
  private BigInteger id;

  @ManyToOne
  @JoinColumn(name = "SESSIONID", referencedColumnName = "SESSIONID")   
  private Sessions session;
  ..........
  }

代码:

List<History> hsLazy = sessions.getHistory();//Nothing select
for (History hsLazy1 : hsLazy) {  //*           
   System.out.println(hsLazy1.getId());
}

*  从SESSIONID =?

的历史中选择一个

多个 SELECT FROM SESSIONS WHERE SESSIONID = ?, SELECT的计数=子表历史记录的计数

Part.2对PrimaryKey的引用

数据库表:

Sessions
ID number         (pk)
SESSIONID varchar (unique, not null) 

History
ID number         (pk)
SESSIONID number(fk to Sessions.ID)

实体:将历史记录更改为

 @Entity
 @Table(name = "HISTORY@ESAD_DB_LINK", schema = "ESAD_OWNER")
 public class History implements Serializable {
   private static final long serialVersionUID = 1L;    
    .......... 
   @ManyToOne
   @JoinColumn(name = "SESSIONID", referencedColumnName = "ID",
                                                 nullable=false)   
   private Sessions session;
..........

代码:

List<History> hsLazy = sessions.getHistory();//Nothing select
for (History hsLazy1 : hsLazy) {  //*           
   System.out.println(hsLazy1.getId());
}

* ONE 按会话ID从历史记录中选择

为什么Hibernate在@ManyToOne引用不是PrimaryKey和引用PrimaryKey时会生成不同数量的查询? 为什么这么发生? 是否可以在未引用PK时更改行为。

P.S。 JPA 2.0 Hibernate 4.2.5

2 个答案:

答案 0 :(得分:1)

@ManyToOne关联的两种情况下,您都渴望为每个Session提取History个对象。可能是,在第二种情况下(引用PrimaryKey)Hibernate从缓存中获取Session对象,因此没有任何其他SQL查询。 我的建议是将抓取更改为延迟,并在需要时使用Session(或其他方式)获取join fetch

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "SESSIONID", referencedColumnName = "SESSIONID")   
private Sessions session;

答案 1 :(得分:1)

Hibernate的第一级缓存基于主键。

如果使用主键作为外键,则Hibernate可以直接从缓存加载对象。

如果对外键使用辅助密钥,则Hibernate无法使用第一级缓存,并且必须查询数据库。