0

How to configure multiple one to many relationship to the same entity?

Consider two classes Boy and Toy. They look as shown below

class Boy {
    @OneToMany(mappedBy='ownedBy',fetch=FetchType.EAGER, cascade=CascadeType.ALL)
    private List<Toy> bikes;
    ...
    @OneToMany(mappedBy='ownedBy',fetch=FetchType.EAGER, cascade=CascadeType.ALL)
    private List<Toy> cars;
    ...

class Toy {
    @ManyToOne
    private Boy ownedBy;
    ...

I know that this config is wrong. But I dont know what needs to be configured here. What configuration should be made to the @OneToMany and @ManyToOne annotations, both sides?

I got the following exception message before I added the 'mappedBy' to the annotations

java.sql.SQLException: Field 'cars_Id' doesn't have a default value
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1073)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4096)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4028)
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2490)
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2651)
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2683)
    at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2144)
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2444)
    at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1997)

But there was a join table like 'boy_toy' created when there was no 'mappedBy' added to the annotation. After adding it I don't see the table created in the database.

  • Update

Also boy_toy table had three columns namely boy_id, cars_id and bikes_id. But ideally it should be like boy_id a not null and others nullable columns. But all the columns generated were not-nullable. I tried to remove the 'mappedBy' from the annotation and manually edit the table structure to make cars_id and bikes_id to nullable. It worked like a wonder.

So now, the only remaining question I have is

How can we dictate hibernate to configure a join table with nullable and not-nullable columns?

promaxdev
  • 455
  • 1
  • 6
  • 19
  • Your mapping doesn't make sense, why would you make two collections of the same items? If you want to make multiple mappings against the same type, you need to specify unique mappedBy for them. In other words, you can't map both collections by "ownedBy", Hibernate won't know what to do, especially in the case of merge/persist. – Rasmus Franke Jun 23 '12 at 15:12
  • Actually I didnt have any requirement to do so. I just did some experimentation with hibernate. I learned that the 'mappedBy' doesnt solve the problem. Removing 'mappedBy' created a join table BOY_TOY with columns BOY_ID, BIKES_ID and CARS_ID; all of them not-nullable.I would like to know a method which will tell hibernate to make BIKES_ID and CARS_ID nullable fields. – promaxdev Jun 23 '12 at 17:20

1 Answers1

0

Use inheritance, create a 1-N relationship between BOY and TOY, with inheritance strategy SINGLE_TABLE. To retrieve only Bikes or Cars connected to a Boy, use polymorhic queries.

Bonus: the above setup would not work even if bikes and cars were different classes. The reason is, you cannot have multiple 1-N relationships with fetch=FetchType.EAGER. More on this in my blog: MultipleBagFetchException and Java equality

Edit: polymorphic queries

Simple:

entityManager.createQuery("SELECT toy FROM Toy toy"); // returns all Toy instances, regardless of being bike or car

entityManager.createQuery("SELECT bike FROM Bike bike"); // returns only Bike type instances of toys

in the above expressions, you can obviously use all other JPQL constructs, like WHERE, joins, etc.

If you happen to use JPA2.0, there are some new features with regards to polymorphism like type checks and type casts, see here: http://wiki.eclipse.org/EclipseLink/Release/2.1.0/JPAQueryEnhancements

Istvan Devai
  • 3,962
  • 23
  • 21