【问题标题】:JPA not saving foreign key to @OneToMany relationJPA 未将外键保存到 @OneToMany 关系
【发布时间】:2010-10-23 07:17:05
【问题描述】:

我正在将 Spring 与 Hibernate 一起用作 JPA 提供程序,并试图获取 @OneToMany(具有多个电话号码的联系人)以将外键保存在电话号码表中。从我的表单中,我得到一个包含电话(号码)列表的联系人对象。 Contact 得到正确持久化(Hibernate 从指定的序列中获取一个 PK)。 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;
    }
}

希望我得到了以上所有相关信息,否则请告诉我。

【问题讨论】:

    标签: java spring jpa


    【解决方案1】:

    试试这个示例:

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

    【讨论】:

      【解决方案2】:

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

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

      在您父实体的@OneToMany 下。

      nullable = false IS VITAL 如果您希望休眠填充子表上的 fk

      【讨论】:

      • 这个对我很有帮助。 Nullable 自动确保在子表中插入键。你是救世主!!
      【解决方案3】:

      您必须自己管理 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;
      
        ...
      }
      

      【讨论】:

      • addPhone 方法是否正确?在我看来,空检查在错误的地方。
      • phone.setContact(this) - 可能是内存泄漏?还是不行?
      • 为什么我必须自己管理java关系?如果我有单向关系怎么办?
      • @FagnerBrack 如果Phone 类上没有@ManyToOne,hibernate 将创建一个表来管理关系,就像CONTACT_PHONE 一样,hibernate 会将所需的记录插入到该表中。
      【解决方案4】:

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

      phone.setContact(contact);
      

      【讨论】:

        【解决方案5】:

        如果 Contact-Phone 关系是单向的,您还可以将 @OneToMany 注释中的 mappedBy 替换为 @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)

        【讨论】:

          【解决方案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);
              }
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2019-01-12
            • 2016-07-09
            • 1970-01-01
            • 2020-11-03
            • 2020-05-17
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多