JPA OneToMany / ManyToOne关系无法正常工作 - 我缺少什么?

时间:2018-03-29 11:04:40

标签: java mysql hibernate jpa persist

我知道之前已经问了很多次,我知道这是因为我已经为我的问题搜索了每个相关问题以试图找到解决方案,但是,所提出的解决方案都没有为我和我工作我很确定我必须遗漏一些东西。

人类:

@Entity
@Table(name = "person", schema = "test")
public class PersonEntity {
    @Id
    @Column(name = "id")
    private long id;
    @Basic
    @Column(name = "name")
    private String name;
    @Basic
    @Column(name = "age")
    private int age;
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "personid")
    private List<ProjectEntity> projects;

}

项目类:

@Entity
@Table(name = "project", schema = "test")
public class ProjectEntity {
    @Id
    @Column(name = "id")
    private long id;
    @Basic
    @Column(name = "name")
    private String name;
    @Basic
    @Column(name = "budget")
    private int budget;
    @JoinColumn(name = "personid", referencedColumnName = "id")
    @ManyToOne(cascade = CascadeType.ALL)
    private PersonEntity personid;
}

我有一个双向的OneToMany / ManyToOne关系,我试过改变 级联类型为PERSIST,添加'optional = false'和更多的东西,但似乎什么都没有。

我读到我必须在持久化之前手动“加入”实体,这就是我所做的:

    em = JPAUtility.getEntityManager();
    em.getTransaction().begin();

    PersonEntity personTest = new PersonEntity();
    personTest.setName("Test");
    personTest.setAge(23);

    ProjectEntity projectTest = new ProjectEntity();
    projectTest.setName("hello");
    projectTest.setBudget(232);

    projectTest.setPersonid(personTest);

    List<ProjectEntity> projects = new ArrayList<ProjectEntity>();
    projects.add(projectTest);

    personTest.setProjects(projects);

    em.persist(personTest);
    em.getTransaction().commit();
    em.close();

    return personTest;

但我仍然明白这一点:

Caused by: 
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: 
Cannot add or update a child row: a foreign key constraint fails 
(`test`.`project`, CONSTRAINT `FK_Personid` FOREIGN KEY (`personid`) REFERENCES
 `person` (`id`) ON DELETE CASCADE ON UPDATE CASCADE)

老实说,我不知道自己错过了什么,如果有人有任何建议,我会非常乐意尝试。

非常感谢你!

由于所有的建议,我设法解决了问题,基本上,我错过了我删除的@GeneratedValue(strategy=GenerationType.AUTO)注释,因为我认为它不起作用,但它没有用,因为我错过了persistence.xml上的属性:

<property name="hibernate.id.new_generator_mappings" value="false" />

I found this info here

您还需要一种方法来在对象中添加关系:

public void addToProjects(ProjectEntity project){ project.setPersonid(this); this.projects.add(project); }

要完成这项工作,您需要在声明变量时初始化List:

private List<ProjectEntity> projects = new ArrayList<ProjectEntity>();

就是这样!

这是最终的工作代码,以防任何人发现它有用:):

人类:

@Entity
@Table(name = "person", schema = "test")
public class PersonEntity {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name = "id")
    private long id;
    @Basic
    @Column(name = "name")
    private String name;
    @Basic
    @Column(name = "age")
    private int age;
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "personid")
    private List<ProjectEntity> projects = new ArrayList<ProjectEntity>();

    public void addToProjects(ProjectEntity project) {
     project.setPersonid(this);
     this.projects.add(project);
    }
}

项目类:

@Entity
@Table(name = "project", schema = "test")
public class ProjectEntity {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name = "id")
    private long id;
    @Basic
    @Column(name = "name")
    private String name;
    @Basic
    @Column(name = "budget")
    private int budget;
    @JoinColumn(name = "personid", referencedColumnName = "id")
    @ManyToOne(cascade = CascadeType.PERSIST)
    private PersonEntity personid;

    public void setPersonid(PersonEntity personid) {
       this.personid = personid;
    }
}

确保将子项添加到其父级,反之亦然(addToProjects())

    em = JPAUtility.getEntityManager();
    em.getTransaction().begin();

    PersonEntity personTest = new PersonEntity();
    personTest.setName("Butters");
    personTest.setAge(10);

    ProjectEntity projectTest = new ProjectEntity();
    projectTest.setName("Hanks");
    projectTest.setBudget(10000);

    ProjectEntity projectTest2 = new ProjectEntity();
    projectTest2.setName("X");
    projectTest2.setBudget(100);

    personTest.addToProjects(projectTest);
    personTest.addToProjects(projectTest2);

    em.persist(personTest);

    em.getTransaction().commit();
    em.close();

希望它有所帮助!非常感谢你。

3 个答案:

答案 0 :(得分:0)

我能想到的几条线索,因为我不止一次地遇到过这样的问题:

除非您希望从Project进行级联操作以更新Person,否则您应该删除     @ManyToOne(cascade = CascadeType.ALL) 来自您的personid属性

尝试更新您的projects集合,而不是创建新集合,因为如果它已经由Hibernate管理(不需要,则执行持久/合并操作)旧的和新的。

人类:

private List<ProjectEntity> projects = new ArrayList<>();

您的代码:

 personTest.getProjects().addAll(projects);

我通常更喜欢merge而不是persist,因为我觉得它更自然&#39;有时,输出显然不一样。

答案 1 :(得分:0)

您需要注意的主要事情是正确定义关系的拥有方。据我所知,我从(有时难以理解的)官方文档中得到的结论是,拥有方几乎是默认触发级联和透明删除的方式。

例如,在上文中,您已将拥有方定义为ProjectEntity,因此级联持久性最重要的步骤是将项目添加到PersonEntity.projects

然后,您需要在关系的所有方面调用persist,即

em.persist(projectTest);

如果这没有帮助,我建议您在JPA提供程序中启用SQL日志记录,以找出它尝试执行的语句,特别是这些实体在insert编辑的顺序

根据现有评论,还要先尝试坚持不懈。 如果你这样做,我认为正确的方法是将持久实体添加到关系中,即:

PersonEntity persistedPerson = em.persist(personTest);
projectTest.setPersonId(persistedPerson);
em.persist(projectTest);

答案 2 :(得分:0)

我有同样的问题。没有@ManyToOne的原因而无法正常工作的2类。我添加了@GeneratedValue(strategy=GenerationType.AUTO),但是并不能解决我的问题。

我也尝试过重命名类,清理,关闭项目,重新启动等,但是没有任何作用。最后,我删除了文件(之前做了一个副本),然后从新文件中重新创建了文件,这解决了我的问题。我使用的是Eclipse 4.8,Spring 2.5,Groovy 2.5,Java 1.8

更新: 不确定是什么问题,无论如何(对于常规)检查您的保存方法:myUserRepo(新的MyUser (“用户名”)),还检查您的xxxxRepo << strong> MyUser ,Integer>,并检查您的文件是否为.groovy(最后一个应该不是问题)

其他更新: 如果要在2个表之间创建关系并使用保存结果,请确保在服务上使用@Transactional并链接关系字段,例如:

@Transactional
UserAccount save(UserAccount userAccount) {
    User user = userRepo.save(new User(userAccount))
    UserAccount.setUser(user)
    userAccountRepo.save(userAccount)
}