Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JPA/Hibernate分离实体传递给持久化_Hibernate_Jpa_Persistence_H2_Ejb 3.0 - Fatal编程技术网

JPA/Hibernate分离实体传递给持久化

JPA/Hibernate分离实体传递给持久化,hibernate,jpa,persistence,h2,ejb-3.0,Hibernate,Jpa,Persistence,H2,Ejb 3.0,JPA和hibernate的新手,所以请容忍我尝试绘制一张完整的图片。所以我有两个Java对象,它们具有双向关系。Employee类是拥有类,Department类是关系的反面。一个部门可以有多个员工,而一个员工只能有一个部门。我将employee_id指定为员工实体的主键,将department_id指定为department实体的主键。我还想在employee类中将department_id用作外键 雇员阶级 @Entity @Table(name = "Employee")

JPA和hibernate的新手,所以请容忍我尝试绘制一张完整的图片。所以我有两个Java对象,它们具有双向关系。Employee类是拥有类,Department类是关系的反面。一个部门可以有多个员工,而一个员工只能有一个部门。我将employee_id指定为员工实体的主键,将department_id指定为department实体的主键。我还想在employee类中将department_id用作外键

雇员阶级

    @Entity
    @Table(name = "Employee")
    public class Employee
    implements java.io.Serializable
    {
       private static final long serialVersionUID = 1L;
       //primary key
       @Id
       @GeneratedValue(strategy = GenerationType.IDENTITY)
       @Column(name = "Employee_ID")
       private Integer       id;

       //foreign key 
       @ManyToOne(cascade=CascadeType.ALL)
       @JoinColumn(name = "Department_ID")
       private Department department;

       @Column(name = "Employee_name")
       private String    name;

       public Employee() { }

       public Employee(Integer id)
       {
          this.setId(id);
       }

       public void setDepartment(Department department){
           this.department = department;
       }
       public Department getDepartment(){
           return department;
       }
       public Integer getId() { return id; }
       public void setId(Integer id) { this.id = id; }
       public String getEmployeeName(){
            return name;
        }

        public void setEmployeeName(String name){
            this.name = name;
        }
系级

@Entity
@Table(name = "Department")
public class Department
implements java.io.Serializable
{
   private static final long serialVersionUID = 1L;
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   @Column(name = "Department_ID")
   private Integer       id;

   @Column(name = "Department_name")
   private String    name;

   @OneToMany(mappedBy="department", cascade=CascadeType.ALL)
   private Collection<Employee> employees = new ArrayList<Employee>();

   public Collection<Employee> getEmployees() {return employees;}
   public void setEmployees(Collection<Employee> e){ employees = e;}

   public Department() { }

   public Department(Integer id)
   {
      this.setId(id);
   }

   public Integer getId() { return id; }
   public void setId(Integer id) { this.id = id; }
   public String getDepartmentName(){
        return name;
    }

    public void setDepartmentName(String name){
        this.name = name;
    }
最初,我试图自己设置所创建对象的主ID,但出现了“分离实体传递到持久化”错误。阅读了一篇类似的文章后,我了解到,如果我在持久化对象之前尝试设置唯一标识符,JPA会认为该实体已经存在于数据库中,它会抛出一个“分离实体传递到持久化错误”。所以我注释掉了setter函数的调用者,上面的代码运行良好。但是,如果我尝试将员工链接到一个部门,就像我使用
e1.setDepartment(d1)所做的那样
我会将此错误
分离的实体传递给persist:com.javatunes.jpa.catalog.Department
。我读过很多博客,比如和,但我仍然找不到解决这个问题的方法。还有一件事,这两个持久化函数被定义为

public void addEmployee(Employee employee) {
          em.persist(employee);
          em.flush();
          }

public void addDepartment(Department department){
          em.persist(department);
          em.flush();
          }

该错误在em.persistent(employee)中出现。

查看员工实体,您已将部门配置为级联所有 这意味着无论何时员工实体被持久化,合并、删除、刷新、分离都将对部门执行相同的操作

现在回到你的问题上来。在
populateTable
函数中 您已经创建了
部门
员工
实体 您需要像这样链接
部门
员工

e1.setDepartment(d1);

最后是persist employee,它将为您保留员工和部门

查看您的员工实体,您已将部门配置为级联所有 这意味着无论何时员工实体被持久化,合并、删除、刷新、分离都将对部门执行相同的操作

现在回到你的问题上来。在
populateTable
函数中 您已经创建了
部门
员工
实体 您需要像这样链接
部门
员工

e1.setDepartment(d1);

最后是坚持员工,这将为您坚持员工和部门

我认为问题在于您的服务级别。因为在保存
d1
service.addDepartment(d1)时,您的服务类是
@Transactional
然后当函数返回时,
d1
被分离,它不再处于持久状态,然后当您尝试保存
e1
服务时,它会进入下一行。addEmployee(e1)
包括
d1.getEmployees().add(e1)
,然后您将明显地得到
分离的实体传递给persist:
此错误。因为您的
d1
对象已经处于分离状态,并且您正在尝试将其持久化到另一个
@Transactional
方法中。我认为您可以将两种服务方法合并为一种,以保存部门和员工,此错误可以忽略,或者您可以在下一种服务方法中使用
merge
操作,如下所示:

public void addDepartment(Department department) {
    em.merge(department);
    em.flush();
}

我认为问题在于你的服务级别。因为在保存
d1
service.addDepartment(d1)时,您的服务类是
@Transactional
然后当函数返回时,
d1
被分离,它不再处于持久状态,然后当您尝试保存
e1
服务时,它会进入下一行。addEmployee(e1)
包括
d1.getEmployees().add(e1)
,然后您将明显地得到
分离的实体传递给persist:
此错误。因为您的
d1
对象已经处于分离状态,并且您正在尝试将其持久化到另一个
@Transactional
方法中。我认为您可以将两种服务方法合并为一种,以保存部门和员工,此错误可以忽略,或者您可以在下一种服务方法中使用
merge
操作,如下所示:

public void addDepartment(Department department) {
    em.merge(department);
    em.flush();
}

多亏了@Ashish451,错误在于在我的服务代码中,我保留了部门(d1)。但是,如果我尝试先链接员工(e1)和部门(d1),然后持久化该员工,JPA将不会高兴,因为部门(d1)已经被持久化,并且
persist()
仅适用于临时对象或新创建的实例。

感谢@Ashish451,错误在于我的服务代码中,我是第一被告。但是,如果我尝试先链接员工(e1)和部门(d1),然后再持久化该员工,JPA将不会高兴,因为部门(d1)已经持久化并且
persist()
仅适用于瞬态对象或新创建的实例。

我在spring boot项目中遇到了类似的问题,但这里的解决方案很容易实现。我意识到,每当您在父对象之前持久化子对象时,您总是会得到分离的持久化异常,也就是说,您不应该将Cascade.ALL约束放在子实体上。

我在spring boot项目中遇到过类似的问题,但这里的解决方案很容易实现。我意识到,每当您在父对象之前持久化子对象时,您总是会得到分离的持久化异常,也就是说,您永远不应该在子实体上放置Cascade.ALL约束