Hibernate中有没有一种方法可以在不首先加载整个实体对象的情况下获取实体的加载的PersistentCollection? [英] Is there a way in Hibernate to obtain an entity's loaded PersistentCollection without loading the entire entity object first?

查看:91
本文介绍了Hibernate中有没有一种方法可以在不首先加载整个实体对象的情况下获取实体的加载的PersistentCollection?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个难题! :D

This is a puzzler! :D

是否有一种方法可以强制Hibernate为某个实体加载一个集合而不先加载整个实体?

Is there a way to force Hibernate to load a collection for an entity without loading the entire entity first?

让我解释得更好.我有一个以这种方式注释的角色实体:

Let m explain better. I have a Role entity annotated this way:

@Entity(name="Role")
@Table(name = "ROLES")
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@javax.persistence.TableGenerator(
 name="GENERATED_IDS",
 table="GENERATED_IDS",
    valueColumnName = "ID"
)
public abstract class Role implements Serializable {
 private static final long serialVersionUID = 1L;


 /**
  * The id of this role. Internal use only.
  * 
  * @since 1.0
  */
 @Id @GeneratedValue(strategy = GenerationType.TABLE, generator="GENERATED_IDS")
 @Column(name = "ROLE_ID")
 protected long id;


 /**
  * Set of permissions granted to this role.
  * 
  * @since 1.0
  */
 @OneToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE }, mappedBy="sourceRole")
 protected Set<Permission> permissions = new HashSet<Permission>();

...

}

当我通过以下方式访问权限集合时:

When I access the permissions collection by doing:

Role role = ...
Set permissions = role.getPermission();

Hibernate使用其PersistentCollection的子类之一包装返回的集合.然后,我可以使用Hibernate.initialize(permissions);强制初始化集合.

Hibernate wraps the returned collection with one of its subclasses of PersistentCollection. I can then use Hibernate.initialize(permissions); to force the collection to be initialized.

但是,我需要的是一种无需先加载角色实体即可完成相同操作的方法.我知道我需要权限集合的实体的ID,以及该集合的角色(temp.pack.Role.permissions).

However, what I need is a way to accomplish the same without first loading the role entity. I know the id for the entity I need the permissions collections for, and the Role for the collection (temp.pack.Role.permissions).

有没有办法做到这一点?我希望避免访问数据库来检索Role对象的所有字段(很多!),只是为了获取集合并将其全部丢弃.

Is there a way to do that? I wold like to avoid hitting the database to retrieve all fields of the Role object (many!) just to get the collection and discard them all.

我可以使用联接,但这使我可以访问权限对象本身,而不是我所需的实际PersistentCollection包装器.

I could use a join, but that givens me access to the permission objects themselves, not the actual PersistentCollection wrapper which the one I need.

我尝试过:

Session session = connectionInfoProvider.getSession(); 

// this is just "permissions", the collection field name
String attributeName = role.substring(role.lastIndexOf(".")+1, role.length()); 

// this is the Role class name, temp.pack.Role
String entityClassName = role.substring(0, role.lastIndexOf("."));
Class<?> roleClass = Class.forName(entityClassName);

Field collectionField = roleClass.getDeclaredField(attributeName);
collectionField.setAccessible(true);
Hibernate.initialize(collection);

但是没有用.我得到的集合只是一个常规的空集,什么也没有加载.

But didn't work. The collection I get is just a regular empty set and nothing is loaded.

我也尝试过:

Session session = connectionInfoProvider.getSession();

// this is just "permissions", the collection field name
String attributeName = role.substring(role.lastIndexOf(".")+1, role.length());

// this is the Role class name, temp.pack.Role
String entityClassName = role.substring(0, role.lastIndexOf("."));
Class<?> roleClass = Class.forName(entityClassName);

Field collectionField = roleClass.getDeclaredField(attributeName);
collectionField.setAccessible(true);
Object object = session.load(roleClass, id);
ProxyObject objectProxy = (ProxyObject)object;
LazyInitializer lazyInitializer = (LazyInitializer)objectProxy.getHandler();

Object objectImpl = lazyInitializer.getImplementation();
Object collection = collectionField.get(objectImpl);
Hibernate.initialize(collection);

但是也没有用,它以java.lang.IllegalArgumentException: unknown handler key失败.

But also didn't work, it fails with java.lang.IllegalArgumentException: unknown handler key.

我也尝试过:

PersistenceContext context = ((SessionImplementor)currSession).getPersistenceContext();
CollectionPersister persister = ((SessionFactoryImplementor) sessFactory) .getCollectionPersister(role);
CollectionKey key = new CollectionKey(persister, id, EntityMode.POJO);
// collection - contains set containing actual data
PersistentCollection collection = context.getCollection(key);

但也会失败,并显示java.lang.IllegalArgumentException: unknown handler key

关于如何实现此目标的任何想法?

Any ideas on how to accomplish this?

推荐答案

嗯,您可以使事情变得复杂并使用

Well, you could make things complicated and use lazy fetching of properties (which requires bytecode instrumentation). But let me quote the documentation:

19.1.7.使用懒惰的属性获取

Hibernate3支持延迟获取 个别属性.这 优化技术也是众所周知的 作为获取组. 请注意 这主要是一种营销功能; 优化行读取要多得多 比优化色谱柱重要 读取.但是,仅加载一些 类的属性可能很有用 在极端的情况下.例如,当 旧表有数百列 并且数据模型无法改进.

19.1.7. Using lazy property fetching

Hibernate3 supports the lazy fetching of individual properties. This optimization technique is also known as fetch groups. Please note that this is mostly a marketing feature; optimizing row reads is much more important than optimization of column reads. However, only loading some properties of a class could be useful in extreme cases. For example, when legacy tables have hundreds of columns and the data model cannot be improved.

因此,在走这条路之前,我首先要确保加载这些属性确实是一个问题.

So before to take this path, I would first make sure that loading these properties is really a concern.

这篇关于Hibernate中有没有一种方法可以在不首先加载整个实体对象的情况下获取实体的加载的PersistentCollection?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆