2009-05-02 35 views
14

Estoy usando Spring con Hibernate como proveedor JPA y estoy tratando de obtener un @OneToMany (un contacto que tiene muchos números de teléfono) para guardar la clave externa en la tabla de números telefónicos. Desde mi formulario, recibo un objeto de contacto que tiene una lista de teléfono (números). El contacto se conserva correctamente (Hibernate recupera un PK de la secuencia especificada). La lista de Teléfono (números) también persiste con un PK correcto, pero no hay FK en la tabla de Contactos.JPA no guarda clave externa en @OneToMany relación

public class Contact implements Serializable { 
@OneToMany(mappedBy = "contactId", cascade = CascadeType.ALL, fetch=FetchType.EAGER) 
private List<Phone> phoneList; 
} 

public class Phone implements Serializable { 
@JoinColumn(name = "contact_id", referencedColumnName = "contact_id") 
@ManyToOne 
private Contact contactId; 
} 

@Repository("contactDao") 
@Transactional(readOnly = true) 
public class ContactDaoImpl implements ContactDao { 
    @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW) 
    public void save(Contact c) { 
    em.persist(c); 
    em.flush(); 
    } 
} 


@Controller 
public class ContactController { 
    @RequestMapping(value = "/contact/new", method = RequestMethod.POST) 
    public ModelAndView newContact(Contact c) { 
    ModelAndView mv = new ModelAndView("contactForm"); 
    contactDao.save(c); 
    mv.addObject("contact", c); 
    return mv; 
    } 
} 

Afortunadamente obtuve todos los bits relevantes anteriores, de lo contrario, hágamelo saber.

Respuesta

21

Tienes que administrar las relaciones de Java tú mismo. Para este tipo de cosas necesita algo como:

@Entity 
public class Contact { 
    @Id 
    private Long id; 

    @OneToMany(cascade = CascadeType.PERSIST, mappedBy = "contact") 
    private List<Phone> phoneNumbers; 

    public void addPhone(PhoneNumber phone) { 
    if (phone != null) { 
     if (phoneNumbers == null) { 
      phoneNumbers = new ArrayList<Phone>();   
     } 
     phoneNumbers.add(phone); 
     phone.setContact(this); 
    } 
    } 

    ... 
} 

@Entity 
public class PhoneNumber { 
    @Id 
    private Long id; 

    @ManyToOne 
    private Contact contact; 

    ... 
} 
+0

Gracias, el establecimiento de las relaciones java resuelto. –

+5

¿Es correcto el método 'addPhone'? Me parece que el cheque nulo está en el lugar equivocado. –

+0

phone.setContact (esto) - ¿Podría ser una pérdida de memoria? ¿o no? –

6

En respuesta a la respuesta de Cletus. Diría que es importante tener la anotación @column en los campos de identificación, así como todas las secuencias. Una alternativa para usar el parámetro mappedBy de la anotación @OneToMany es usar la anotación @JoinColumn.

Como algo aparte de su implementación de addPhone necesita mirar. Probablemente debería ser algo así como.

public void addPhone(PhoneNumber phone) { 
    if (phone == null) { 
     return; 
    } else { 
     if (phoneNumbers == null) { 
      phoneNumbers = new ArrayList<Phone>(); 
     } 
     phoneNumbers.add(phone); 
     phone.setContact(this); 
    } 
} 
1

No creo que el método addPhone es necesario, es suficiente para establecer el contacto en el objeto móvil: phone.setContact (contacto);

-1

Si la relación de teléfono de contacto es unidireccional, también puede reemplazar mappedBy en la anotación @OneToMany con @JoinColumn(name = "contact_id").

@Entity 
public class Contact { 
    @Id 
    private Long id; 

    @OneToMany(cascade = CascadeType.PERSIST) 
    @JoinColumn(name = "contact_id") 
    private List<Phone> phoneNumbers; 

    // normal getter/setter 
    ... 
} 

@Entity 
public class PhoneNumber { 
    @Id 
    private Long id; 

    ... 
} 

similares en JPA @OneToMany -> Parent - Child Reference (Foreign Key)

Cuestiones relacionadas