LINUX.ORG.RU

LazyInitializationException при FetchType.EAGER

 ,


0

1

Господа, что это за хрень с хибернейтом:

	@ManyToMany(fetch = FetchType.EAGER, targetEntity = Role.class)
	@JoinTable(
		name = "users_roles",
		joinColumns = {@JoinColumn(name = "user_id")},
		inverseJoinColumns = {@JoinColumn(name = "role_id")}
	)
	public Set<Role> getRoles() {
		return roles;
	}
			beginTransaction();
			user = (User) session.
				createCriteria(User.class).
				add(Restrictions.eq("login", action.getLogin())).
				add(Restrictions.eq("password", action.getPassword())).
				uniqueResult();
			session.flush();
			commit();
			if (user instanceof User) {
				doSmth(user);
			}

Вот на doSmth(user) идет итерирование по вышеуказанной коллекции, где, собственно, происходит:

Caused by: org.hibernate.LazyInitializationException: failed to lazily initialize a collection, no session or session was closed
	at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:383)
	at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:375)
	at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:368)
	at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:111)
	at org.hibernate.collection.PersistentSet.iterator(PersistentSet.java:186)

Что еще за хрень? Гугли молчат, а то, что дают - для FetchType.LAZY.

Испробовано: Hibernate 3.2, 3.3, 3.6. Четверку и пятерку еще не пробовал.

Ответ на: комментарий от vertexua

Удваиваю, manyToMany подразумевает симметричное отношение A<->B, вот в последнем вполне может быть FetchType.LAZY

lester_dev ★★★★★
()
Ответ на: комментарий от vertexua

в Role у меня обратного отношения не настроено. Там Role - это что-то типа placeholder, который маппится в java enum (так проще управлять ролями - определил в коде новую роль, она в Grid отобразилась и при необходимости автоматом в базе создалась).

GateKeeper ★★
() автор топика
Ответ на: комментарий от GateKeeper

А не проще непосредственно использовать enum мапнутым в виде строки? Тогда будет не ManyToMany что есть гут

vertexua ★★★★★
()
Ответ на: комментарий от GateKeeper

Грубо говоря, там происходит так:

		boolean canLogin = false;
		for (Role role: user.getRoles()) {
			if (role.getName().equals(RolesEnum.LOGIN.name())) {
				canLogin = true;
				break;
			}
		}

или так:

	public static void validateLoggedInUser(RolesEnum[] roles, Provider<HttpSession> provider) throws ActionException {
		HttpSession session = provider.get();
		for (RolesEnum requiredRole: roles) {
			boolean found = false;
			if (session.getAttribute("user") == null) {
				throw new InsufficientPermissionsError("Недостаточно полномочий: для действия требуется роль " + requiredRole.name());
			}
			for (Role role: ((User) session.getAttribute("user")).getRoles()) {
				if (role.getName().equals(requiredRole.name())) {
					found = true;
					break;
				}
			}
			if ( ! found) {
				if (requiredRole.equals(RolesEnum.LOGIN)) {
					session.invalidate();
				}
				throw new InsufficientPermissionsError("Недостаточно полномочий: для действия требуется роль " + requiredRole.name());
			}
		}
	}

INB4: i18n, это еще впереди.

GateKeeper ★★
() автор топика
Ответ на: комментарий от vertexua

Дело в том, что какая разница, в остальных моделях таких отношений, и OneToMany, и ManyToMany и ManyToOne дофигища. Не будет здесь - будет там такая же беда. Хотелось бы просто разобраться, какого хрена Hibernate жадный маппинг коллекции не грузит как надо. При этом:

Hibernate: select this_.id as id1_1_, this_.email as email1_1_, this_.login as login1_1_, this_.name as name1_1_, this_.password as password1_1_, roles2_.user_id as user1_1_3_, role3_.id as role2_3_, role3_.id as id14_0_, role3_.description as descript2_14_0_, role3_.name as name14_0_ from users this_ left outer join users_roles roles2_ on this_.id=roles2_.user_id left outer join roles role3_ on roles2_.role_id=role3_.id where this_.login=? and this_.password=?

Вот такой вот запрос геренит в случае, как в первом посте.

GateKeeper ★★
() автор топика

Мда... В общем, моя невнимательность. Я понятия не имею, почему ошибка именно в итераторе, но после того, как заметил, что в doSmth(user) создается новый инстанс PresistentSet (по сути там идет отвязка persistent entity от хибернейта, т.е. создается новый экземпляр User, а все отношения в нем рекурсивно заменяются с PersistentSet на HashSet, PersistentList на ArrayList. Где-то проморгал, в новом инстансе создавался опять PersistentSet. После исправления ошибка более не проявлялась.

PS. Да, да, я накостылил dozer/gilead/подобные на коленке для сериализации в GWT async request-response.

GateKeeper ★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.