Не сохраняется сущность в базу JPA Hibernate
Всем привет.
В проекте есть сущность Post с полями:
@Entity(name = "Post")
@Table(name = "POST")
public class Post extends IdEntity{
private Long id;
private String message;
private String location;
private Date datePosted;
private User userPosted;
private User userPagePosted;
private Set<User> usersTagged;
public Post() {
}
@Id
@SequenceGenerator(name = "POS_SQ", sequenceName = "POST_SEQ", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "POS_SQ")
@Column(name = "POST_ID")
@Override
public Long getId() {
return id;
}
@Column(name = "MESSAGE", nullable = false)
public String getMessage() {
return message;
}
@Column(name = "LOCATIONS", nullable = false)
public String getLocation() {
return location;
}
@Column(name = "DATE_POSTED", nullable = false)
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy")
public Date getDatePosted() {
return datePosted;
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "ID_USER_POSTED")
public User getUserPosted() {
return userPosted;
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "ID_USER_PAGE_POSTED")
public User getUserPagePosted() {
return userPagePosted;
}
//@JsonIgnore
@ManyToMany(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinTable(name = "POST_USERS1", joinColumns = @JoinColumn(name = "POST_ID"),
inverseJoinColumns = @JoinColumn(name = "USER_ID"))
public Set<User> getUsersTagged() {
return usersTagged;
}
@JsonCreator
public static Post createFromJson(String jsonString){
ObjectMapper objectMapper = new ObjectMapper();
Post post = null;
try {
post = objectMapper.readValue(jsonString, Post.class);
}catch (IOException e){
e.printStackTrace();
}
return post;
}
//setters, equals, hashCode and toString don`t give for brevity
Так же есть сущность User:
@Entity(name = "User")
@Table(name = "USERS1")
public class User extends IdEntity{
private Long id;
private String firstName;
private String lastName;
private String phone;
private String email;
private String password;
private String country;
private String city;
private String age;
private Date dateRegistered;
private Date dateLastActive;
private RelationshipType relationship;
private ReligionType religion;
private String school;
private String university;
private List<Message> messageSent;
private List<Message> messageReceived;
private List<Post> posts;
private Set<Relationship> statuses = new HashSet<>();
public User() {
}
@Id
@SequenceGenerator(name = "USER_SQ", sequenceName = "USERS1_SEQ", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "USER_SQ")
@Column(name = "USER_ID")
@Override
public Long getId() {
return id;
}
@Column(name = "USER_FIRST_NAME", nullable = false)
public String getFirstName() {
return firstName;
}
@Column(name = "USER_LAST_NAME", nullable = false)
public String getLastName() {
return lastName;
}
@Column(name = "PHONE", nullable = false)
public String getPhone() {
return phone;
}
@Column(name = "EMAIL", nullable = false)
public String getEmail(){ return email; }
@Column(name = "PASSWORD_USER")
public String getPassword() {
return password;
}
@Column(name = "COUNTRY", nullable = false)
public String getCountry() {
return country;
}
@Column(name = "CITY", nullable = false)
public String getCity() {
return city;
}
@Column(name = "AGE", nullable = false)
public String getAge() {
return age;
}
@Column(name = "DATE_REGISTERED", nullable = false)
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy")
public Date getDateRegistered() {
return dateRegistered;
}
@Column(name = "DATE_LAST_ACTIVE", nullable = false)
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy")
public Date getDateLastActive() {
return dateLastActive;
}
@Enumerated(EnumType.STRING)
@Column(name = "RELATIONSHIP_TYPE", nullable = false)
public RelationshipType getRelationship() {
return relationship;
}
@Enumerated(EnumType.STRING)
@Column(name = "RELIGION_TYPE", nullable = false)
public ReligionType getReligion() {
return religion;
}
@Column(name = "SCHOOL", nullable = false)
public String getSchool() {
return school;
}
@Column(name = "UNIVERSITY", nullable = false)
public String getUniversity() {
return university;
}
@JsonIgnore
@OneToMany(mappedBy = "userFrom", fetch = FetchType.LAZY, targetEntity = Message.class)
public List<Message> getMessageSent() {
return messageSent;
}
@JsonIgnore
@OneToMany(mappedBy = "userTo", fetch = FetchType.LAZY, targetEntity = Message.class)
public List<Message> getMessageReceived() {
return messageReceived;
}
@JsonIgnore
@OneToMany(mappedBy = "userPosted", fetch = FetchType.LAZY, targetEntity = Post.class)
public List<Post> getPosts() {
return posts;
}
@JsonIgnore
@ManyToMany(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinTable(name = "USERS1_RELATIONSHIP", joinColumns = @JoinColumn(name = "USER_ID"),
inverseJoinColumns = @JoinColumn(name = "RELATION_ID"))
public Set<Relationship> getStatuses() {
return statuses;
}
public void addRelationship(Relationship relationship){
statuses.add(relationship);
relationship.getUsers().add(this);
}
public void removeRelationship(Relationship relationship){
statuses.remove(relationship);
relationship.getUsers().remove(this);
}
@JsonCreator
public static User createFromJson(String jsonString){
ObjectMapper objectMapper = new ObjectMapper();
User user = null;
try {
user = objectMapper.readValue(jsonString, User.class);
}catch (IOException e){
e.printStackTrace();
}
return user;
}
//setters, equals, hashCode and toString don`t give for brevity
Без поля Set<User> usersTagged сущность Post сохраняется в базу без проблем. Но после того, как я нахожу отмеченных в сообщении юзеров, заношу их в список и пытаюсь просетить сущности Post полученный список юзеров
метод createPost:
public void createPost(Post post)throws BadRequestException, InternalServerError{
if (!post.getUserPosted().getId().equals(post.getUserPagePosted().getId())){
checkStatusBetweenUsers(post.getUserPosted().getId(), post.getUserPagePosted().getId());
}
validateMessage(post.getMessage());
Date datePosted = new Date();
post.setDatePosted(datePosted);
if (!findUsersTagged(post.getMessage()).isEmpty()){
post.setUsersTagged(findUsersTagged(post.getMessage()));
}
postDAO.save(post);
}
То получаю ошибку.
Тестирую через Postman. Полный вывод ошибки:
<p><b>Type</b> Exception Report</p>
<p><b>Message</b> Request processing failed; nested exception is javax.persistence.PersistenceException:
org.hibernate.PersistentObjectException: detached entity passed to persist: com.findme.models.User</p>
<p><b>Description</b> The server encountered an unexpected condition that prevented it from fulfilling the request.
</p>
<p><b>Exception</b></p>
<pre>org.springframework.web.util.NestedServletException: Request processing failed; nested exception is javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: com.findme.models.User
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1013)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908)
javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
</pre>
<p><b>Root Cause</b></p>
<pre>javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: com.findme.models.User
org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:149)
org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:157)
org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:164)
org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:813)
org.hibernate.internal.SessionImpl.persist(SessionImpl.java:773)
org.hibernate.jpa.event.internal.core.JpaPersistEventListener$1.cascade(JpaPersistEventListener.java:80)
org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:467)
org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:392)
org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:193)
org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:500)
org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:432)
org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:395)
org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:193)
org.hibernate.engine.internal.Cascade.cascade(Cascade.java:126)
org.hibernate.event.internal.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:445)
org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:281)
org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:182)
org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:125)
org.hibernate.jpa.event.internal.core.JpaPersistEventListener.saveWithGeneratedId(JpaPersistEventListener.java:67)
org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:189)
org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:132)
org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:58)
org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:782)
org.hibernate.internal.SessionImpl.persist(SessionImpl.java:767)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)
org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:308)
com.sun.proxy.$Proxy48.persist(Unknown Source)
com.findme.dao.GeneralDAO.save(GeneralDAO.java:27)
com.findme.dao.GeneralDAO$$FastClassBySpringCGLIB$$bc01b56.invoke(<generated>)
org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:749)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294)
org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
com.findme.dao.PostDAO$$EnhancerBySpringCGLIB$$f9a4ae71.save(<generated>)
com.findme.service.PostService.createPost(PostService.java:41)
com.findme.controller.PostController.addPost(PostController.java:41)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)
org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:189)
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:800)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1038)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908)
javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
</pre>
<p><b>Root Cause</b></p>
<pre>org.hibernate.PersistentObjectException: detached entity passed to persist: com.findme.models.User
org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:124)
org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:806)
org.hibernate.internal.SessionImpl.persist(SessionImpl.java:773)
org.hibernate.jpa.event.internal.core.JpaPersistEventListener$1.cascade(JpaPersistEventListener.java:80)
org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:467)
org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:392)
org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:193)
org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:500)
org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:432)
org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:395)
org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:193)
org.hibernate.engine.internal.Cascade.cascade(Cascade.java:126)
org.hibernate.event.internal.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:445)
org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:281)
org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:182)
org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:125)
org.hibernate.jpa.event.internal.core.JpaPersistEventListener.saveWithGeneratedId(JpaPersistEventListener.java:67)
org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:189)
org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:132)
org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:58)
org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:782)
org.hibernate.internal.SessionImpl.persist(SessionImpl.java:767)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)
org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:308)
com.sun.proxy.$Proxy48.persist(Unknown Source)
com.findme.dao.GeneralDAO.save(GeneralDAO.java:27)
com.findme.dao.GeneralDAO$$FastClassBySpringCGLIB$$bc01b56.invoke(<generated>)
org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:749)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294)
org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
com.findme.dao.PostDAO$$EnhancerBySpringCGLIB$$f9a4ae71.save(<generated>)
com.findme.service.PostService.createPost(PostService.java:41)
com.findme.controller.PostController.addPost(PostController.java:41)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)
org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:189)
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:800)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1038)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908)
javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
</pre>
<p><b>Note</b> The full stack trace of the root cause is available in the server logs.</p>
<hr class="line" />
<h3>Apache Tomcat/9.0.8</h3>
Не могу понять где проблема. Не правильно заданы отношения между сущностями ? Подскажите, что не так делаю.