当@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
答案 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无法使用第一级缓存,并且必须查询数据库。