0

これぞパズル!:D

最初にエンティティ全体をロードせずに、Hibernate にエンティティのコレクションを強制的にロードさせる方法はありますか?

もっとよく説明しましょう。このように注釈が付けられた Role エンティティがあります。

@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 のサブクラスの 1 つでラップします。その後、Hibernate.initialize(permissions); を使用できます。コレクションを強制的に初期化します。

ただし、必要なのは、最初に役割エンティティをロードせずに同じことを達成する方法です。アクセス許可コレクションが必要なエンティティの ID と、コレクションの役割 (temp.pack.Role.permissions) を知っています。

それを行う方法はありますか?コレクションを取得してそれらをすべて破棄するためだけに、Role オブジェクトのすべてのフィールド (多数!) を取得するためにデータベースにアクセスすることは避けたいと思います。

結合を使用することもできますが、これにより、必要な実際の 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);

しかし、また失敗しますjava.lang.IllegalArgumentException: unknown handler key

これを達成する方法についてのアイデアはありますか?

4

1 に答える 1

1

まあ、物事を複雑にして、プロパティの遅延フェッチを使用することもできます(これにはバイトコードの計測が必要です)。しかし、ドキュメントを引用させてください:

19.1.7. 遅延プロパティ フェッチの使用

Hibernate3 は、個々のプロパティの遅延フェッチをサポートしています。この最適化手法は、フェッチ グループとも呼ばれます。これは主にマーケティング機能であることに注意してください。行の読み取りの最適化は、列の読み取りの最適化よりもはるかに重要です。ただし、クラスの一部のプロパティをロードするだけでも、極端な場合に役立ちます。たとえば、従来のテーブルに数百の列があり、データ モデルを改善できない場合などです。

したがって、この道をたどる前に、これらのプロパティの読み込みが実際に重要であることをまず確認します。

于 2010-10-31T11:58:02.967 に答える