关于分离实体的问题总是有很多问题!
首先,它们经常导致LazyInitializationExceptionHibernate.是的,有另一个持久性提供程序,它们不会抛出异常,但我认为它们在一致性方面存在一些问题.考虑一下我们有A和B实体有reference(@ManyToOne)A从而B需要非空.
我们开始了会话,加载了A实例,然后关闭了会话.之后我们尝试获取参考B.并假设另一个事务刚刚删除了我们A和B实例.所以当我们从数据库查询时,我们找不到合适的B实例并得到null!
所以我们的合同被违反了.一些依赖于a.getB()返回对象的事实的代码
将抛出一个NullPointerException.对于持久化实体,这是不可能的,因为我们在获取对象本身的同一事务中具有所有延迟加载,因此所有操作都是原子的(如果我们当然有正确的事务隔离).
当您想要将持久性和分离的实体存储在一个实体中时,也会出现问题Set.这这种情况下,你应该总是覆盖equals和hashCode,通常看起来很笨拙,因为我看不到一个很好的办法做到这一点.
要让一个独立的实体回到EntityManager你身边应该使用merge哪个是毛躁的.
所以我的问题是:是否存在真正需要分离实体的合理方案?此外,何时需要混合分离的和持久的实体并将分离的实体合并为一个新的EntityManager?
使用标准JPA注释时,您可以FetchType.LAZY在非集合字段(即@ManyToOne和@OneToOne)上指定.在这种情况下,似乎Hibernate内部使用"代理"提取.但代理提取有其继承问题,我认为最好将无代理提取与字节码检测结合使用.不幸的是,Hibernate仍然要求你在hbm-file中指定"no-proxy" 或者使用特定于Hibernate的@LazyToOne注释.
我的问题是:Hibernate是否支持配置选项,对所有非收集字段使用无代理提取策略,这是FetchType.LAZY什么?
以下是我需要的内容:一方面,我想在大多数情况下只使用JPA注释.另一方面,我想避免继承和惰性字段的问题.我不喜欢在接口中包装所有内容的想法,因为我在当前项目中使用DDD,所以我认为我的域模型中不存在样板垃圾,只有纯业务逻辑.
我有一个不好的解决方法的想法:通过使用字节码修改,我添加@LazyToOne注释到处@ManyToOne出现.但我更喜欢内置的Hibernate功能,如果存在的话.
这是(众所周知的)代理提取的问题,以使事情更清楚:
@Entity @DiscriminatorColumn("t") @DiscriminatorValue("")
public abstract class A {
@Id private Integer id;
}
@Entity @DiscriminatorValue("B")
public abstract class B extends A {
}
@Entity @DiscriminatorValue("C")
public abstract class C extends A {
}
@Entity public class D {
@Id private Integer id;
@ManyToOne(fetch = FetchType.LAZY) private A a;
public A getA() {
return a;
}
}
Run Code Online (Sandbox Code Playgroud)
准备:
D …Run Code Online (Sandbox Code Playgroud) 我使用远程调试协议为Google Chrome编写自定义调试器.我的调试器工作正常,除了它无法访问功能范围.我监听Debugger.paused事件和监听器得到的数组CallFrame.我closure从每个帧获得范围,因此我可以获得所有绑定变量及其属性.这些变量中有一些功能.我Runtime.getProperties将其中一个功能的ID 发布到Chrome并获取其属性.以下是我的回应:
{
"result":[
{
"configurable":false, "enumerable":false,
"isOwn":true, "name":"length",
"value":{
"description":"0",
"type":"number",
"value":0
},
"writable":false
}, {
"configurable":false, "enumerable":false,
"isOwn":true, "name":"name",
"value":{
"type":"string",
"value":""
},
"writable":false
}, {
"configurable":false, "enumerable":false,
"get":{
"className":"Function",
"description":"function ThrowTypeError() { [native code] }",
"objectId":"{\"injectedScriptId\":3,\"id\":34}",
"type":"function"
},
"isOwn":true,"name":"arguments",
"set":{
"className":"Function",
"description":"function ThrowTypeError() { [native code] }",
"objectId":"{\"injectedScriptId\":3,\"id\":35}",
"type":"function"
}
}, {
"configurable":false, "enumerable":false,
"get":{
"className":"Function",
"description":"function ThrowTypeError() { [native code] }",
"objectId":"{\"injectedScriptId\":3,\"id\":36}",
"type":"function"
},
"isOwn":true, …Run Code Online (Sandbox Code Playgroud)