I set up two datasources in Spring Boot. In a controller I want to persist a couple of parent-child entities on both. They're almost identical bidirectional relationships, but the first one works, while the second emits a committing message but doesn't actually persist the child entity. Entities from working datasource
@Entity
public class Brand {
private Integer id;
private Set<Line> lines = new HashSet<Line>();
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@JsonIgnore
public Integer getId() {
return id;
}
@JsonIgnore
@OneToMany(mappedBy = "brand", cascade = CascadeType.ALL, orphanRemoval = true)
public Set<Line> getLines() {
return lines;
}
@Entity
public class Line {
private Integer id;
private Brand brand;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
public Integer getId() {
return id;
}
@ManyToOne
@JoinColumn(name = "brand")
public Brand getBrand() {
return brand;
}
while this ones are from second datasource, that persists the parent but not the child
@Entity
public class User {
private String id;
private List<UserCommit> userCommitList = new ArrayList<UserCommit>();
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
public Integer getId() {
return id;
}
}
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
public List<UserCommit> getUserCommitList() {
return userCommitList;
}
@Entity
public class UserCommit {
private Integer id;
private User user;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
public Integer getId() {
return id;
}
@ManyToOne
@JoinColumn(name = "user")
public User getUser() {
return user;
}
This is the the interesting part of the controller
Brand brand = brandService.createFrom(fsDto.getBrand());
Line line = lineService.createFrom(fsDto.getLine(), brand);
AccessToken accToken = token.getAccount().getKeycloakSecurityContext().getToken();
try {
prodService.updateFrom(id, line, fsDto);
User user = userService.createFrom(accToken);
ucService.createFrom(user, id, "EDIT", "FIRST");
And these are the service methods
public Brand createFrom(String name) {
Brand foundBrand = findByName(name);
Brand brand = new Brand();
if (foundBrand == null) {
brand = brandRepo.save(brand);
brand.setName(name);
} else
brand = foundBrand;
return brand;
public Line createFrom(String name, Brand brand) {
Line foundLine = findByNameAndBrand(name, brand);
Line line = new Line();
if (foundLine == null) {
line.setName(name);
line.setBrand(brand);
line.getBrand().addLine(line);
} else
line = foundLine;
return line;
}
public User createFrom(AccessToken accToken) {
User user = findByKcId(accToken.getSubject());
if(user == null) {
user = new User();
user.setKcId(accToken.getSubject());
user.setName(accToken.getPreferredUsername());
userRepo.save(user);
}
return user;
}
public UserCommit createFrom(User user, Integer prodId, String ucType, String stage) {
UserCommit uc = new UserCommit();
uc.setUser(user);
uc.getUser().addUserCommit(uc);
uc.setProdId(prodId);
uc.setUCType(UserCommit.UCType.valueOf(ucType));
uc.setStage(UserCommit.Stage.valueOf(stage));
uc.setTime(LocalDateTime.now());
return uc;
}
- Brand gets persisted.
- Line gets Persisted.
- User gets persisted.
- UserCommit DON'T get persisted.
- Everything works if I explicitly call UserCommitService.save(), but I think it shouldn't be needed.
EDIT I updated my code to make the two couples of transactions even more similar, and now for the second one I got this classic error on lazy initialization.
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: petmenu.entities.users.User.userCommitList, could not initialize proxy - no Session
What really drives me mad, is that Brand→Line works, while User→UserCommit doesn't. Even tracing JPA I cannot understand why User entity is not included in the session at UserCommit commiting.
2020-05-26 16:51:54.258 DEBUG 78269 --- [http-nio-192.168.1.10-8080-exec-2] o.s.orm.jpa.JpaTransactionManager : Found thread-bound EntityManager [SessionImpl(1767213597<open>)] for JPA transaction
2020-05-26 16:51:54.258 DEBUG 78269 --- [http-nio-192.168.1.10-8080-exec-2] o.s.orm.jpa.JpaTransactionManager : Creating new transaction with name [petmenu.services.users.UserService.createFrom]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2020-05-26 16:51:54.259 DEBUG 78269 --- [http-nio-192.168.1.10-8080-exec-2] o.s.orm.jpa.JpaTransactionManager : Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@41ca5759]
2020-05-26 16:52:01.687 DEBUG 78269 --- [http-nio-192.168.1.10-8080-exec-2] o.s.orm.jpa.EntityManagerFactoryUtils : Opening JPA EntityManager
2020-05-26 16:52:01.708 DEBUG 78269 --- [http-nio-192.168.1.10-8080-exec-2] org.hibernate.SQL : select user0_.id as id1_0_, user0_.kc_id as kc_id2_0_, user0_.name as name3_0_ from user user0_ where user0_.kc_id=?
2020-05-26 16:52:01.708 TRACE 78269 --- [http-nio-192.168.1.10-8080-exec-2] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [VARCHAR] - [80a3b4b1-00d1-4062-a7e5-1927b938c203]
2020-05-26 16:52:01.709 TRACE 78269 --- [http-nio-192.168.1.10-8080-exec-2] o.h.type.descriptor.sql.BasicExtractor : extracted value ([id1_0_] : [INTEGER]) - [2005]
2020-05-26 16:52:01.709 TRACE 78269 --- [http-nio-192.168.1.10-8080-exec-2] o.h.type.descriptor.sql.BasicExtractor : extracted value ([kc_id2_0_] : [VARCHAR]) - [80a3b4b1-00d1-4062-a7e5-1927b938c203]
2020-05-26 16:52:01.709 TRACE 78269 --- [http-nio-192.168.1.10-8080-exec-2] o.h.type.descriptor.sql.BasicExtractor : extracted value ([name3_0_] : [VARCHAR]) - [user1]
2020-05-26 16:52:01.709 TRACE 78269 --- [http-nio-192.168.1.10-8080-exec-2] o.s.orm.jpa.JpaTransactionManager : Triggering beforeCommit synchronization
2020-05-26 16:52:01.709 TRACE 78269 --- [http-nio-192.168.1.10-8080-exec-2] o.s.orm.jpa.JpaTransactionManager : Triggering beforeCompletion synchronization
2020-05-26 16:52:01.709 DEBUG 78269 --- [http-nio-192.168.1.10-8080-exec-2] o.s.orm.jpa.JpaTransactionManager : Initiating transaction commit
2020-05-26 16:52:01.709 DEBUG 78269 --- [http-nio-192.168.1.10-8080-exec-2] o.s.orm.jpa.JpaTransactionManager : Committing JPA transaction on EntityManager [SessionImpl(1767213597<open>)]
2020-05-26 16:53:06.630 TRACE 78269 --- [http-nio-192.168.1.10-8080-exec-2] o.s.orm.jpa.JpaTransactionManager : Triggering afterCommit synchronization
2020-05-26 16:53:06.671 TRACE 78269 --- [http-nio-192.168.1.10-8080-exec-2] o.s.orm.jpa.JpaTransactionManager : Triggering afterCompletion synchronization
2020-05-26 16:53:06.671 DEBUG 78269 --- [http-nio-192.168.1.10-8080-exec-2] o.s.orm.jpa.JpaTransactionManager : Not closing pre-bound JPA EntityManager after transaction
2020-05-26 16:53:06.671 DEBUG 78269 --- [http-nio-192.168.1.10-8080-exec-2] o.s.orm.jpa.JpaTransactionManager : Found thread-bound EntityManager [SessionImpl(1767213597<open>)] for JPA transaction
2020-05-26 16:53:06.671 DEBUG 78269 --- [http-nio-192.168.1.10-8080-exec-2] o.s.orm.jpa.JpaTransactionManager : Creating new transaction with name [petmenu.services.users.UserCommitService.createFrom]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2020-05-26 16:53:06.671 DEBUG 78269 --- [http-nio-192.168.1.10-8080-exec-2] o.s.orm.jpa.JpaTransactionManager : Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@323b85aa]
2020-05-26 16:53:17.438 TRACE 78269 --- [http-nio-192.168.1.10-8080-exec-2] o.s.orm.jpa.JpaTransactionManager : Triggering beforeCompletion synchronization
2020-05-26 16:53:17.472 DEBUG 78269 --- [http-nio-192.168.1.10-8080-exec-2] o.s.orm.jpa.JpaTransactionManager : Initiating transaction rollback
2020-05-26 16:53:17.472 DEBUG 78269 --- [http-nio-192.168.1.10-8080-exec-2] o.s.orm.jpa.JpaTransactionManager : Rolling back JPA transaction on EntityManager [SessionImpl(1767213597<open>)]
2020-05-26 16:53:17.472 TRACE 78269 --- [http-nio-192.168.1.10-8080-exec-2] o.s.orm.jpa.JpaTransactionManager : Triggering afterCompletion synchronization
2020-05-26 16:53:17.472 DEBUG 78269 --- [http-nio-192.168.1.10-8080-exec-2] o.s.orm.jpa.JpaTransactionManager : Not closing pre-bound JPA EntityManager after transaction
2020-05-26 16:53:17.473 DEBUG 78269 --- [http-nio-192.168.1.10-8080-exec-2] o.j.s.OpenEntityManagerInViewInterceptor : Closing JPA EntityManager in OpenEntityManagerInViewInterceptor
2020-05-26 16:53:17.496 ERROR 78269 --- [http-nio-192.168.1.10-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: petmenu.entities.users.User.userCommitList, could not initialize proxy - no Session] with root cause