Anyway there is another problem with unidirectional OneToOne
relationship either. Suppose we have entities e1 and e2. Now if I have
foreign key on e2 and saving e1 - it works fine, but if I save e2 - it
save the data and fails with an error. Please consider this example
(please not Car, Wheel and Tire is solely for example purposes - so some
relations might not make sense):
@Entity
@Table(name="tire")
public class Tire {
@Id @GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
@Version
private int version;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "wheel")
private Wheel wheel;
....
}
@Entity
@Table(name="wheel")
public class Wheel {
@Id @GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
@Version
private int version;
@OneToOne(mappedBy="wheel", cascade = CascadeType.ALL)
private Tire tire;
....
}
Now here is a simple code that creates beans:
Wheel w1 = new Wheel();
Tire t1 = new Tire();
t1.setWheel(w1);
w1.setTire(t1);
Now the success completely depends on which entity you provide to
Ebean.save(): make it Ebean.save(w1); and it's OK; make it
Ebean.save(t1); and you get exception:
javax.persistence.PersistenceException: ERROR executing DML
bindLog[Binding Insert [tire] set[id=121, version=1, wheel=121, ]]
error[ERROR: duplicate key value violates unique constraint "pk_tire"]
at
com.avaje.ebeaninternal.server.persist.dml.DmlBeanPersister.execute(DmlBeanPersister.java:116)
at
com.avaje.ebeaninternal.server.persist.dml.DmlBeanPersister.insert(DmlBeanPersister.java:76)
at
com.avaje.ebeaninternal.server.persist.DefaultPersistExecute.executeInsertBean(DefaultPersistExecute.java:91)
at
com.avaje.ebeaninternal.server.core.PersistRequestBean.executeNow(PersistRequestBean.java:527)
at
com.avaje.ebeaninternal.server.core.PersistRequestBean.executeOrQueue(PersistRequestBean.java:557)
at
com.avaje.ebeaninternal.server.persist.DefaultPersister.insert(DefaultPersister.java:404)
at
com.avaje.ebeaninternal.server.persist.DefaultPersister.saveEnhanced(DefaultPersister.java:345)
at
com.avaje.ebeaninternal.server.persist.DefaultPersister.saveRecurse(DefaultPersister.java:315)
at
com.avaje.ebeaninternal.server.persist.DefaultPersister.save(DefaultPersister.java:282)
at
com.avaje.ebeaninternal.server.core.DefaultServer.save(DefaultServer.java:1577)
at
com.avaje.ebeaninternal.server.core.DefaultServer.save(DefaultServer.java:1567)
at com.avaje.ebean.Ebean.save(Ebean.java:538)
at lt.travelonline.test.CarTest.testCarInsert(CarTest.java:22)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:616)
at
org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at
org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at
org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at
org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at
org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
at
org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:82)
at
org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
at
org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:240)
at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
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:236)
at
org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:180)
at
org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
at
org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: org.postgresql.util.PSQLException: ERROR: duplicate key value
violates unique constraint "pk_tire"
at
org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:1608)
at
org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1343)
at
org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:194)
at
org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:451)
at
org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:350)
at
org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:304)
at
com.jolbox.bonecp.PreparedStatementHandle.executeUpdate(PreparedStatementHandle.java:228)
at
com.avaje.ebeaninternal.server.type.DataBind.executeUpdate(DataBind.java:74)
at
com.avaje.ebeaninternal.server.persist.dml.InsertHandler.execute(InsertHandler.java:155)
at
com.avaje.ebeaninternal.server.persist.dml.DmlBeanPersister.execute(DmlBeanPersister.java:105)
... 40 more
The transaction log:
txn[1001], 19:27:37.932, insert into wheel (id, version) values (?,?)
txn[1001], 19:27:37.932, Binding Insert [wheel] set[id=141, version=1, ]
txn[1001], 19:27:37.936, Inserted [Wheel] [141]
txn[1001], 19:27:37.937, insert into tire (id, version, wheel) values
(?,?,?)
txn[1001], 19:27:37.937, Binding Insert [tire] set[id=141, version=1,
wheel=141, ]
txn[1001], 19:27:37.939, Inserted [Tire] [141]
txn[1001], 19:27:37.939, insert into tire (id, version, wheel) values
(?,?,?)
txn[1001], 19:27:37.939, Binding Insert [tire] set[id=141, version=1,
wheel=141, ]
txn[1001], 19:27:37.942, ERROR executing DML bindLog[Binding Insert
[tire] set[id=141, version=1, wheel=141, ]] error[ERROR: duplicate key
value violates unique constraint "pk_tire"]
txn[1001], 19:27:37.942, Rollback
Now given all this I believe this might as well be related to recursion
problem.
I can really live without bidirectional OneToOne as I don't really need
it, but trying to escape this bug would be a real nighmare :)
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "booking")
private Booking booking;
You will need to also remove from the Invoice entity:
@ManyToOne(cascade = CascadeType.ALL) @JoinColumn(name = "booking") private Booking booking;
>>So the question is, if you remove that derived relationship (Booking on the Invoice entity) is there a problem?I've commented out List<Invoice> invoices field on Booking entity. The problem stays the same: http://pastie.org/1788902
All the rest code is the same, just field invoices and its getter and setter are commented.
On 2011.04.13 01:15, Rob Bygrave wrote:
>>�and Invoice�http://pastie.org/1786543
So I see you have change Booking here to be a ManyToOne (when it used to be a OneToOne).
I'm pretty sure the booking column is effectively derived data. Strictly speaking it is not required for either of the 2 relationships .... but you are looking to include it to help you navigate the other way - hmmm, I think that might not help you actually.
>>�So it is not bidirectional OneToOne
Good - I think we are agreed on that. The problem being it almost looked like one which I think is the problem - Ebean likely thought you where trying to define a bi-directional OneToOne without any mappedBy attribute (hence the recursion problem).
>>�So I get this error not only on bidirectional OneToOne but on other�relationships too.�
Hmm, this statement is a regression. No mappedBy means no bi-directional OneToOne -> this was not a bi-directional OneToOne.
>>�So my guess is that this happens when there is a ...
> > ďż˝ ďż˝ ďż˝ ďż˝@Id @GeneratedValue(strategy = GenerationType.SEQUENCE)
> > � � � �private Long id;
>
> > ďż˝ ďż˝ ďż˝ ďż˝@Version
> > � � � �private int version;
>
> > ďż˝ ďż˝ ďż˝ ďż˝@OneToOne(cascade = CascadeType.ALL)
> > ďż˝ ďż˝ ďż˝ ďż˝ @JoinColumn(name = "booking")
> > � � � �private Booking booking;
>
> > ďż˝ ďż˝ ďż˝ ďż˝...
> > }
>
> > @Entity
> > @Table(name = "booking")
> > public class Booking {
>
> > ďż˝ ďż˝ ďż˝ ďż˝@Id @GeneratedValue(strategy = GenerationType.SEQUENCE)
> > � � � �private Long id;
>
> > ďż˝ ďż˝ ďż˝ ďż˝@Version
> > � � � �private int version;
>
> > ďż˝ ďż˝ ďż˝ ďż˝@OneToOne(cascade = CascadeType.ALL)
> > ďż˝ ďż˝ ďż˝ ďż˝ @JoinColumn(name = "client_invoice")
> > � � � �private Invoice clientInvoice;
>
> > ďż˝ ďż˝ ďż˝ ďż˝@OneToOne(cascade = CascadeType.ALL)
> > ďż˝ ďż˝ ďż˝ ďż˝@JoinColumn(name = "agent_invoice")
> > � � � �private Invoice agentInvoice;
>
> > ďż˝ ďż˝ ďż˝ ďż˝...
> > }
>
> > As you can see I need this bidirectional OneToOne relationship in
> > order to get Booking entity when having Invoice entity. Without
> > JoinColumn on Booking side, I cannot identify which of the invoices is
> > client invoice and which is agent invoice. Without JoinColumn on
> > Invoice side, I cannot select (not that simple) all invoices for some
> > booking, also having an invoice I cannot easily find which booking it
> > belongs to.
>
> > On Apr 6, 7:34 pm, Saulius Pa�ekajus <saul...@pacekajus.lt> wrote:
> > > Well you are actually right that the bidirectional OneToOne relationship
> > > does not really have any advantages. Well I unless one forgets to add
> > > index for a foreign key :)
>
> > > Anyway there is another problem with unidirectional OneToOne
> > > relationship either. Suppose we have entities e1 and e2. Now if I have
> > > foreign key on e2 and saving e1 - it works fine, but if I save e2 - it
> > > save the data and fails with an error. Please consider this example
> > > (please not Car, Wheel and Tire is solely for example purposes - so some
> > > relations might not make sense):
>
> > > @Entity
> > > @Table(name="tire")
> > > public class Tire {
>
> > > ďż˝ ďż˝ ďż˝@Id @GeneratedValue(strategy = GenerationType.SEQUENCE)
> > > � � �private Long id;
>
> > > ďż˝ ďż˝ ďż˝@Version
> > > � � �private int version;
>
> > > ďż˝ ďż˝ ďż˝@OneToOne(cascade = CascadeType.ALL)
> > > ďż˝ ďż˝ ďż˝@JoinColumn(name = "wheel")
> > > � � �private Wheel wheel;
>
> > > ďż˝ ďż˝ ďż˝....
>
> > > }
>
> > > @Entity
> > > @Table(name="wheel")
> > > public class Wheel {
>
> > > ďż˝ ďż˝ ďż˝@Id @GeneratedValue(strategy = GenerationType.SEQUENCE)
> > > � � �private Long id;
>
> > > ďż˝ ďż˝ ďż˝@Version
> > > � � �private int version;
>
> > > ďż˝ ďż˝ ďż˝@OneToOne(mappedBy="wheel", cascade = CascadeType.ALL)
> > > � � �private Tire tire;
>
> > > ďż˝ ďż˝ ďż˝....
>
> > > }
>
> > > Now here is a simple code that creates beans:
>
> > > � � �Wheel w1 = new Wheel();
> > > � � �Tire t1 = new Tire();
>
> > > � � �t1.setWheel(w1);
> > > � � �w1.setTire(t1);
>
> > > Now the success completely depends on which entity you provide to
> > > Ebean.save(): make it Ebean.save(w1); and it's OK; make it
> > > Ebean.save(t1); and you get exception:
>
> > > javax.persistence.PersistenceException: ERROR executing DML
> > > bindLog[Binding Insert [tire] �set[id=121, version=1, wheel=121, ]]
> > > error[ERROR: duplicate key value violates unique constraint "pk_tire"]
> > > � � �at
>
> > com.avaje.ebeaninternal.server.persist.dml.DmlBeanPersister.execute(DmlBeanPersister.java:116)
> > > � � �at
>
> > com.avaje.ebeaninternal.server.persist.dml.DmlBeanPersister.insert(DmlBeanPersister.java:76)
> > > � � �at
>
> > com.avaje.ebeaninternal.server.persist.DefaultPersistExecute.executeInsertBean(DefaultPersistExecute.java:91)
> > > � � �at
>
> > com.avaje.ebeaninternal.server.core.PersistRequestBean.executeNow(PersistRequestBean.java:527)
> > > � � �at
>
> > com.avaje.ebeaninternal.server.core.PersistRequestBean.executeOrQueue(PersistRequestBean.java:557)
> > > � � �at
>
> > com.avaje.ebeaninternal.server.persist.DefaultPersister.insert(DefaultPersister.java:404)
> > > � � �at
>
> > com.avaje.ebeaninternal.server.persist.DefaultPersister.saveEnhanced(DefaultPersister.java:345)
> > > � � �at
>
> > com.avaje.ebeaninternal.server.persist.DefaultPersister.saveRecurse(DefaultPersister.java:315)
> > > � � �at
>
> > com.avaje.ebeaninternal.server.persist.DefaultPersister.save(DefaultPersister.java:282)
> > > � � �at
>
> > com.avaje.ebeaninternal.server.core.DefaultServer.save(DefaultServer.java:1577)
> > > � � �at
>
> > com.avaje.ebeaninternal.server.core.DefaultServer.save(DefaultServer.java:1567)
> > > � � �at com.avaje.ebean.Ebean.save(Ebean.java:538)
> > > � � �at lt.travelonline.test.CarTest.testCarInsert(CarTest.java:22)
> > > � � �at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> > > � � �at
>
> > sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
> > > � � �at
>
> > sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> > > � � �at java.lang.reflect.Method.invoke(Method.java:616)
> > > � � �at
>
> > org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
> > > � � �at
>
> > org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
> > > � � �at
>
> > org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
> > > � � �at
>
> > org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
> > > � � �at
>
> > org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
> > > � � �at
>
> > org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:82)
> > > � � �at
>
> > org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
> > > � � �at
>
> > org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:240)
> > > � � �at
>
> > org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
> > > � � �at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
> > > � � �at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
> > > � � �at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
> > > � � �at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
> > > � � �at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
> > > � � �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:236)
> > > � � �at
>
> > org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:180)
> > > � � �at
>
> > org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
> > > � � �at
>
> > org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
> > > � � �at
>
> > org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
> > > � � �at
>
> > org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
> > > � � �at
>
> > org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
> > > � � �at
>
> > org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
> > > Caused by: org.postgresql.util.PSQLException: ERROR: duplicate key value
> > > violates unique constraint "pk_tire"
> > > � � �at
>
> > org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:1608)
> > > � � �at
>
> > org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1343)
> > > � � �at
>
> > org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:194)
> > > � � �at
>
> > org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:451)
> > > � � �at
>
> > org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:350)
> > > � � �at
>
> > org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:304)
> > > � � �at
>
> > com.jolbox.bonecp.PreparedStatementHandle.executeUpdate(PreparedStatementHandle.java:228)
> > > � � �at
>
> > com.avaje.ebeaninternal.server.type.DataBind.executeUpdate(DataBind.java:74)
> > > � � �at
>
> > com.avaje.ebeaninternal.server.persist.dml.InsertHandler.execute(InsertHandler.java:155)
> > > � � �at
>
> > com.avaje.ebeaninternal.server.persist.dml.DmlBeanPersister.execute(DmlBeanPersister.java:105)
> > > ďż˝ ďż˝ ďż˝... 40 more
>
> > > The transaction log:
>
> > > txn[1001], 19:27:37.932, insert into wheel (id, version) values (?,?)
> > > txn[1001], 19:27:37.932, Binding Insert [wheel]
>
> ...
>
> read more »
I removed it from Invoice entity too and it works.
But I would really prefer to have this one as I need Booking in most tasks where I process Invoice!
On 2011.04.13 04:12, Rob Bygrave wrote:
You will need to also remove from the Invoice entity:
@ManyToOne(cascade = CascadeType.ALL) @JoinColumn(name = "booking") private Booking booking;
>>So the question is, if you remove that derived relationship (Booking on the Invoice entity) is there a problem?I've commented out List<Invoice> invoices field on Booking entity. The problem stays the same: http://pastie.org/1788902
All the rest code is the same, just field invoices and its getter and setter are commented.
On 2011.04.13 01:15, Rob Bygrave wrote:
>> and Invoice http://pastie.org/1786543
So I see you have change Booking here to be a ManyToOne (when it used to be a OneToOne).
I'm pretty sure the booking column is effectively derived data. Strictly speaking it is not required for either of the 2 relationships .... but you are looking to include it to help you navigate the other way - hmmm, I think that might not help you actually.
>> So it is not bidirectional OneToOne
Good - I think we are agreed on that. The problem being it almost looked like one which I think is the problem - Ebean likely thought you where trying to define a bi-directional OneToOne without any mappedBy attribute (hence the recursion problem).
>> So I get this error not only on bidirectional OneToOne but on other relationships too.
Hmm, this statement is a regression. No mappedBy means no bi-directional OneToOne -> this was not a bi-directional OneToOne.
> > @Id @GeneratedValue(strategy = GenerationType.SEQUENCE)
> > private Long id;
>
> > @Version
> > private int version;
>
> > @OneToOne(cascade = CascadeType.ALL)
> > @JoinColumn(name = "booking")
> > private Booking booking;
>
> > ...
> > }
>
> > @Entity
> > @Table(name = "booking")
> > public class Booking {
>
> > @Id @GeneratedValue(strategy = GenerationType.SEQUENCE)
> > private Long id;
>
> > @Version
> > private int version;
>
> > @OneToOne(cascade = CascadeType.ALL)
> > @JoinColumn(name = "client_invoice")
> > private Invoice clientInvoice;
>
> > @OneToOne(cascade = CascadeType.ALL)
> > @JoinColumn(name = "agent_invoice")
> > private Invoice agentInvoice;
>
> > ...
> > }
>
> > As you can see I need this bidirectional OneToOne relationship in
> > order to get Booking entity when having Invoice entity. Without
> > JoinColumn on Booking side, I cannot identify which of the invoices is
> > client invoice and which is agent invoice. Without JoinColumn on
> > Invoice side, I cannot select (not that simple) all invoices for some
> > booking, also having an invoice I cannot easily find which booking it
> > belongs to.
>
> > On Apr 6, 7:34 pm, Saulius Pačekajus <saul...@pacekajus.lt> wrote:
> > > Well you are actually right that the bidirectional OneToOne relationship
> > > does not really have any advantages. Well I unless one forgets to add
> > > index for a foreign key :)
>
> > > Anyway there is another problem with unidirectional OneToOne
> > > relationship either. Suppose we have entities e1 and e2. Now if I have
> > > foreign key on e2 and saving e1 - it works fine, but if I save e2 - it
> > > save the data and fails with an error. Please consider this example
> > > (please not Car, Wheel and Tire is solely for example purposes - so some
> > > relations might not make sense):
>
> > > @Entity
> > > @Table(name="tire")
> > > public class Tire {
>
> > > @Id @GeneratedValue(strategy = GenerationType.SEQUENCE)
> > > private Long id;
>
> > > @Version
> > > private int version;
>
> > > @OneToOne(cascade = CascadeType.ALL)
> > > @JoinColumn(name = "wheel")
> > > private Wheel wheel;
>
> > > ....
>
> > > }
>
> > > @Entity
> > > @Table(name="wheel")
> > > public class Wheel {
>
> > > @Id @GeneratedValue(strategy = GenerationType.SEQUENCE)
> > > private Long id;
>
> > > @Version
> > > private int version;
>
> > > @OneToOne(mappedBy="wheel", cascade = CascadeType.ALL)
> > > private Tire tire;
>
> > > ....
>
> > > }
>
> > > Now here is a simple code that creates beans:
>
> > > Wheel w1 = new Wheel();
> > > Tire t1 = new Tire();
>
> > > t1.setWheel(w1);
> > > w1.setTire(t1);
>
> > > Now the success completely depends on which entity you provide to
> > > Ebean.save(): make it Ebean.save(w1); and it's OK; make it
> > > Ebean.save(t1); and you get exception:
>
> > > javax.persistence.PersistenceException: ERROR executing DML
> > > bindLog[Binding Insert [tire] set[id=121, version=1, wheel=121, ]]
> > > error[ERROR: duplicate key value violates unique constraint "pk_tire"]
> > > at
>
> > org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
> > > Caused by: org.postgresql.util.PSQLException: ERROR: duplicate key value
> > > violates unique constraint "pk_tire"
> > > at
>
> > org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:1608)
> > > at
>
> > org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1343)
> > > at
>
> > org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:194)
> > > at
>
> > org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:451)
> > > at
>
> > org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:350)
> > > at
>
> > org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:304)
> > > at
>
> > com.jolbox.bonecp.PreparedStatementHandle.executeUpdate(PreparedStatementHandle.java:228)
> > > at
>
> > com.avaje.ebeaninternal.server.type.DataBind.executeUpdate(DataBind.java:74)
> > > at
>
> > com.avaje.ebeaninternal.server.persist.dml.InsertHandler.execute(InsertHandler.java:155)
> > > at
>
> > com.avaje.ebeaninternal.server.persist.dml.DmlBeanPersister.execute(DmlBeanPersister.java:105)
> > > ... 40 more
>
> > > The transaction log:
>
> > > txn[1001], 19:27:37.932, insert into wheel (id, version) values (?,?)
> > > txn[1001], 19:27:37.932, Binding Insert [wheel]
>
> ...
>
> read more »
Right.
I believe the problem will be something along the lines of what you said earlier.... Ebean is probably searching for the other side of the OneToOne's ... finding that Booking property and then incorrectly thinking it is the other side of the OneToOne.
I don't have time to look at that tonight ... hopefully you can wait a day or two (until I find some time to investigate).
Cheers, Rob.
I removed it from Invoice entity too and it works.
But I would really prefer to have this one as I need Booking in most tasks where I process Invoice!
On 2011.04.13 04:12, Rob Bygrave wrote:
You will need to also remove from the Invoice entity:
@ManyToOne(cascade = CascadeType.ALL) @JoinColumn(name = "booking") private Booking booking;
>>So the question is, if you remove that derived relationship (Booking on the Invoice entity) is there a problem?I've commented out List<Invoice> invoices field on Booking entity. The problem stays the same: http://pastie.org/1788902
All the rest code is the same, just field invoices and its getter and setter are commented.
On 2011.04.13 01:15, Rob Bygrave wrote:
>>�and Invoice�http://pastie.org/1786543
So I see you have change Booking here to be a ManyToOne (when it used to be a OneToOne).
I'm pretty sure the booking column is effectively derived data. Strictly speaking it is not required for either of the 2 relationships .... but you are looking to include it to help you navigate the other way - hmmm, I think that might not help you actually.
>>�So it is not bidirectional OneToOne
Good - I think we are agreed on that. The problem being it almost looked like one which I think is the problem - Ebean likely thought you where trying to define a bi-directional OneToOne without any mappedBy attribute (hence the recursion problem).
>>�So I get this error not only on bidirectional OneToOne but on other�relationships too.�
Hmm, this statement is a regression. No mappedBy means no bi-directional OneToOne -> this was not a bi-directional OneToOne.
>>�So my guess is that this happens when there is a ...
> > ďż˝ ďż˝ ďż˝ ďż˝@Id @GeneratedValue(strategy = GenerationType.SEQUENCE)
> > � � � �private Long id;
>
> > ďż˝ ďż˝ ďż˝ ďż˝@Version
> > � � � �private int version;
>
> > ďż˝ ďż˝ ďż˝ ďż˝@OneToOne(cascade = CascadeType.ALL)
> > ďż˝ ďż˝ ďż˝ ďż˝ @JoinColumn(name = "booking")
> > � � � �private Booking booking;
>
> > ďż˝ ďż˝ ďż˝ ďż˝...
> > }
>
> > @Entity
> > @Table(name = "booking")
> > public class Booking {
>
> > ďż˝ ďż˝ ďż˝ ďż˝@Id @GeneratedValue(strategy = GenerationType.SEQUENCE)
> > � � � �private Long id;
>
> > ďż˝ ďż˝ ďż˝ ďż˝@Version
> > � � � �private int version;
>
> > ďż˝ ďż˝ ďż˝ ďż˝@OneToOne(cascade = CascadeType.ALL)
> > ďż˝ ďż˝ ďż˝ ďż˝ @JoinColumn(name = "client_invoice")
> > � � � �private Invoice clientInvoice;
>
> > ďż˝ ďż˝ ďż˝ ďż˝@OneToOne(cascade = CascadeType.ALL)
> > ďż˝ ďż˝ ďż˝ ďż˝@JoinColumn(name = "agent_invoice")
> > � � � �private Invoice agentInvoice;
>
> > ďż˝ ďż˝ ďż˝ ďż˝...
> > }
>
> > As you can see I need this bidirectional OneToOne relationship in
> > order to get Booking entity when having Invoice entity. Without
> > JoinColumn on Booking side, I cannot identify which of the invoices is
> > client invoice and which is agent invoice. Without JoinColumn on
> > Invoice side, I cannot select (not that simple) all invoices for some
> > booking, also having an invoice I cannot easily find which booking it
> > belongs to.
>
> > On Apr 6, 7:34 pm, Saulius Pa�ekajus <saul...@pacekajus.lt> wrote:
> > > Well you are actually right that the bidirectional OneToOne relationship
> > > does not really have any advantages. Well I unless one forgets to add
> > > index for a foreign key :)
>
> > > Anyway there is another problem with unidirectional OneToOne
> > > relationship either. Suppose we have entities e1 and e2. Now if I have
> > > foreign key on e2 and saving e1 - it works fine, but if I save e2 - it
> > > save the data and fails with an error. Please consider this example
> > > (please not Car, Wheel and Tire is solely for example purposes - so some
> > > relations might not make sense):
>
> > > @Entity
> > > @Table(name="tire")
> > > public class Tire {
>
> > > ďż˝ ďż˝ ďż˝@Id @GeneratedValue(strategy = GenerationType.SEQUENCE)
> > > � � �private Long id;
>
> > > ďż˝ ďż˝ ďż˝@Version
> > > � � �private int version;
>
> > > ďż˝ ďż˝ ďż˝@OneToOne(cascade = CascadeType.ALL)
> > > ďż˝ ďż˝ ďż˝@JoinColumn(name = "wheel")
> > > � � �private Wheel wheel;
>
> > > ďż˝ ďż˝ ďż˝....
>
> > > }
>
> > > @Entity
> > > @Table(name="wheel")
> > > public class Wheel {
>
> > > ďż˝ ďż˝ ďż˝@Id @GeneratedValue(strategy = GenerationType.SEQUENCE)
> > > � � �private Long id;
>
> > > ďż˝ ďż˝ ďż˝@Version
> > > � � �private int version;
>
> > > ďż˝ ďż˝ ďż˝@OneToOne(mappedBy="wheel", cascade = CascadeType.ALL)
> > > � � �private Tire tire;
>
> > > ďż˝ ďż˝ ďż˝....
>
> > > }
>
> > > Now here is a simple code that creates beans:
>
> > > � � �Wheel w1 = new Wheel();
> > > � � �Tire t1 = new Tire();
>
> > > � � �t1.setWheel(w1);
> > > � � �w1.setTire(t1);
>
> > > Now the success completely depends on which entity you provide to
> > > Ebean.save(): make it Ebean.save(w1); and it's OK; make it
> > > Ebean.save(t1); and you get exception:
>
> > > javax.persistence.PersistenceException: ERROR executing DML
> > > bindLog[Binding Insert [tire] �set[id=121, version=1, wheel=121, ]]
> > > error[ERROR: duplicate key value violates unique constraint "pk_tire"]
> > > � � �at
>
> > org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
> > > Caused by: org.postgresql.util.PSQLException: ERROR: duplicate key value
> > > violates unique constraint "pk_tire"
> > > � � �at
>
> > org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:1608)
> > > � � �at
>
> > org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1343)
> > > � � �at
>
> > org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:194)
> > > � � �at
>
> > org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:451)
> > > � � �at
>
> > org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:350)
> > > � � �at
>
> > org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:304)
> > > � � �at
>
> > com.jolbox.bonecp.PreparedStatementHandle.executeUpdate(PreparedStatementHandle.java:228)
> > > � � �at
>
> > com.avaje.ebeaninternal.server.type.DataBind.executeUpdate(DataBind.java:74)
> > > � � �at
>
> > com.avaje.ebeaninternal.server.persist.dml.InsertHandler.execute(InsertHandler.java:155)
> > > � � �at
>
> > com.avaje.ebeaninternal.server.persist.dml.DmlBeanPersister.execute(DmlBeanPersister.java:105)
> > > ďż˝ ďż˝ ďż˝... 40 more
>
> > > The transaction log:
>
> > > txn[1001], 19:27:37.932, insert into wheel (id, version) values (?,?)
> > > txn[1001], 19:27:37.932, Binding Insert [wheel]
>
> ...
>
> read more »
Nope, no news ... been busy.
>>�Maybe a donation could help?
Donations are always�gratefully�received. Unfortunately that would be about the 4th donation�received and the first for quite some time -�so donations are not exactly funding any of my time. We don't have a corporate sponsor so currently people will have to exercise patience. Suggestions welcome.
Cheers, Rob.
2011/4/27 Saulius <sau...@pacekajus.lt>
Hey guys, any news on this?
I've spent quite some time migrating my app to use Ebean, but I cannot
release it to production for 3 weeks now because of this cascading
bug. Maybe a donation could help?
Regards, Saulius
> > 2011/4/13 Saulius Pa�ekajus <saul...@pacekajus.lt
On Apr 13, 11:01 am, Saulius Pa�ekajus <saul...@pacekajus.lt> wrote:
> Sure I can wait a day or two. I appreciate your help!
>
> Regards, Saulius
>
> On 2011.04.13 10:52, Rob Bygrave wrote:
>
>
>
>
>
>
>
> > Right.
>
> > I believe the problem will be something along the lines of what you
> > said earlier.... Ebean is probably searching for the other side of the
> > OneToOne's ... finding that Booking property and then incorrectly
> > thinking it is the other side of the OneToOne.
>
> > I don't have time to look at that tonight ... hopefully you can wait a
> > day or two (until I find some time to investigate).
>
> > Cheers, Rob.
>
> > <mailto:saul...@pacekajus.lt>>
>> >> � � 2011/4/13 Saulius Pa�ekajus <saul...@pacekajus.lt
> > ďż˝ ďż˝ I removed it from Invoice entity too and it works.
>
> > ďż˝ ďż˝ But I would really prefer to have this one as I need Booking in
> > ďż˝ ďż˝ most tasks where I process Invoice!
>
> > ďż˝ ďż˝ On 2011.04.13 04:12, Rob Bygrave wrote:
>
> >> ďż˝ ďż˝ You will need to also remove from the Invoice entity:
>
> >> � � @ManyToOne(cascade �= �CascadeType.ALL)
> >> ďż˝ ďż˝ @JoinColumn(name ďż˝= ďż˝"booking")
> >> � � private �Booking �booking;
>
> >> ďż˝ ďż˝ <mailto:saul...@pacekajus.lt>>
>> >>> ďż˝ ďż˝ ďż˝ ďż˝ >> and Invoicehttp://pastie.org/1786543
> >> ďż˝ ďż˝ ďż˝ ďż˝ >>So the question is, if you remove that derived relationship
> >> ďż˝ ďż˝ ďż˝ ďż˝ (Booking on the Invoice entity) is there a problem?
>
> >> ďż˝ ďż˝ ďż˝ ďż˝ I've commented out /List<Invoice> invoices/ field on Booking
> >> ďż˝ ďż˝ ďż˝ ďż˝ entity. The problem stays the same:http://pastie.org/1788902
>
> >> ďż˝ ďż˝ ďż˝ ďż˝ All the rest code is the same, just field /invoices /and its
> >> ďż˝ ďż˝ ďż˝ ďż˝ getter and setter are commented.
>
> >> ďż˝ ďż˝ ďż˝ ďż˝ On 2011.04.13 01:15, Rob Bygrave wrote:
>
> >>> ďż˝ ďż˝ ďż˝ ďż˝ So I see you have change Booking here to be a ManyToOne
> >>> ďż˝ ďż˝ ďż˝ ďż˝ (when it used to be a OneToOne).
>
> >>> ďż˝ ďż˝ ďż˝ ďż˝ >> The database scheme for these 2 entities is
> >>> � � � �http://pastie.org/1786710
>
> >>> ďż˝ ďż˝ ďż˝ ďż˝ I'm pretty sure the booking column is effectively derived
> >>> ďż˝ ďż˝ ďż˝ ďż˝ data. Strictly speaking it is not required for either of the
> >>> ďż˝ ďż˝ ďż˝ ďż˝ 2 relationships .... but you are looking to include it to
> >>> ďż˝ ďż˝ ďż˝ ďż˝ help you navigate the other way - hmmm, I think that might
> >>> ďż˝ ďż˝ ďż˝ ďż˝ not help you actually.
>
> >>> ďż˝ ďż˝ ďż˝ ďż˝ >> So it is not bidirectional OneToOne
>
> >>> ďż˝ ďż˝ ďż˝ ďż˝ Good - I think we are agreed on that. The problem being it
> >>> ďż˝ ďż˝ ďż˝ ďż˝ almost looked like one which I think is the problem - Ebean
> >>> ďż˝ ďż˝ ďż˝ ďż˝ likely thought you where trying to define a bi-directional
> >>> ďż˝ ďż˝ ďż˝ ďż˝ OneToOne without any mappedBy attribute (hence the recursion
> >>> ďż˝ ďż˝ ďż˝ ďż˝ problem).
>
> >>> ďż˝ ďż˝ ďż˝ ďż˝ >> So I get this error not only on bidirectional OneToOne
> >>> ďż˝ ďż˝ ďż˝ ďż˝ but on other relationships too.
>
> >>> ďż˝ ďż˝ ďż˝ ďż˝ Hmm, this statement is a regression. No mappedBy means no
> >>> ďż˝ ďż˝ ďż˝ ďż˝ bi-directional OneToOne -> this was not a bi-directional
> >>> ďż˝ ďż˝ ďż˝ ďż˝ OneToOne.
>
> >>> ďż˝ ďż˝ ďż˝ ďż˝ >> So my guess is that this happens when there is a ...
>
> >>> ďż˝ ďż˝ ďż˝ ďż˝ Sounds about right.
>
> >>> ďż˝ ďż˝ ďż˝ ďż˝ The summary for me is that you have 2 unidirectional
> >>> ďż˝ ďż˝ ďż˝ ďż˝ OneToOne relationships... plus a derived relationship going
> >>> ďż˝ ďż˝ ďż˝ ďż˝ back the other way. So the question is, if you remove that
> >>> ďż˝ ďż˝ ďż˝ ďż˝ derived relationship (Booking on the Invoice entity) is
> >>> ďż˝ ďż˝ ďż˝ ďż˝ there a problem?
>
> >>> ďż˝ ďż˝ ďż˝ ďż˝ On Wed, Apr 13, 2011 at 1:17 AM, Saulius
> >>> ďż˝ ďż˝ ďż˝ ďż˝ <saul...@pacekajus.lt <mailto:saul...@pacekajus.lt>> wrote:> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ they are: Bookinghttp://pastie.org/1786569and Invoice
>
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ Well I don't actually want to prove that bidirectional
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ OneToOne
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ relationship is necessary for me or anybody else. In
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ fact you are
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ right, I don't have this bidirectional OneToOne
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ relationship - I've
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ just made it up as an example to illustrate that
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ cascading bug that
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ leads to infinite recursion.
>
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ Anyway if you want to see complete booking and invoice
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ entities, here
> >>> � � � � � �http://pastie.org/1786543> >>> � � � � � � these 2 entities ishttp://pastie.org/1786710
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ (note it's actually OneToMany relationship). The
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ database scheme for
>
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ So it is not bidirectional OneToOne, but it is a real
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ world example
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ and it does not change the fact, that when I try to save
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ Booking with
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ both invoices set (http://pastie.org/1786739) I get the
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ same infinite
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ recursion failure:http://pastie.org/1786745
>
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ So I get this error not only on bidirectional OneToOne
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ but on other
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ relationships too. So my guess is that this happens when
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ there is a
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ loop in relationship between 2 entities (E1 has
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ reference to E2 and E2
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ has reference to E1 - and it does not have to be a
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ bidirectional
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ relashionship) and it probably happens because after
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ doing work on E1
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ and then cascading to E2 algorithm goes again back to E1
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ thus getting
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ into infinite recursion.
>
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ Regards, Saulius
>
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ On Apr 12, 12:46 am, Rob Bygrave
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ <robin.bygr...@gmail.com
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ <mailto:saul...@pacekajus.lt>>> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ <mailto:robin.bygr...@gmail.com>> wrote:
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > Well, there are no mappedBy attributes so this doesn't
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ look like a valid
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > bi-directional OneToOne. As there are 2 relationship
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ here I suspect that is
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > where the confusion is - specifically around the
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ booking property in the
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > Invoice.
>
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > I suspect you added that Booking property later
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ (originally
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > unidirectional?). Can you state again what the problem
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ you had with your
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > query (it was not obvious to me why you didn't query
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ from the Booking ... to
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > get the Invoices for a given booking).
>
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > Can you state what your DB tables look like (I'm
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ especially interested in
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > that booking column which looks dubious/incorrect so
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ it would be good to
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > clarify what the relational model looks like).
>
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > I suspect removing the booking property on the Invoice
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ is effectively the
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > fix here. Otherwise you might be looking to use a join
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ table (which Ebean
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > does not support) but that is a guess and I suspect
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ that is not what you
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > want.
>
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > Cheers, Rob.
>
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > 2011/4/12 Saulius <saul...@pacekajus.lt
> >>> � � � � � � > > On Apr 6, 7:34 pm, Saulius Pa�ekajus>
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > > Hi guys,
>
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > > I know it's a low priority issue for you, but it is
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ the only issue
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > > that keeps me from using it in production and I
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ think it is a serious
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > > problem because Ebean.save fails for a valid entity.
>
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > > Once again, just to picture the situation consider
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ these 2 entities:
>
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > > @Entity
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > > @Table(name="invoice")
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > > public class Invoice {
>
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > > ďż˝ ďż˝ ďż˝ ďż˝@Id @GeneratedValue(strategy =
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ GenerationType.SEQUENCE)
> >>> � � � � � � > > � � � �private Long id;
>
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > > ďż˝ ďż˝ ďż˝ ďż˝@Version
> >>> � � � � � � > > � � � �private int version;
>
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > > ďż˝ ďż˝ ďż˝ ďż˝@OneToOne(cascade = CascadeType.ALL)
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > > ďż˝ ďż˝ ďż˝ ďż˝ @JoinColumn(name = "booking")
> >>> � � � � � � > > � � � �private Booking booking;
>
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > > ďż˝ ďż˝ ďż˝ ďż˝...
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > > }
>
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > > @Entity
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > > @Table(name = "booking")
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > > public class Booking {
>
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > > ďż˝ ďż˝ ďż˝ ďż˝@Id @GeneratedValue(strategy =
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ GenerationType.SEQUENCE)
> >>> � � � � � � > > � � � �private Long id;
>
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > > ďż˝ ďż˝ ďż˝ ďż˝@Version
> >>> � � � � � � > > � � � �private int version;
>
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > > ďż˝ ďż˝ ďż˝ ďż˝@OneToOne(cascade = CascadeType.ALL)
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > > ďż˝ ďż˝ ďż˝ ďż˝ @JoinColumn(name = "client_invoice")
> >>> � � � � � � > > � � � �private Invoice clientInvoice;
>
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > > ďż˝ ďż˝ ďż˝ ďż˝@OneToOne(cascade = CascadeType.ALL)
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > > ďż˝ ďż˝ ďż˝ ďż˝@JoinColumn(name = "agent_invoice")
> >>> � � � � � � > > � � � �private Invoice agentInvoice;
>
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > > ďż˝ ďż˝ ďż˝ ďż˝...
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > > }
>
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > > As you can see I need this bidirectional OneToOne
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ relationship in
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > > order to get Booking entity when having Invoice
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ entity. Without
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > > JoinColumn on Booking side, I cannot identify which
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ of the invoices is
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > > client invoice and which is agent invoice. Without
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ JoinColumn on
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > > Invoice side, I cannot select (not that simple) all
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ invoices for some
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > > booking, also having an invoice I cannot easily find
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ which booking it
> >>> ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ ďż˝ > > belongs to.
>
>> paypal
Fair enough. The button is on the source forge download page... but I see it is pretty tiny now. I will put a donate button or two on the avaje site.
>> open source
Yes it is. Links etc on the download page. Svn repo in source forge.
>> mature enough
Unfortunately I can't claim to be unbiased. After all... There are a lot more hibernate users out there.
Technically yes I think Ebean is mature enough. On the other hand the community is very small and not very 'vocal' so there is a significant support/community problem. Most questions are answered by about 4 people.
There is also no financial backing so finding time to do bugs and develop features is difficult.
Ideally Ebean finds enough support to make the next step.
Not sure if that answers your question.
Cheers, Rob.
Regards, Saulius