JPA-la persistance D'une relation unidirectionnelle à plusieurs échoue avec EclipseLink

J'essaie de persister une relation unidirectionnelle un à plusieurs très simple, mais EclipseLink (2.3.1) échoue.

Classe De Service (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;
}

Classe De Paramètres (Enfant):
(Bien sûr, il y a un champ de clé étrangère "service_id" dans la base de données, qui n'est pas représenté dans la classe, car c'est une relation unidirectionnelle).

@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;
}

Et c'est le code pour la persistance de L'entité:

    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();

Je reçois cette 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: La base de données le champ service_id A (et devrait avoir) une contrainte not-null, en raison de la nature des données.

Est-ce un bug ou quelque chose ne va pas dans le code?

23
demandé sur gamliela 2012-10-06 03:39:47

6 réponses

Essayez de supprimer la contrainte not null sur le champ service_id de la table des paramètres. Eclipselink mettra à jour la clé étrangère pour les colonnes unidirectionnelles 1:m join dans une instruction séparée, vous devrez donc désactiver ou retarder la vérification des contraintes. Le rendre bidirectionnel permettra au champ fp d'être mis à jour avec le reste des données du paramètre.

14
répondu Chris 2012-10-06 19:42:31

Utiliser nullable = false, sur @JoinColumn:

@JoinColumn(name = "service_id", nullable = false)
27
répondu William Ferreira 2016-04-11 18:18:49
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 voliation exceptions that occurs at run-time
2
répondu SreeNath 2018-07-06 14:13:35

Vous pouvez changer votre persistance pour hibernate version

1
répondu Alexander 2012-11-20 16:41:18

J'ai pu le faire fonctionner dans Oracle en utilisant une clé étrangère différable.

Exemple:

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
1
répondu jc12 2017-09-15 12:32:51

Comme je l'ai découvert, dans de tels cas, la clé étrangère est remplie dans une instruction séparée. Dans mon exemple, j'ai utilisé Address entité avec customer_id comme clé étrangère.

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]

Donc @JoinColumn avec nullable=true provoque une erreur.

, Comme alternative, vous pouvez utiliser @OneToMany (..., orphanRemoval = true, ...).

0
répondu kolobok 2014-07-08 18:02:27