Play Framework: Model Development

Model development is one aspect of MVC that I do not have a lot of real world experience. Sure I am familiar with using an instance of a data model to work with Wicket. So developing the warehouse and book exchange data models was a great refresher.

Java Persistence
Coding the persistence with respect to the Ebean ORM was a fairly painless process compared to using the Hibernate ORM. Both ORMs used the same Java persistence annotations, yet Hibernate and Ebean differed on model retrieval. Hibernate needs each model to be associated with an entity manager instance. Although associating each model with an entity manager may be such a trivial step when creating a new project, moving an existing project over to the Hibernate ORM means that I need to sacrifice time to manage each model’s association. On the other hand, Ebean does not have an entity manager. Just creating the model with the persistence annotations means the model is ready to use. No more Hibernate configurations!

Warehouse Model
Warehouse

The warehouse model example helped jump start the programming with the various relationship persistence tags. I found that writing the tests was helpful as it gave me a sterile environment to understand how the models interact with regards to the persistentce database.

Textbook Exchange Model
TextbookExchange (2)

My first rendition of the textbook exchange request and offer models referenced the foreign key for both the student and the book models. Basically I still thought in term of database relations rather than persistence relations. After creating the models in Java, it quickly became apparent that the foreign keys were unnecessary and that I had to replicate the warehouse stockitem relation from the warehouse example.

Textbook Exchange: ERROR executing DML bindLog[] error

[textbookexchange] $ test
[info] Compiling 1 Java source to D:\workspace\textbookexchange\target\scala-2.1
0\test-classes...
[error] Test models.ModelTest.testModel failed: ERROR executing DML bindLog[] er
ror[Referential integrity constraint violation: "FK_REQUEST_STUDENT_3: PUBLIC.RE
QUEST FOREIGN KEY(STUDENT_PRIMARY_KEY) REFERENCES PUBLIC.STUDENT(PRIMARY_KEY) (1
)"; SQL statement:\n insert into request (primary_key, price, condition, student
_primary_key, book_primary_key) values (?,?,?,?,?) [23506-168]]
[error]     at com.avaje.ebeaninternal.server.persist.dml.DmlBeanPersister.execu
te(DmlBeanPersister.java:97)
[error]     at com.avaje.ebeaninternal.server.persist.dml.DmlBeanPersister.inser
t(DmlBeanPersister.java:57)
[error]     at com.avaje.ebeaninternal.server.persist.DefaultPersistExecute.exec
uteInsertBean(DefaultPersistExecute.java:72)
[error]     at com.avaje.ebeaninternal.server.core.PersistRequestBean.executeNow
(PersistRequestBean.java:481)
[error]     at com.avaje.ebeaninternal.server.core.PersistRequestBean.executeOrQ
ueue(PersistRequestBean.java:511)
[error]     at com.avaje.ebeaninternal.server.persist.DefaultPersister.insert(De
faultPersister.java:387)
[error]     at com.avaje.ebeaninternal.server.persist.DefaultPersister.saveEnhan
ced(DefaultPersister.java:326)
[error]     at com.avaje.ebeaninternal.server.persist.DefaultPersister.saveRecur
se(DefaultPersister.java:296)
[error]     at com.avaje.ebeaninternal.server.persist.DefaultPersister.save(Defa
ultPersister.java:263)
[error]     at com.avaje.ebeaninternal.server.core.DefaultServer.save(DefaultSer
ver.java:1610)
[error]     at com.avaje.ebeaninternal.server.core.DefaultServer.save(DefaultSer
ver.java:1600)
[error]     at com.avaje.ebean.Ebean.save(Ebean.java:505)
[error]     at play.db.ebean.Model.save(Model.java:91)
[error]     at models.ModelTest.testModel(ModelTest.java:209)
[error]     ...
[error] Caused by: org.h2.jdbc.JdbcSQLException: Referential integrity constrain
t violation: "FK_REQUEST_STUDENT_3: PUBLIC.REQUEST FOREIGN KEY(STUDENT_PRIMARY_K
EY) REFERENCES PUBLIC.STUDENT(PRIMARY_KEY) (1)"; SQL statement:
[error] insert into request (primary_key, price, condition, student_primary_key,
 book_primary_key) values (?,?,?,?,?) [23506-168]
[error]     at org.h2.message.DbException.getJdbcSQLException(DbException.java:3
29)
[error]     at org.h2.message.DbException.get(DbException.java:169)
[error]     at org.h2.message.DbException.get(DbException.java:146)
[error]     at org.h2.constraint.ConstraintReferential.checkRowOwnTable(Constrai
ntReferential.java:361)
[error]     at org.h2.constraint.ConstraintReferential.checkRow(ConstraintRefere
ntial.java:303)
[error]     at org.h2.table.Table.fireConstraints(Table.java:871)
[error]     at org.h2.table.Table.fireAfterRow(Table.java:888)
[error]     at org.h2.command.dml.Insert.insertRows(Insert.java:126)
[error]     at org.h2.command.dml.Insert.update(Insert.java:84)
[error]     at org.h2.command.CommandContainer.update(CommandContainer.java:75)
[error]     at org.h2.command.Command.executeUpdate(Command.java:230)
[error]     at org.h2.jdbc.JdbcPreparedStatement.executeUpdateInternal(JdbcPrepa
redStatement.java:156)
[error]     at org.h2.jdbc.JdbcPreparedStatement.executeUpdate(JdbcPreparedState
ment.java:142)
[error]     at com.jolbox.bonecp.PreparedStatementHandle.executeUpdate(PreparedS
tatementHandle.java:203)
[error]     at com.avaje.ebeaninternal.server.type.DataBind.executeUpdate(DataBi
nd.java:55)
[error]     at com.avaje.ebeaninternal.server.persist.dml.InsertHandler.execute(
InsertHandler.java:139)
[error]     at com.avaje.ebeaninternal.server.persist.dml.DmlBeanPersister.execu
te(DmlBeanPersister.java:86)
[error]     ... 46 more
[info] models.ModelTest
[info] x models.ModelTest.testModel
[info]
[info]
[info] Total for test models.ModelTest
[info] Finished in 0.003 seconds
[info] 1 tests, 1 failures, 0 errors
[error] Failed: : Total 1, Failed 1, Errors 0, Passed 0, Skipped 0
[error] Failed tests:
[error]         models.ModelTest
[error] (test:test) Tests unsuccessful
[error] Total time: 8 s, completed Apr 10, 2013 9:59:10 PM
[textbookexchange] $

In class we discussed a solution to this problem by adding getter and setter methods to each model’s attributes. I will update my code later if a more ideal solution does not appear.

Walk Through with Christopher Foo
There were a couple things I learned when Christopher walked me through his code and diagrams of his Warehouse and Textbook exchange models. We discussed the mapped-by persistence configuration since we both did not fully understand its usage.

Our textbook exchange model slightly differed where I assumed that a student to request is one to zero or many relation. Same went for the student to offer relation.

After Thoughts
Beyond the foreign key error with the Ebean ORM, I found this experience deepen my understanding of the Persistence API. Previously, I used Hibernate ORM only to store the results from execute stored procedures, so annotations such as @ManyToOne were left unused as all the relations were done in the stored procedure. Even with a greater understanding of the persistence API, I still feel that persistence is not an ideal solution to interacting with a database.