Отображение одного и того же JPA-объекта на другой JPA-объект несколько раз - PullRequest
0 голосов
/ 08 сентября 2018

Я хочу сопоставить пользователя с отношением через first_user и second_user, чтобы я мог отслеживать их статусы отношений. Там может быть лучший подход, и я с удовольствием рассмотрю любые полезные предложения.

Основная проблема возникает, когда я пытаюсь упорствовать. Сторона "отношений" отношений, кажется, работает просто отлично, когда я проверяю базу данных, но таблица user_relationship не работает.

Итак, вопрос в основном, почему не сохраняется сохранение отношений в работе пользователя?

Редактировать: Я видел пост, дублирование которого было предложено. В принятом ответе Sym-sym указывает на исправление отношений и приводит примеры. Я рассмотрел примеры, но единственное отличие, которое я вижу на стороне OneToMany отношений, - это атрибут mappedBy. Я не совсем уверен, какой из них сопоставить, так как у нас есть два ManyToOne на другой стороне отношений. Будем ли мы отображать карту по FirstParty или, возможно, по SecondParty, и что будет с другой?

Вот что я получил до сих пор:

@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
)

Это класс отношений:

@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()))

Это последовательно дает мне это, когда я пытаюсь сохранить пользователя со связями:

    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

1 Ответ

0 голосов
/ 10 сентября 2018

Если кто-нибудь окажется в той же ситуации, что и я: не пытайтесь использовать этот подход. Насколько показывают мои испытания, невозможно создать двунаправленную связь между two @ManyToOne в одной сущности и просто one @OneToMany в другой сущности.

Два решения, найденные для нашего конкретного случая, либо:

  • Сопоставьте два отдельных поля в каждом объектов друг с другом. Не одно поле в одном объекте, а два поля в другом объекте.
  • Или сопоставьте объекты с одним полем @ManyToMany и найдите другой способ определить, кому принадлежит какой статус (например, самый большой идентификатор или что-то в этом роде)

Я использовал эту ссылку, чтобы получить правильные отношения @OneToMany

...