简体   繁体   中英

Insert fails for @OneToMany Hibernate mapping with inheritance

I'm using Java and Hibernate 3.6.4.Final.
TABLE_B is a mapping table for a specific type of A entities (B) which have a OneToMany relationship with X entities.
I'm having problems inserting a B entity in the DB.
Reading of B entities from the DB is not a problem and the related X entities are correctly loaded as well.

DB model:

  • TABLE_A (id, active, info)
  • TABLE_B (a_id, x_id)
  • TABLE_X (id, info)

An "A" entity might have zero or more relations with X entities.
An "A" entity with one or more relations to Xs are called "B" entities and have their own behavior in the code.

(The class and table names has been changed for simplicity)

@Entity
@Table(name = "TABLE_A")
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class A {
  ...
}

@Entity
@Table(name="TABLE_B")
@PrimaryKeyJoinColumn(name="A_ID", referencedColumnName = "ID")
public class B extends A implements Serializable {

    @OneToMany(cascade={CascadeType.ALL})
    @JoinTable(
        name="TABLE_B",
        joinColumns = @JoinColumn( name="A_ID"),
        inverseJoinColumns = @JoinColumn( name="X_ID", insertable = true, nullable = false)
    )
    private List<X> Xs;
    ...
}

The log:

SQLStatementLogger - insert into TABLE_A (active, info) values (?, ?)
SQLStatementLogger - insert into TABLE_B (A_ID) values (?)
JDBCExceptionReporter - could not insert: [com.test.B] [insert into TABLE_B (A_ID) values (?)]
java.sql.SQLException: Field 'X_ID' doesn't have a default value

I would understand if the problem is caused by specifying the entity table as "TABLE_B" and using the same for the OneToMany join table but this is what my DB model looks like.
To me it seems like Hibernate first tries to just insert the inheritance and if that would work the next insert would be the mapping between B and X. The problem is that for me the inheritance and mapping table are the same.

How should I map my DB model correctly in Hibernate? Help is much appreciated.

You can't have TABLE_B as both 'entity' table (eg table to which B is mapped) and 'join' table (eg table that holds joins between B and X ).

In the first case, TABLE_B needs to have at most one record for each TABLE_A record (that is, for those A s that are also B s); in the second case TABLE_B needs to have as many records as you have X elements in B 's collection which presents an obvious contradiction.

What you can do, therefore, is either of the following:

  • Map your Xs collection without join table ( @ManyToOne on X side; @OneToMany mappedBy="X" on B side). Your 'X_TABLE' will have to have an a_id (or b_id , whatever you call it) FK to owner.
  • Use another table ( TABLE_B_X for B -to- X mapping)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM