2012-02-28 25 views
12

estoy usando JPA2 con la implementación EclipseLinkmapeo @ManyToOne no puede guardar ID padres

! [Estructura de la tabla simple] [1]

Aquí están las dos tablas que intento trazar y la Anotaciones JPA.

public class Story implements Serializable{ 
    @Id 
    @GeneratedValue(strategy = GenerationType.SEQUENCE) 
    Integer id; 
    @Temporal(TemporalType.TIMESTAMP) 
    @Column (name="DATE_CREATED") 
    Date dateCreated; 
    String title; 
    String description; 
    @Column(name="AUTHOR_ID") 
    Integer authorId; 
    @Column(name="COUNTRY_ID") 
    Integer countryId; 
    private String reviews; 

    @OneToMany(mappedBy = "story", cascade=CascadeType.ALL) 
    private List<Tip> tipList; 
} 

public class Tip implements Serializable{ 
    @Id 
    @GeneratedValue(strategy = GenerationType.SEQUENCE) 
    private Integer id; 
    private String description; 
    private Integer vote; 

    @ManyToOne (cascade=CascadeType.ALL) 
    @JoinColumn(name="STORY_ID", referencedColumnName="ID") 
    private Story story; 
} 

Como un ejemplo simple, me gustaría insistir en una historia y algunos consejos relacionados con la historia en la misma transacción. Aquí es la sección de código que hace que:

Story newStory = new Story(title, body, ...); 

EntityTransaction transaction = em.getTransaction().begin(); 
    boolean completed = storyService.create(newStory); 
    //The tips are saved as a List<String>. This methods creates the needed List<Tip> from the Strings 
    List<Tip> tips = TipUtil.getTipList(tipList); 
    newStory.setTipList(tips) 
transaction.commit(); 

que no tienen errores y todas las entidades que se conservan en la base de datos. El problema es que en la tabla de sugerencias el campo story_id siempre es NULL. Me imagino que JPA no puede obtener el nuevo id de la tabla de la historia. ¿Cuál es el enfoque correcto aquí?

LE

En el estado actual del código, las entidades Tip se conservan pero el identificador de país sigue siendo nula.

Respuesta

6

Con JPA, siempre se recomienda actualizar la relación en ambos lados en una relación bidireccional. Esto es para asegurar que los datos sean consistentes en su capa de aplicación y nada que ver con la base de datos.

Sin embargo, es obligatorio que actualice el lado propietario de la relación en una relación bidireccional.

Por lo tanto, el ajuste/no establecer

story.setTipList(tips) 

depende de usted. Pero si quieres que los cambios reflejan adecuadamente en el PP entonces usted ruido de fondo llamar

tip.setStory(story) 

como Tip es el lado propietario aquí, como por su código. También me parece que su código es incompleto. Razones es,

  • la entidad devuelta por storyService.create(newStory) se gestiona pero no el newStory. Por lo tanto, solo configurar newStory.setTipList(tips) no actualizará el db
5

Porque necesita actualizar la historia del enlace principal en cada uno de sus hijos.

La manera en que se hace es crear un método addTip (Tip tip) en su clase Story.

Este método hace:

tip.setStory(this); 
tipList.add(tip); 

Si usted no necesita enfoque bedirectional, puede quitar el campo de la historia en el consejo y se resolverá el problema

+1

Me pregunto si no hay una forma más automática de hacerlo. Además, realmente no creo que eliminar el campo de historia en Tip sería una buena idea, porque de esta manera, tendría que deshacerse de la '@PrimaryKeyJoinColumn (name =" STORY_ID ", referenciadoColumnName =" ID ") ', dejando a JPA sin ninguna pista sobre cómo debería unirse. Esto es lo que entendí de leer un poco sobre el tema. Por favor, avíseme si me equivoco. – Dragos

+0

Ebean tiene una solución automática para este, pero las implementaciones de JPA no ofrecen una solución automática. – Palesz

0

No se debe utilizar PrimaryKeyJoinColumn, justo JoinColumn, pero tener su clase completa ayudaría a dar una respuesta determinada.

PrimaryKeyJoinColumn solo se usaría si el story_id fuera también el id del Tip (sin id en Tip) y hubiera un mapeo básico duplicado para él. Rara vez se debe utilizar, y ya no se requiere en JPA 2.0 ya que las asignaciones de identificación duplicadas ya no son necesarias.

+0

¡Hola! ¡Gracias por su respuesta! Actualicé mi pregunta Agregué todos los atributos de entidad y los cambios que tuvieron lugar después de cambiar la anotación '@ PrimaryKeyJoinColumn'. Espero que esté más claro ahora. – Ionut

1

Retire la

@Column (name = "story_id") privada Entero storyid;

Ya está declarando en @JoinColumn (name = "story_id", referencedcolumnname = "ID")

Es por eso que está recibiendo el error varias asignaciones de escritura existen para el campo [tip.STORY_ID]

+0

Gracias! De hecho, no hay otro error, pero las entidades 'Tip' ya no persisten – Ionut

+0

Dependiendo de la implementación, en una relación bidireccional hay que establecer las dos formas de la relación (no estoy seguro de si en eclipselink es así, pero podría vale la pena intentarlo). Por lo tanto, intente configurar newStory en cada una de las sugerencias de la lista. Además, la línea "boolean completed = storyService.create (newStory);" sería más lógico colocarlo justo antes de transaction.commit; – Pau

Cuestiones relacionadas