Abh*_*L L 3 spring jpa lazy-loading exception spring-transactions
我想对延迟加载和会话边界等做一些澄清.
我的代码结构如下
@Entity
class A {
....
@OneToOne(fetch=LAZY)
private B b;
..
}
@Entity
class B {
private id;
private name;
}
@Transactional(SUPPORTS)
ADao {
A findById(int id);
}
@Transactional(SUPPORTS)
LayerDB {
A getAForId(int i) {
return adao.findById(i);
}
}
//Note that there is no transactional attribute here
LayerB {
public boolean doSomethingWithAandB(int aId) {
A a = LayerDB.getAForId(aId);
if(a.getB().getName().equals("HIGH"))
return true;
return false;
}
}
//start transaction here
@Transaction(REQUIRED)
LayerC {
LayerB layerb;
private handleRequest(int id) {
layerb.doSomethingWithAandB(id);
}
}
Run Code Online (Sandbox Code Playgroud)
现在,当我们尝试在方法中访问实体A中的B.
doSomethingWithAandB
Run Code Online (Sandbox Code Playgroud)
尝试访问B时出现延迟初始化异常
即使该方法在LayerC中创建的事务中,仍然会出现以下异常
Exception : org.hibernate.LazyInitializationException: could not initialize proxy - no Session
Run Code Online (Sandbox Code Playgroud)
但是在改变以下两种方法时:
@Transactional(SUPPORTS)
LayerDB {
A getAForId(int i) {
A a = adao.findById(i);
a.getB().getName();
return a;
}
}
//Note that there is no transactional attribute here
LayerB {
public boolean doSomethingWithAandB(int aId) {
A a = LayerDB.getAForId(aId);
if(a.getB().getName().equals("HIGH"))
return true;
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
为什么不使用在LayerC中创建的事务/会话?
即使我们在DBLayer上有SUPPORTS,它是否会创建一个单独的"会话".
任何正确理解的指针都会对我有所帮助.
谢谢.
wal*_*orn 19
使用延迟加载时,当您请求A类型的对象时,您将获得A类型的对象a.a.getB()但是,不会是B类型,而是B a.getB()的代理,以后可以解析(这是延迟加载部分) ),但仅限于生活在其中的持久性环境中.
你的第二个实现了这一点:它通过调用解决乙a.getB().getName(),而你却还在@Transaction.Hibernate现在可以向数据库发出第二个请求以获取B,现在a.getB()实际上是B类并保持这种状态,因此您可以在持久化上下文之外使用它.
你的第一个实现会跳过它.从数据库中获取A,@Transactional块结束,然后调用a.getB().getName(),但现在持久化上下文消失,a.getB()无法从数据库中获取,并抛出异常.
| 归档时间: |
|
| 查看次数: |
18333 次 |
| 最近记录: |