0

Let me give you the simplified situation.

Article class

@Entity
@Table(name="article")
data class Article (

    @Id
    var id: String = java.util.UUID.randomUUID().toString(),

    @OneToMany(cascade = [CascadeType.ALL], fetch = FetchType.EAGER)
    var keywords: MutableList<Keyword> = mutableListOf()
)

Keyword class

@Entity
@Table(name="keyword")
data class Keyword(

    @Id
    var id: String = java.util.UUID.randomUUID().toString(),

    var keyword: String = ""
)

This situation automatically generated an extra table named "article_keyword" that is essentially a join table between Article and Keyword. This is all makes sense and works just fine.

The problem

Let's say Article has 10 Keyword objects in it's list, this is persisted. This Article is fetched again and one Keyword is removed and the object is saved it tells me this:

Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails

It says it specifically on the generated article_keyword table concerning Article_id in that table. It tries to update the article_keyword join table but can't delete any relation as it has a foreign key constraint to the Article object itself. It makes sense. Yet, I don't know how to solve it.

I've tried numerous things, like adding the @JoinTable specification that Hibernate has generated. Adding orphanRemoval and many other things. Without result.

note: I've tried the queries that Hibernate executes in mysql myself, they work fine, that might be a hint??


Update: The saga continues As it happens with posting your issue on Stackoverflow, I've resolved it to a certain extent.

In order to work around it for now, as I had to have it working right now, I turned off foreign_key_checks just for one operation. After turning it on again to debug some more, no more issues. I made absolutely sure that foreign_key_checks are on again and they are.

The one thing that has changed is that no longer there is a foreign_key on the column Article_id of the table article_keyword. Is this just some Hibernate magic or am I missing something?

I've been trying this for the entire day thus far. The issue has been resolved, but I would still like to understand this behaviour.

JamesENL
  • 6,400
  • 6
  • 39
  • 64
Sjenkie
  • 207
  • 2
  • 3
  • 14
  • Well based on your update, I'd say you're no longer getting a foreign key constraint because the join table no longer has article_id marked as a foreign key. This probably isn't desirable behaviour. – JamesENL Nov 26 '19 at 03:43

1 Answers1

1

Based on your code, I can see two potential solutions going forward. You could make the current relationship a bi-directional link, or you could start explicitly managing the join table. I've not worked in Kotlin before, so I'm translating this from a Java context, so you might need to translate my examples back.

Bi-Directional One to Many Relationship

@Entity
@Table(name="article")
data class Article (

    @Id
    var articleId: String = java.util.UUID.randomUUID().toString(),

    @OneToMany(mappedBy="keyword")
    var keywords: MutableList<Keyword> = mutableListOf()
)

@Entity
@Table(name="keyword")
data class Keyword(

    @Id
    var keywordId: String = java.util.UUID.randomUUID().toString(),

    @ManyToOne
    @JoinColumn(name="articleId")
    var article: Article

    var keyword: String = ""
)

OR

Uni-directional with explicit join table management

@Entity
@Table(name="article")
data class Article (

    @Id
    var articleId: String = java.util.UUID.randomUUID().toString(),

    @OneToMany
    @JoinTable(name="article_keyword,
           joinColumns = @JoinColumn(name="articleId"),
           inverseJoinColumns = @JoinColumn(name="keywordId"))
    var keywords: MutableList<Keyword> = mutableListOf()
)

@Entity
@Table(name="keyword")
data class Keyword(

    @Id
    var keywordId: String = java.util.UUID.randomUUID().toString(),

    var keyword: String = ""
)

@Entity
@Table(name="article_keyword")
data class articlekeyword(

    var articleKeywordId: String = java.util.UUID.randomUUID().toString(),

    @ManyToOne
    @JoinColumn(name="articleId")
    var article: Article

    @ManyToOne
    @JoinColumn(name="keywordId")
    var keyword: Keyword
)

My only worry might be that if you choose to do a bi-directional link it may have unintended consequences when you delete things, but that's probably something to test out. I adapted these examples from my answer here which you may find useful.

JamesENL
  • 6,400
  • 6
  • 39
  • 64