Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 495
gamliela Avatar asked Oct 05 '12 23:10

gamliela


5 Answers

Use nullable = false, on @JoinColumn:

@JoinColumn(name = "service_id", nullable = false)
like image 122
William Ferreira Avatar answered Oct 02 '22 07:10

William Ferreira


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.

like image 30
Chris Avatar answered Oct 02 '22 07:10

Chris


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"

like image 37
Alexander Avatar answered Oct 02 '22 07:10

Alexander


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
like image 28
jc12 Avatar answered Oct 02 '22 07:10

jc12


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.

like image 33
SreeNath Avatar answered Oct 02 '22 07:10

SreeNath