Reputation: 71
I want to map the User to Relationship, through first_user and second_user, so that I can keep track of their relationship statuses. There might be a better approach and I'll gladly consider any helpful suggestions.
The main problem arrives when i try to persist. The "relationship"-side of the relationship seems to be working just fine when I check the database but the table user_relationship is not working.
So the question is basically why isn't isn't the persisting of relationships in user working?
Edit: I've seen the post which this has been suggested a duplicate of. In the accepted answer Sym-sym points to fixing the relationship and provides examples. I've looked into the examples but the only difference I see on the OneToMany-side of the relationship is the mappedBy attribute. I'm not really sure which one to map by since we have two ManyToOne on the other side of the relationship. Would we map by firstParty or perhaps secondParty and what happens to the other one?
This is what I got so far:
@Entity
@Table(name = "user")
data class User(
@Id
@GeneratedValue(generator = "my_user_sequence")
@SequenceGenerator(name = "my_user_sequence", sequenceName = "user_sequence", allocationSize = 1)
val id: Long = -1,
@JsonIgnore
@OneToOne(mappedBy = "user", cascade = [CascadeType.ALL], optional = false)
var preferences: Preferences? = null,
@OneToMany(cascade = [CascadeType.ALL])
var relationships: MutableSet<Relationship> = mutableSetOf(),
@Column(name = "facebook_id")
var fbId: String = "",
var email: String? = null,
var registrationToken: String = "",
var birthday: LocalDate? = null,
val created: LocalDateTime = LocalDateTime.now(Clock.systemUTC()),
@Column(name = "phone_number")
var phoneNumber: String = "",
var password: String? = null,
@Column(name = "first_name")
var firstName: String? = null,
@Column(name = "show_location")
var showLocation: Boolean = true,
@Column(name = "show_age")
var showAge: Boolean = true,
@Column(name = "picture_url")
var pictureUrl: String? = null,
@Column(name = "notify_message")
var notifyMessage: Boolean = true,
@Column(name = "notify_relationships")
var notifyRelationship: Boolean = true
)
This is the relationship class:
@Entity
@Table(name = "relationship")
data class Relationship(
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "joyship_relationship_sequence")
@SequenceGenerator(name = "joyship_relationship_sequence", sequenceName = "relationship_sequence", allocationSize = 1)
val id: Long = -1,
@ManyToOne(cascade = [])
@JoinTable(name = "first_party")
val firstParty: User,
@ManyToOne(cascade = [])
@JoinTable(name = "second_party")
val secondParty: User,
// Id of user is key for relationship_status of user with smaller number on id
@Enumerated(EnumType.STRING)
@Column(name = "first_status")
var firstStatus: RelationshipStatus = NOT_INTRODUCED,
// Id of user is key for relationship_status of user with bigger number on id
@Enumerated(EnumType.STRING)
@Column(name = "second_status")
var secondStatus: RelationshipStatus = NOT_INTRODUCED,
// Changes when relationship_status_1 or *_2 changes
// (Strongest of the statuses dictates common_relationship_status)
@Enumerated(EnumType.STRING)
@Column(name = "common_relationship_status")
var commonRelationshipStatus: RelationshipStatus = NOT_INTRODUCED,
@Column(name = "relative_distance")
var relativeDistance: Int = 160,
@Column
val established: LocalDateTime = LocalDateTime.now(Clock.systemUTC()),
@OneToOne(mappedBy = "relationship", cascade = [CascadeType.ALL], optional = false)
@JoinColumn(name = "last_interaction")
var lastInteraction: Interaction? = null,
@Column
var lastInteractionTime: LocalDateTime = LocalDateTime.now(Clock.systemUTC()))
It consistently gives me this when i try to persist a user with relationships:
javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: co.joyship.server.fraendurheim.models.Relationship
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:149)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:157)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:164)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:814)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:774)
at org.hibernate.jpa.event.internal.core.JpaPersistEventListener$1.cascade(JpaPersistEventListener.java:80)
at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:467)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:392)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:193)
at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:500)
at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:432)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:395)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:193)
at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:126)
at org.hibernate.event.internal.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:445)
at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:281)
at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:182)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:125)
at org.hibernate.jpa.event.internal.core.JpaPersistEventListener.saveWithGeneratedId(JpaPersistEventListener.java:67)
at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:189)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:132)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:58)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:783)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:768)
at org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager.persist(TestEntityManager.java:93)
at co.joyship.server.fraendurheim.RelationshipRepositoryTest.whenRequestingUserRelationshipFromDBReturnCorrectPagination(RelationshipRepositoryTest.kt:64)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:73)
at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:83)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: co.joyship.server.fraendurheim.models.Relationship
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:124)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:807)
... 52 more
Upvotes: 2
Views: 1466
Reputation: 71
If anyone ever finds themselves in the same situation as I was: Don't try this approach. It is not possible, as far as my trials show, to create a bi-directional relationship between two @ManyToOne in one entity and just one @OneToMany in the other entity.
The two solutions found for our specific case so far is either to:
I used this reference to get the @OneToMany relationships correct
Upvotes: 1