JPA OneToMany / ManyToOne关系不起作用 - 我错过了什么? [英] JPA OneToMany/ManyToOne relationship not working - What am I missing?

查看:112
本文介绍了JPA OneToMany / ManyToOne关系不起作用 - 我错过了什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道这个问题以前已经问过很多次了,我知道这是因为我已经搜索了我的问题的每个相关问题以尝试找到解决方案,但是,没有一个提议的解决方案适用于我和我我很确定我必须缺少一些东西。



人类:

  @Entity 
@Table(name =person,schema =test)
public class PersonEntity {
@Id
@Column(name =id )
私人长ID;
@Basic
@Column(name =name)
私人字符串名称;
@Basic
@Column(name =age)
private int age;
@OneToMany(cascade = CascadeType.ALL,mappedBy =personid)
private List< ProjectEntity>项目;


$ / code>

项目分类:

  @Entity 
@Table(name =project,schema =test)
public class ProjectEntity {
@Id
@Column(name =id)
私人长ID;
@Basic
@Column(name =name)
私人字符串名称;
@Basic
@Column(name =budget)
private int budget;
@JoinColumn(name =personid,referencedColumnName =id)
@ManyToOne(cascade = CascadeType.ALL)
私人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);

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

personTest.setProjects(projects);

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

return personTest;

但我仍然得到这个:

导致:
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException:
无法添加或更新子行:外键约束失败
``test`.`project`,CONSTRAINT`FK_Personid` FOREIGN KEY(`personid`)REFERENCES
`person`(`id`)ON DELETE CASCADE ON UPDATE CASCADE)



我真的不知道我错过了什么,如果有人有任何建议,我会乐于尝试。



非常感谢!




解决方案



我设法解决了所有问题,基本上,我错过了 @GeneratedValue(strategy = GenerationType.AUTO) code>注解,我删除了,因为我认为它没有工作,但它不工作,因为我在persistence.xml中缺少一个属性:



< property name =hibernate.id .new_generator_mappingsvalue =false/>



我在这里找到了这个信息 您还需要一个方法添加关系到对象中:



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



为了做到这一点,您需要在声明变量时初始化列表:



私人列表< ProjectEntity> projects = new ArrayList< ProjectEntity>();



就是这样!



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

Person类:

  @Entity 
@Table(name =person,schema =test)
public class PersonEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name =id)
私人长ID;
@Basic
@Column(name =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)
私人长ID;
@Basic
@Column(name =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;


$ / code>

请确保您将孩子添加到他们的父母和孩子-versa (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();

希望它有帮助!非常感谢。 解决方案

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



例如,在上面的例子中,您已将自己的一方定义为 ProjectEntity ,因此级联持久化工作最重要的一步是将项目添加到 PersonEntity.projects



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

  em.persist(projectTest); 

如果这没有帮助,我建议您在JPA提供程序中启用SQL日志记录看看它试图执行什么语句,特别是这些实体的顺序是什么 insert ed。



另外按照现有的评论,先试着坚持自己的观点。
如果你这样做,我相信正确的方法是将持久实体添加到关系中,即:

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


I know this has been asked a lot of times before, I know it because I've searched for every related question to my problem to try to find a solution, however, none of the proposed solutions are working for me and I'm pretty sure that I have to be missing something.

Person Class:

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

}

Project Class:

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

I have a bidirectional OneToMany/ManyToOne relationship, I have tried changing the cascade type to PERSIST, adding 'optional=false' and way more things but nothing seems to work.

I read that I have to 'join' manually the entities before the persist, and that's what I did:

    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;

But I still get this:

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)

I honestly don't know what I'm missing, if anyone has any suggestion I'll be more than happy to try it.

Thank you so much!


SOLUTION

I managed to solve the problem thanks to all the suggestions, basically, I was missing the @GeneratedValue(strategy=GenerationType.AUTO) annotation which I removed because I thought it didn't work but, it wasn't working because I was missing a property on the persistence.xml:

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

I found this info here

You also need a method to add the relationship in the objects:

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

To make this work you need to initialize the List when you declare the variable:

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

And that's it!

This is the final working code in case anyone can find it useful :):

Person Class:

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

Project Class:

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

Make sure you add the Children to their Parent and vice-versa (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();

Hope it helps! Thank you so much.

解决方案

The main thing that you will want to watch out for is to define the owning side of the relation correctly. As far as I remember, my takeaway from the (sometimes difficult to understand) official documentation was that the owning side is pretty much the one that will by default trigger cascades and transparent deletions.

For example, in the above, you have defined the owning side as ProjectEntity, so the most important step for cascaded persistence to work is to add the project to PersonEntity.projects.

You will then want to call persist on the owning side of the relation, i.e.

em.persist(projectTest);

If this doesn't help, I would suggest that you enable SQL logging in your JPA provider to find out what statements it is trying to execute, and especially in what order these entities are being inserted.

Also try, as per existing comments, to persist person first. If you do this, I believe the correct way is to add the persisted entity to the relationship, i.e:

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

这篇关于JPA OneToMany / ManyToOne关系不起作用 - 我错过了什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆