I have a springboot project and I use postgresql and hibernate.
I have several entities, 2 of them are below:
Company Entity:
@Entity
@Table
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder
@Getter
@Setter
public class Company extends BaseDatedEntity {
....... fields
@ManyToMany(
fetch = FetchType.LAZY,
cascade = {CascadeType.PERSIST}
)
@JoinTable(
name = "company_interest",
joinColumns = {@JoinColumn(name = "company_id")},
inverseJoinColumns = {@JoinColumn(name = "interest_id")}
)
private List<Interest> interests = new ArrayList<>();
}
Interest Entity:
@Entity
@Table
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder
@Getter
@Setter
public class Interest extends BaseDatedEntity {
@Column(unique = true)
private String name;
public boolean equals(Interest interest){
return this.name.equals(interest.getName());
}
}
When I post a new company, it also persists interest. This is wanted and expected result. And if I delete the specified company with delete request, my company information is removed from database along with the relations in company_interest join table. In Interest table, interest records are still there, because these are not related with the company itself. This is also expected and ok.
But when I add a new company again with the interest which is already recorded in the database, I get detached entity passed to persist exception.
1- I want to add company even if its interest is already in database, just connect it in join table.
2- If the interest is not in the db, then persist it in the Interest table.
Whole exception log:
14:44:50.427 [http-nio-8081-exec-4] WARN o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver - Resolved [org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist: com.aedesium.domain.entity.company.Interest; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: com.aedesium.domain.entity.company.Interest]
I believe this has a simple solution. But I could not figure it out.
Thanks already.
Seems like you are missing the @Transactional
annotation on your service method where you are dealing with repository actions. since the fetch type is set to lazy, session needs to be open in order for ORM to be aware of the other entities you are trying to access.
All Entities are saved successfully because you have set a Cascade type on the parent entity and so it will 'cascade' that action to all child entities. You are not fetching anything at that moment, so there is no error you are experiencing afterwards.