JPA-Persistiendo una relación Unidireccional de Uno a Muchos falla con EclipseLink


Estoy tratando de persistir una relación Unidireccional muy simple de Uno a Muchos, pero EclipseLink (2.3.1) falla.

Clase de servicio (Padre):

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

Clase de parámetro (Hijo):
(Por supuesto, hay un campo de clave foránea" service_id " en la base de datos, que no está representado en la clase, ya que es una relación unidireccional).

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

Y este es el código para la persistencia de entidades:

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

Obtengo esta excepción:

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]

EDITAR: La base de datos field service_id tiene (y debería tener) restricción not-null, debido a la naturaleza de los datos.

¿Es esto un error o algo está mal en el código?

Author: gamliela, 2012-10-06

6 answers

Intente eliminar la restricción not null en el campo service_id de la tabla de parámetros. Eclipselink actualizará la clave foránea para columnas unidireccionales de unión 1:m en una instrucción separada, por lo que deberá deshabilitar o retrasar la comprobación de restricciones. Hacerlo bidireccional permitirá que el campo fp se actualice con el resto de los datos del parámetro.

 14
Author: Chris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-06 19:42:31

Use nullable = false, on @JoinColumn:

@JoinColumn(name = "service_id", nullable = false)
 27
Author: William Ferreira,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
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
Author: SreeNath,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-06 14:13:35

Puede cambiar su persistencia para la versión de hibernación

 1
Author: Alexander,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-20 16:41:18

Pude conseguir que funcione en Oracle mediante el uso de una clave foránea deferible.

Ejemplo:

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
Author: jc12,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-15 12:32:51

Como he averiguado, en tales casos, la clave foránea se rellena en una declaración separada. En mi ejemplo, usé Address entidad con customer_id como clave foránea.

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]

Por lo tanto, tener @JoinColumn con nullable=true causa un error.

Como alternativa, puede usar @OneToMany (..., orphanRemoval = true, ...).

 0
Author: kolobok,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-08 18:02:27