简体   繁体   English

JPA 不将外键保存到@OneToMany 关系

[英]JPA not saving foreign key to @OneToMany relation

I'm using Spring with Hibernate as a JPA provider and are trying to get a @OneToMany (a contact having many phonenumbers) to save the foreign key in the phone numbers table.我正在使用 Spring 和 Hibernate 作为 JPA 提供程序,并试图获取 @OneToMany(具有多个电话号码的联系人)以将外键保存在电话号码表中。 From my form i get a Contact object that have a list of Phone(numbers) in it.从我的表格中,我得到一个联系人 object,其中包含电话(号码)列表。 The Contact get persisted properly (Hibernate fetches an PK from the specified sequence). Contact 得到正确的持久化(Hibernate 从指定的序列中获取 PK)。 The list of Phone(numbers) also gets persisted with a correct PK, but there's no FK to the Contacts table. Phone(numbers) 列表也使用正确的 PK 进行保存,但 Contacts 表没有 FK。

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

Hopefully I got all of the relevant bits above, otherwise please let me know.希望我得到了上面所有的相关位,否则请告诉我。

You have to manage the Java relationships yourself.您必须自己管理 Java 关系。 For this kind of thing you need something like:对于这种事情,你需要这样的东西:

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

  ...
}

In reply to Cletus' answer.回复 Cletus 的回答。 I would say that it's important to have the @column annotation on the id fields, as well as all the sequence stuff.我会说在 id 字段以及所有序列内容上都有@column注释很重要。 An alternative to using the mappedBy parameter of the @OneToMany annotation is to use the @JoinColumn annotation.使用的参数的mappedBy的替代@OneToMany注释是使用@JoinColumn注解。

As a kinda aside your implementation of addPhone needs looking at.顺便说一下,您需要查看 addPhone 的实现。 It should probably be something like.它应该是类似的。

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

If the Contact-Phone relationship is unidirectional, you can also replace mappedBy in @OneToMany annotation with @JoinColumn(name = "contact_id") .如果 Contact-Phone 关系是单向的,你也可以用mappedBy @JoinColumn(name = "contact_id")替换@OneToMany注解中的@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 in JPA @OneToMany -> Parent - Child Reference (Foreign Key)类似于JPA @OneToMany -> Parent - Child Reference (Foreign Key)

我不认为addPhone方法是必要的,你只需要在电话对象中设置联系人:

phone.setContact(contact);

If you want your relationship unidirectional ie can navigate from Contact to Phone's only, you need to add如果您希望您的关系单向,即只能从联系人导航到电话,则需要添加

@JoinColumn(name = "contact_id", nullable = false)

Under your @OneToMany on your parent entity.在您的父实体上的@OneToMany下。

nullable = false IS VITAL if you want hibernate to populate the fk on the child table nullable = false IS VITAL如果您希望休眠在子表上填充 fk

Try this sample:试试这个示例:

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

    @JoinColumn(name = "contactId")
    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
    private Set<Phone> phones;
}

@Entity
public class Phone {
    @Id
    private Long id;
    private Long contactId;
}

In JPA this helped me在 JPA 这对我有帮助

contact.getPhoneList().forEach(pl -> pl.setContact(contact));
contactRepository.save(contact);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM