【发布时间】:2015-07-16 22:00:41
【问题描述】:
我在创建 @ManyToOne 关联以延迟加载时遇到了一些麻烦。我正在使用 fetch=LAZY 但当主键列未进行连接时它不起作用。
我知道这个问题已经是asked,但我认为它没有得到正确回答,所以我提供了详细信息来澄清这个问题。
这是我的模型:
DummyB -> DummyA
这些是表格:
create table dummyA (
id number(18,0), --pk
name varchar2(20) -- unique field
);
create table dummyB (
id number(18,0),
dummya_id number(18,0),
dummya_name varchar2(20)
);
这些是实体:
@Entity
public class DummyA implements Serializable {
private Long id;
private String name;
@Id
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@Entity
public class DummyB implements Serializable {
private Long id;
private DummyA dummyA;
@Id
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
/* Case 1: mapping DummyB -> DummyA by DummyA NON primary key (field name) */
// @ManyToOne(fetch = FetchType.LAZY)
// @JoinColumn(name = "dummya_id")
// public DummyA getDummyA() {
// return dummyA;
// }
/* Case 2: mapping DummyB -> DummyA by DummyA primary key */
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "dummya_name", referencedColumnName = "name")
@LazyToOne(LazyToOneOption.PROXY)
public DummyA getDummyA() {
return dummyA;
}
public void setDummyA(DummyA dummyA) {
this.dummyA = dummyA;
}
}
注意实体 DummyB 中的 getDummyA 方法是重复的,尝试两种情况加入实体。
案例 1:通过 DummyA 主键映射 DummyB -> DummyA
@ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "dummy_id")
这很好,只执行一个查询来检索 DummyB 对象。
案例 2:通过 DummyA NON 主键(字段名)映射 DummyB -> DummyA
@ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "dummy_name", referencedColumnName="name")
相同的 dummyB 选择被执行,但紧接着,一个 dummyA 选择被执行过滤 name=?获取相关的 A 对象。
我正在使用一个非常简单的 jUnit 来执行过滤:
public class DummyTest {
@Autowired
HibernateTransactionManager transactionManager;
@Test
@Transactional
public void testFindDummyB() throws DAOException {
Long idDummyB = 2L;
Session session = getCurrentHibernateSession();
List lst = session.createCriteria(DummyB.class)
.add(Restrictions.eq("id", idDummyB)).list();
assertTrue(lst.size() > 0);
}
private Session getCurrentHibernateSession() {
return this.transactionManager.getSessionFactory().getCurrentSession();
}
}
我的图书馆:
- org.hibernate:hibernate-core:jar:4.2.17.Final:compile
- org.hibernate.common:hibernate-commons-annotations:jar:4.0.2.Final:compile
- org.hibernate.javax.persistence:hibernate-jpa-2.0-api:jar:1.0.1.Final:compile
- org.hibernate:hibernate-validator:jar:4.3.2.Final:provided
我已经尝试过的其他事情:
-
将 hiberante 的 @LazyToOne 添加到 getDummyA() 方法没有任何效果。
@LazyToOne(LazyToOneOption.PROXY) @ManyToOne(fetch = FetchType.LAZY, optional = true) @JoinColumn(name = "dummy_name", referencedColumnName = "name") @LazyToOne(LazyToOneOption.PROXY)
创建从 DummyB 表到 dummyA 的外键(以及 dummy.name 字段中的唯一约束)无效。
- 在 DummyA getName() 方法上添加 @Column(unique = true) 没有成功。
- 按照建议设置 optional=true 或 false here 也无效。
-
尝试使用条件中的 setFetchMode 强制延迟加载无效,DummyA select 继续执行。
List lst = session.createCriteria(DummyB.class) .add(Restrictions.eq("id", idDummyB)).setFetchMode("dummyA", FetchMode.SELECT) .list() ;
我在 Hibernate 的文档中找不到引用此行为的点,所以我想知道我的注释中是否有任何问题,或者我遇到了 Hibernate 错误。
谁能告诉我?
由 md-dev 请求更新: 设置得更清楚:
这是预期的行为还是错误?如果这是预期的行为,它记录在哪里?
谢谢。
【问题讨论】: