代码之家  ›  专栏  ›  技术社区  ›  Edy Bourne

在Hibernate中有没有一种方法可以在不首先加载整个实体对象的情况下获取实体加载的PersistentCollection?

  •  0
  • Edy Bourne  · 技术社区  · 15 年前

    有没有一种方法可以强制Hibernate在不首先加载整个实体的情况下加载实体的集合?

    让我解释清楚。我有一个这样注释的角色实体:

    @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>();
    
    ...
    
    }
    

    当我通过执行以下操作访问权限集合时:

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

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

    然而,我需要的是一种不必首先加载角色实体即可完成相同任务的方法。我知道我需要权限集合的实体的id,以及集合的角色(temp.pack.Role.permissions)。

    有办法吗?我希望避免点击数据库来检索角色对象的所有字段(很多!),只是为了获取集合并丢弃它们。

    我可以使用连接,但这使我能够访问权限对象本身,而不是我需要的实际PersistentCollection包装器。

    我试过这个:

    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);
    

    但是没有起作用。我得到的集合只是一个常规的空集,没有加载任何内容。

    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 .

    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);
    

    但也不符合

    关于如何实现这一点有什么想法吗?

    1 回复  |  直到 15 年前
        1
  •  1
  •   Pascal Thivent    15 年前

    好吧,你可以把事情复杂化,使用 lazy fetching of properties

    19.1.7. Using lazy property fetching

    Hibernate3支持延迟抓取 优化技术也是众所周知的 请注意 这主要是一种营销特征; 比柱优化更重要 阅读 类的属性可能很有用 在极端情况下。例如,当 旧表有数百列 数据模型无法改进。

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