郁闷小甜甜 发表于 2009-3-17 08:14:07

JPA和hibernate对删除操作的不同

在hibernate里面调用session的delete方法以后,无论这个被删除的对象有没有被人外键引用到,都可以被删除,并且此时的外键设为null,也就是说他会自动帮我们去查看他被谁引用到了。然后把引用全部去掉后,再把自己删掉。而在JPA里面,如果调用EntityManager.remove方法时,传进去的对象,有被外键引用到,则会失败。因为JPA里面的实现就是直接执行delete语句,也不管他有没有被外键引用,此时,当然会出错了。
    测试时候使用的两个类分别如下:
    举的例子是部门和员工的关系。一个部门可以有多个员工。然后把部门删掉的时候,员工的部门属性就为null了,不过,按照严谨来说,还是JPA的严谨一些。这样可以防止误操作,呵呵。

    部门的实体对象




Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.hadeslee.jpaentity;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

/**
*
* @author hadeslee
*/
@Entity
@Table(name = "JPADepartment")
public class Department implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    @OneToMany(mappedBy = "department")
    private Set<Person> persons = new HashSet<Person>();
    private String deptName;
    private String description;

    public String getDeptName() {
      return deptName;
    }

    public void setDeptName(String deptName) {
      this.deptName = deptName;
    }

    public String getDescription() {
      return description;
    }

    public void setDescription(String description) {
      this.description = description;
    }
   
    public Set<Person> getPersons() {
      return persons;
    }

    public void setPersons(Set<Person> persons) {
      this.persons = persons;
    }

    public Long getId() {
      return id;
    }

    public void setId(Long id) {
      this.id = id;
    }

    @Override
    public int hashCode() {
      int hash = 0;
      hash= (id != null ? id.hashCode() : 0);
      return hash;
    }

    @Override
    public boolean equals(Object object) {
      // TODO: Warning - this method won't work in the case the id fields are not set
      if (!(object instanceof Department)) {
            return false;
      }
      Department other = (Department) object;
      if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
            return false;
      }
      return true;
    }

    @Override
    public String toString() {
      return "com.hadeslee.jpaentity.Department";
    }
}

    人员的实体对象






Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.hadeslee.jpaentity;

import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

/**
*
* @author hadeslee
*/
@Entity
@Table(name = "JPAPerson")
public class Person implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;
    private String name;
    private int age;
    @ManyToOne
    private Department department;

    public int getAge() {
      return age;
    }

    public void setAge(int age) {
      this.age = age;
    }

    public Department getDepartment() {
      return department;
    }

    public void setDepartment(Department department) {
      this.department = department;
    }

    public String getName() {
      return name;
    }

    public void setName(String name) {
      this.name = name;
    }

    public Integer getId() {
      return id;
    }

    public void setId(Integer id) {
      this.id = id;
    }

    @Override
    public int hashCode() {
      int hash = 0;
      hash= (id != null ? id.hashCode() : 0);
      return hash;
    }

    @Override
    public boolean equals(Object object) {
      // TODO: Warning - this method won't work in the case the id fields are not set
      if (!(object instanceof Person)) {
            return false;
      }
      Person other = (Person) object;
      if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
            return false;
      }
      return true;
    }

    @Override
    public String toString() {
      return "com.hadeslee.jpaentity.Person";
    }
}

   
               

    由于JPA是不需要配置的,代码里面已经包括了注释,所以下面附上Hibernate的映射文件,为了使数据库里面更清楚一些,所以两者使用的表不是同一张表,JPA的表是带JPA前缀的,用@Table这个注释声明了这一点。




Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--><?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.hadeslee.jpaentity">
    <class name="Department" table="Department">
      <id name="id" column="departId" type="long">
            <generator class="native"/>
      </id>
      <property name="deptName"/>
      <property name="description"/>
      <set name="persons">
            <key column="deptId"/>
            <one-to-many class="Person"/>
      </set>
    </class>
    <class name="Person" table="Person">
      <id name="id" column="personId" type="long">
            <generator class="native"/>
      </id>
      <property name="name"/>
      <property name="age"/>
      <many-to-one name="department" column="deptId" class="Department"/>
   </class>
</hibernate-mapping>
    调用JPA的代码如下:






Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--> EntityManagerFactory emf = Persistence.createEntityManagerFactory("TestSSH1PU2");
      EntityManager em = emf.createEntityManager();
      em.getTransaction().begin();
      com.hadeslee.jpaentity.Person p = new com.hadeslee.jpaentity.Person();
      p.setAge(26);
      p.setName("千里冰封");

      com.hadeslee.jpaentity.Department dept = em.find(com.hadeslee.jpaentity.Department.class, Long.valueOf("3"));
      System.out.println("找到的dept="   dept);
      em.remove(dept);
      em.getTransaction().commit();
    调用hibernate的代码如下:






Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->Session session = HibernateUtil.getSessionFactory().getCurrentSession();
      session.getTransaction().begin();
      Department dept = (Department) session.load(Department.class, 2);
      session.delete(dept);
      session.getTransaction().commit();
    最后发现是JPA是不能删除的,而hibernate这边的调用可以删除,一开始我还以为是toplink的实现问题,后来特意把实现改成hibernate的实现,也同样。所以有可能是JPA的要求必须得这样做,不能替我们自动完成一些东西,是利于安全。这可能就是标准和流行的差别吧。呵呵。上一页
页: [1]
查看完整版本: JPA和hibernate对删除操作的不同