JPA没有将外键保存到@OneToMany关系

时间:2009-05-02 09:09:52

标签: java spring jpa

我正在使用Spring和Hibernate作为JPA提供商并且正在尝试获得@OneToMany(具有许多phonenumbers的联系人)以将外键保存在电话号码表中。从我的表单中我得到一个Contact对象,其中包含Phone(数字)列表。 Contact正确持久化(Hibernate从指定的序列中获取PK)。电话(号码)列表也会以正确的PK持久存在,但是联系人表格中没有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;
    }
}

希望我得到上面的所有相关内容,否则请告诉我。

6 个答案:

答案 0 :(得分:23)

您必须自己管理Java关系。对于这种事情你需要像:

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

  ...
}

答案 1 :(得分:6)

回答Cletus的回答。我会说在id字段上有@column注释以及所有序列内容都很重要。使用@OneToMany注释的mappedBy参数的替代方法是使用@JoinColumn注释。

另外,您需要查看addPhone的实现。它应该是类似的东西。

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

答案 2 :(得分:2)

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

phone.setContact(contact);

答案 3 :(得分:2)

如果联系电话关系是单向的,您也可以用mappedBy替换@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;

  ...
}

类似于JPA @OneToMany -> Parent - Child Reference (Foreign Key)

答案 4 :(得分:1)

如果您希望单向关系,即只能从“联系人”导航到“电话”,则需要添加

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

在您的父实体的@OneToMany下。

nullable = false 是重要的,如果您希望休眠以填充子表上的fk

答案 5 :(得分:0)

尝试此示例:

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