0

I have the following property in my entity :

@OneToOne
@JoinColumn(unique = true)
@NotNull(message = ValidatorUtils.ERROR_NOT_NULL)
public User user;

and I get the following stacktrace when I refresh my browser, while trying to generate database migration :

[error] application - 

! @6gmdbcgi0 - Internal server error, for (GET) [/] ->

play.api.UnexpectedException: Unexpected exception[NullPointerException: null]
    at play.core.ReloadableApplication$$anonfun$get$1$$anonfun$apply$1$$anonfun$1.apply(ApplicationProvider.scala:148) ~[play_2.10.jar:2.2.0]
    at play.core.ReloadableApplication$$anonfun$get$1$$anonfun$apply$1$$anonfun$1.apply(ApplicationProvider.scala:112) ~[play_2.10.jar:2.2.0]
    at scala.Option.map(Option.scala:145) ~[scala-library.jar:na]
    at play.core.ReloadableApplication$$anonfun$get$1$$anonfun$apply$1.apply(ApplicationProvider.scala:112) ~[play_2.10.jar:2.2.0]
    at play.core.ReloadableApplication$$anonfun$get$1$$anonfun$apply$1.apply(ApplicationProvider.scala:110) ~[play_2.10.jar:2.2.0]
    at scala.util.Success.flatMap(Try.scala:200) ~[scala-library.jar:na]
Caused by: java.lang.NullPointerException: null
    at com.avaje.ebeaninternal.server.ddl.CreateTableVisitor.isDbColumnWritten(CreateTableVisitor.java:59) ~[avaje-ebeanorm.jar:na]
    at com.avaje.ebeaninternal.server.ddl.CreateTableColumnVisitor.visitOneImported(CreateTableColumnVisitor.java:111) ~[avaje-ebeanorm.jar:na]
    at com.avaje.ebeaninternal.server.ddl.VisitorUtil.visit(VisitorUtil.java:109) ~[avaje-ebeanorm.jar:na]
    at com.avaje.ebeaninternal.server.ddl.VisitorUtil.visit(VisitorUtil.java:73) ~[avaje-ebeanorm.jar:na]
    at com.avaje.ebeaninternal.server.ddl.VisitorUtil.visitBean(VisitorUtil.java:62) ~[avaje-ebeanorm.jar:na]
    at com.avaje.ebeaninternal.server.ddl.VisitorUtil.visit(VisitorUtil.java:36) ~[avaje-ebeanorm.jar:na]

If I remove the @JoinColumn annotation, my schema is migrated correctly. How can I specify the column to be unique without having this error ? Thanks.

EDIT 01/09/2014 : Add generated ddl

Here is the generated ddl :

As we can see there is a foreign key for user

I'd like the generated ddl to contain something like : constraint uq_user_id unique (user_id)

c4k
  • 4,270
  • 4
  • 40
  • 65

1 Answers1

0

Instead of @JoinColumn(unique = true) try: @Column(unique=true)

Also, if you want to make a combination of multiple columns unique, you can use: Table(name="table_name",uniqueConstraints=@UniqueConstraint(columnNames={"column1","column2"}))

jrook
  • 3,459
  • 1
  • 16
  • 33
  • I tried @Column, there is no error but the unique constraint is not applied to the column in the database. UniqueConstraint at table level works fine as I used it for another entity of my project, but here I have only one field that must be unique... – c4k Dec 31 '13 at 10:24
  • Do you mean that after using @Column, play! still doesn't generate the expected DDL? I use play 2.2.0+Ebean+MySQL and after adding the annotation, the generated DDL contains the following line: constraint uq_[tableName]_[fiedName] unique (fieldName) – jrook Dec 31 '13 at 13:15
  • Yes, @Column works with a simple field (String, Double...) but not with a ManyToOne annotation. – c4k Dec 31 '13 at 16:43
  • Why would you want to set a ManyToOne variable unique? Variable user in your class does not actually create a user column in your database. ManyToOne annotation only inserts the primary key of the "ONE" field(which is unique) from the parent table into the table which contains the "MANY" side of the relationship. In this case, that would be User.id from table User. You can check that by looking at the created db schema. – jrook Dec 31 '13 at 17:03
  • You're right for the ManyToOne annotation, I replaced it with a OneToOne. I edited my question with the generated ddl and what is missing. Thanks – c4k Jan 08 '14 at 23:11
  • Let me rephrase my question: Why don't you try and enforce the unique constraint on the User entity itself? You have an entity(and hence a table) named User, right? As I see it, you have only user_id hear which is copied from user table, so if it's unique there, it will be unique hear. – jrook Jan 14 '14 at 02:50
  • I think there is a misunderstanding. You're right, my property "User.id" is unique. So i'll never have several users with the same id in the "User" table. But here, it is the "Account" model. I want to avoid someone to insert more than once an account with the same user ==> A user has only one account. If i don't protect it, I can have this in my table : Account.id = 5, User.id = 3 Account.id = 6, User.id = 3. You see ? – c4k Jan 15 '14 at 13:46
  • Does this help? http://stackoverflow.com/questions/15260116/ebean-unidirectional-onetoone-relation-with-unique-constraint – jrook Jan 17 '14 at 06:17
  • Yep I ended up doing this, but this is a bug of Ebean or the DDL generator of Play Framework because it must be working with @JoinColumn(unique = true)... I think the aim of uniqueConstraints is for multiple fields uniqueness. Anyway, thank you for the help. – c4k Jan 17 '14 at 14:28