Detached entity passed to persist

Hi,

versuche in einem Projekt mit Spring Data JPA folgendes :

UserEntity hat eine GroupEntity, GroupEntity hat viele UserEntities und RoleEntities, RoleEntity besteht aus einem String.

Dazu jeweils ein JpaRepository - das funktioniert alles ohne Probleme. Auch meine Klasse die Beispieldaten erzeugt funktioniert einwandfrei.

Problematisch wird es, wenn ich versuche eine UserEntity über eine Weboberfläche anzulegen und zu persistieren.
Wenn ich einen User anlege der eine GroupEntity hat, bekomme ich folgende Exception :

org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist: eu.shishigami.school.domain.GroupEntity

Die passende GroupEntity wird über ein h:selectOneMenu ausgewählt, das mit allen Gruppen der Datenbank befüllt ist.

Ich habe bereits versucht die Service-Methode mit @Transactional zu annotieren und die GroupEntity nochmal neu aus der Datenbank zu laden :

  // ...
  GroupEntity group = groupService.findOne(addUserView.getUserEntity.getGroup().getId());
  addUserView.getUserEntity().setGroup(group);
  userService.save(addUserView.getUserEntity());
}

Leider hat das überhaupt nichts gebracht. Was mache ich falsch? Da es recht viel Code ist habe ich hier ein Gist hochgeladen :

Vielen Dank für jegliche Hilfe.

Auch wenn sie sich so anfühlen, Entities sind eben nicht nur POJOs. Sie haben einen Life-Cycle. Du lädst Sie ja mit einem EntityManager (bei Hibernate Session). Solange der EntityManager noch lebt, ist die Entity an diesem attached. Du kannst sie über diesen wieder persistieren. Wenn der EntityManager entsorgt ist, ist die Entity detached. Du kannst sie so nicht mehr persisiteren. Der Grund ist, dass jemand anderes mit einem anderen EntityManager Änderungen vorgenommen haben könnte, die Deine Entities nicht mitbekommen haben (denn ihr EntityManager existiert ja nicht mehr). Würdest Du sie einfach so persistieren, könnte das zu Inkonsistenzen führen. Eine ausührliche und gute Erklärung sowie Lösungsmöglichkeiten findest Du hier: http://blog.xebia.com/2009/03/23/jpa-implementation-patterns-saving-detached-entities/

Hi,

danke für deine Antwort. Ein Grund für mich Spring Data einzusetzen war es, dass ich mich nicht selbst mit dem Entity Manager herumschlagen muss - zumindest hatte ich bisher den Eindruck, dass sich die Implementierung des JpaRepository von Spring darum kümmert : https://github.com/spring-projects/spring-data-jpa/blob/master/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java

Gibt es für Spring keine andere Lösung?

Hi,

durch das einschränken der Kaskadierung (CascadeType.ALL --> { CascadeType.MERGE, CascadeType.REFRESH }) funktioniert jetzt alles wie gewollt. Folgendes ist nun zwar nichtmehr möglich, allerdings denke ich dass ich dann auch einfach vorher nochmal persistieren kann :

	testGroup.setGroupName("TestGroup");
	testGroup.setRoles(roleService.findAll());
		
	UserEntity testUser = new UserEntity();
	testUser.setUsername("test");
	testUser.setPassword(new BCryptPasswordEncoder().encode("123qwe"));
	testUser.setFirstName("FirstName");
	testUser.setLastName("LastName");
	testUser.setEmail("bla@shishigami.eu");
	testUser.setEnabled(true);
	testUser.setGroup(testGroup);
		
	testUser = userService.save(testUser);