Pregunta

Estoy usando Spring con Hibernate como proveedor de 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 de teléfono. De mi formulario obtengo un objeto de contacto que tiene una lista de teléfonos (números). El contacto persiste correctamente (Hibernate obtiene una PK de la secuencia especificada). La lista de teléfonos (números) también se mantiene con una PK correcta, pero no hay FK en la tabla Contactos.

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

Espero haber obtenido todos los bits relevantes anteriores, de lo contrario, hágamelo saber.

¿Fue útil?

Solución

Tienes que gestionar las relaciones Java tú mismo. Para este tipo de cosas necesitas 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 Phone {
  @Id
  private Long id;

  @ManyToOne
  private Contact contact;

  ...
}

Otros consejos

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 al uso del parámetro mappedBy de la anotación @OneToMany es usar la anotación @JoinColumn .

Como un poco aparte, su implementación de addPhone debe analizarse. Probablemente debería ser algo así.

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

Si la relación contacto-teléfono 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;

  ...
}

Similar en JPA @OneToMany - > Principal - Referencia secundaria (clave externa)

No creo que el método addPhone sea necesario, solo tiene que configurar el contacto en el objeto del teléfono:

phone.setContact(contact);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top