java - manytoone - eclipselink que es
JPA: la relaciĆ³n de persistencia de uno a varios unidireccional falla con EclipseLink (6)
Como descubrí, en tales casos, la clave externa se rellena en una declaración por separado. En mi ejemplo, utilicé la entidad de Address
con customer_id
como clave externa.
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 @JoinColumn
nullable=true
provoca un error.
Como alternativa, puede usar @OneToMany (..., orphanRemoval = true, ...)
.
Estoy tratando de persistir en una relación unidireccional de uno a muchos muy simple, 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 (niño):
(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 la entidad:
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();
Me sale 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: El campo de base de datos service_id
tiene (y debería tener) una restricción no nula, debido a la naturaleza de los datos.
¿Es esto un error o algo está mal en el código?
Intente eliminar la restricción no nula en el campo service_id de la tabla de parámetros. Eclipselink actualizará la clave foránea para columnas unidireccionales 1: m en una declaración separada, por lo que deberá deshabilitar o retrasar la verificación de restricciones. Si se hace bidireccional, el campo fp se actualizará con el resto de los datos de parámetros.
Pude hacer que funcionara en Oracle mediante el uso de una clave externa diferible.
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
Puede cambiar su persistencia para la versión de hibernación <4.0 y su código se ejecutará bien. "Bien" en referencia "para relación de uno a varios SÓLO para padres / persistencias, NO guardar / persistir la recopilación del niño por tarea separada"
Use nullable = false
, en @JoinColumn
:
@JoinColumn(name = "service_id", nullable = false)
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