Есть ли способ в Hibernate получить загруженный объект PersistentCollection без предварительной загрузки всего объекта? - PullRequest
0 голосов
/ 30 октября 2010

Это головоломка! : 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. Затем я могу использовать Hibernate.initialize (permissions); чтобы инициализировать коллекцию.

Однако мне нужен способ выполнить то же самое без предварительной загрузки объекта роли. Я знаю идентификатор объекта, для которого мне нужны коллекции разрешений, и роль для коллекции (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

Есть идеи, как этого добиться?

1 Ответ

1 голос
/ 31 октября 2010

Ну, вы могли бы все усложнить и использовать ленивая выборка свойств (что требует инструментирования байт-кодом).Но позвольте мне процитировать документацию:

19.1.7.Использование отложенной выборки свойств

Hibernate3 поддерживает отложенную выборку отдельных свойств.Этот метод оптимизации также известен как выборочные группы. Обратите внимание, что это в основном маркетинговая функция;оптимизация чтения строк гораздо важнее, чем оптимизация чтения столбцов .Тем не менее, только загрузка некоторых свойств класса может быть полезна в крайних случаях.Например, когда у устаревших таблиц есть сотни столбцов, и модель данных не может быть улучшена.

Поэтому, прежде чем идти по этому пути, я сначала должен убедиться, что загрузка этих свойств действительно вызывает беспокойство.

...