Rob*_*Rob 60 java hibernate jpa
我想在不加载整个对象的情况下获取一对一关系的id.我以为我可以使用延迟加载执行此操作,如下所示:
class Foo {
@OneToOne(fetch = FetchType.LAZY, optional = false)
private Bar bar;
}
Foo f = session.get(Foo.class, fooId); // Hibernate fetches Foo
f.getBar(); // Hibernate fetches full Bar object
f.getBar().getId(); // No further fetch, returns id
Run Code Online (Sandbox Code Playgroud)
我希望f.getBar()不会触发另一个提取.我希望hibernate给我一个代理对象,允许我调用.getId()而不实际获取Bar对象.
我究竟做错了什么?
Art*_*ald 38
使用属性访问策略
代替
@OneToOne(fetch=FetchType.LAZY, optional=false)
private Bar bar;
Run Code Online (Sandbox Code Playgroud)
使用
private Bar bar;
@OneToOne(fetch=FetchType.LAZY, optional=false)
public Bar getBar() {
return this.bar;
}
Run Code Online (Sandbox Code Playgroud)
现在它工作正常!
如果您调用任何不是标识符getter方法的方法,则会初始化代理.但它在使用属性访问策略时才有效.记在心上.
xme*_*eko 28
只是添加到Arthur Ronald FD Garcia'post:您可以通过@Access(AccessType.PROPERTY)
(或弃用@AccessType("property")
)强制访问属性,请参阅http://256stuff.com/gray/docs/misc/hibernate_lazy_field_access_annotations.shtml
另一个解决方案可能是
public static Integer getIdDirect(Entity entity) {
if (entity instanceof HibernateProxy) {
LazyInitializer lazyInitializer = ((HibernateProxy) entity).getHibernateLazyInitializer();
if (lazyInitializer.isUninitialized()) {
return (Integer) lazyInitializer.getIdentifier();
}
}
return entity.getId();
}
Run Code Online (Sandbox Code Playgroud)
适用于分离的实体.
Pau*_*ski 17
不幸的是,接受的答案是错的.其他答案也没有提供最简单或最明确的解决方案.
使用属性访问级别为ID
中的BAR
类.
@Entity
public class Bar {
@Id
@Access(AccessType.PROPERTY)
private Long id;
...
}
Run Code Online (Sandbox Code Playgroud)
就像那简单:)
小智 15
添加@AccessType("属性")
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@AccessType("property")
protected Long id;
Run Code Online (Sandbox Code Playgroud)
Java Persistence with Hibernate Book在"13.1.3 Understanding Proxies"中提到了这一点:
只要您只访问数据库标识符属性,就不需要初始化代理.(请注意,如果使用直接字段访问映射标识符属性,则不会出现这种情况; Hibernate甚至不知道getId()方法是否存在.如果调用它,则必须初始化代理.)
但是,基于此页面中的@xmedeko答案,我开发了一个hack,以避免在使用直接字段访问策略时初始化代理.只需改变getId()
如下所示的方法即可.
代替:
public long getId() { return id; }
Run Code Online (Sandbox Code Playgroud)
使用:
public final long getId() {
if (this instanceof HibernateProxy) {
return (long)((HibernateProxy)this).getHibernateLazyInitializer().getIdentifier();
}
else { return id; }
}
Run Code Online (Sandbox Code Playgroud)
这里的想法是将getId()
方法标记为final
,以便代理不能覆盖它.然后,调用该方法不能运行任何代理代码,因此无法初始化代理.该方法本身检查其实例是否是代理,并在这种情况下从代理返回id.如果实例是真实对象,则返回id.
归档时间: |
|
查看次数: |
31173 次 |
最近记录: |