JPA - Persisting a Unidirectional One to Many relationship fails with EclipseLink

耗尽温柔 提交于 2019-12-03 19:01:13

问题


I'm trying to persist a very simple Unidirectional One to Many relationship, but EclipseLink (2.3.1) fails.

Service Class (Parent):

@Entity
@Table(name = "tbl_service2")
public class Service implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="service_id")
    public long serviceID;

    @Column(name="name")
    public String name;

    @OneToMany(cascade={CascadeType.ALL})
    @JoinColumn(name="service_id", referencedColumnName="service_id")
    public Set<Parameter> parameters;
}

Parameter Class (Child):
(Of course there is "service_id" foreign key field in the database, which is not represented in the class, as it's unidirectional relation).

@Entity
@Table(name = "tbl_service_parameters2")
public class Parameter implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="param_id")
    public long parameterID;

    @Column(name="name")
    public String name;
}

And this is the code for Entity persistence:

    Service service = new Service();
    service.parameters = new HashSet<Parameter>();
    service.name = "test";
    Parameter param = new Parameter();
    param.name = "test";
    service.parameters.add(param);
    em.persist(service);
    em.flush();

I get this exception:

Internal Exception: java.sql.SQLException: Field 'service_id' doesn't have a default value
Error Code: 1364
Call: INSERT INTO tbl_service_parameters2 (name) VALUES (?)
    bind => [test]

EDIT: The database field service_id has (and should have) not-null constraint, due the nature of the data.

Is this a bug or is something wrong in the code?


回答1:


Try removing the not null constraint on the Parameter table's service_id field. Eclipselink will update the foreign key for unidirectional 1:m join columns in a separate statement, so you'll need to disable or delay the constraint check. Making it bidirectional will allow the fp field to be updated with the rest of the parameter data.




回答2:


Use nullable = false, on @JoinColumn:

@JoinColumn(name = "service_id", nullable = false)



回答3:


You can change your persistence for hibernate version<4.0 and your code will run well."Well" in reference " for one-to-many relation save/persist parent ONLY, NOT save/persist child's collection by separate task"




回答4:


I was able to get it to work in Oracle by using a deferrable foreign key.

Example:

ALTER TABLE my_table ADD CONSTRAINT my_constraint_name FOREIGN KEY (my_table_column) REFERENCES foreign_key_table  (foreign_key_table_column) DEFERRABLE INITIALLY DEFERRED



回答5:


As I found out, in such cases, foreign key is filled in a separate statement. In my example, I used Address entity with customer_id as foreign key.

2014-07-08T20:51:12.752+0300|FINE: INSERT INTO ADDRESS (address_id, street, city, region) VALUES (?, ?, ?, ?)
    bind => [10, foo, foo, foo]
2014-07-08T20:51:12.753+0300|FINEST: Execute query InsertObjectQuery(ua.test.customer.Address@28cef39d)
2014-07-08T20:51:12.757+0300|FINEST: Execute query DataModifyQuery(sql="UPDATE ADDRESS SET customer_id = ? WHERE (address_id = ?)")
2014-07-08T20:51:12.757+0300|FINE: UPDATE ADDRESS SET customer_id = ? WHERE (address_id = ?)
    bind => [151, 10]

Therefore, having @JoinColumn with nullable=true causes an error.

As alternative, you can use @OneToMany (..., orphanRemoval = true, ...).




回答6:


By default nullable is true on @JoinColumn, while persisting the data in one to many relationship, we need to make nullable as false to avoid data violation exceptions that occurs at run-time.



来源:https://stackoverflow.com/questions/12755380/jpa-persisting-a-unidirectional-one-to-many-relationship-fails-with-eclipselin

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!