Ebean: Cascade with OneToOne – tries inserts instead of update
Asked Answered
E

0

4

I'm using Scala with Ebean, and I've run into some serious trouble. The situation is quite simple, I have a parent entity:

@Entity
case class Person(@(PrivateOwned@field)
                 @(OneToOne@field)(fetch = FetchType.LAZY, cascade = Array(CascadeType.ALL), orphanRemoval = true)
                 @(JoinColumn@field)(name = "website_setting_id")
                 websiteSetting: WebsiteSetting,
                 @(Id@field)id: Long = 0) extends Model

where WebsiteSetting is:

@Entity
case class WebsiteSetting(@(Column@field)(unique = true) domain: String,
                          planId: Long,
                          @(Id@field) id: Long = 0) extends Model

What I'm seeing is that when I do something like:

val ws = WebsiteSetting("somedomain.com", 1)
val p = Person(ws)
p.save() // works as expected

But the following fails,

val updated = p.copy(websiteSetting = p.websiteSetting.copy(planId = 2))
updated.update()

with:

    javax.persistence.PersistenceException: ERROR executing DML bindLog[] 
error[Duplicate entry '167' for key 'PRIMARY']

Which clearly means that Ebean doesn't know that the child entity needs an update and tries to do an insert with it, disregarding the id field, which equals 167.

Whats the best way to avoid this problem?

Edit: Ebean plugin version: https://www.playframework.com/documentation/2.3.6/api/java/play/db/ebean/package-summary.html (I've used the ebean plugin that was shipped with Play 2.3.6)

Exception: The exception arises when Ebean tries to do an insert of an instance with an existing ID. I've seen from the SQL logs that the statement Ebean tries to execute on the server is an insert with id = 167, which is an existing row on the table. This results in the exception.

Eleemosynary answered 29/4, 2016 at 15:47 Comment(5)
Your description does not state the version of Ebean used. You could also include the SQL log (as that would show the behavior and confirm you are not misinterpreting an exception).Sperrylite
@RobBygrave I've edited the question.Eleemosynary
That is not the version of Ebean itself though. The point of the SQL log is that it should include all the statements starting from the original update. That is, you ought to be seeing a series of SQL statements due to the original update followed by cascade etc ... and you are not showing any of that.Sperrylite
I confirm the problem the OP has - I have exactly the same struggle. The SQL log doesn't say much - it is simply stating what the OP suggests, meaning that an INSERT INTO statement is done, regardless of the ID being present, instead of an UPDATE statement. I could fix this issue for ONE child of mine by adding an ID column to the model (which otherwise is inherited by AbstractModel), but the same fix fails for another child. But this shouldn't be the problem of the OP, since he has his ID specified. Totally stuck on this.Apologia
@Apologia following this and the general idea of ORM's, we've moved away from Ebean and we're in the process of dropping it from production. Since we're a Scala shop, things like Anorm or Slick make much more sense.Eleemosynary

© 2022 - 2024 — McMap. All rights reserved.