千里冰封
JAVA 浓香四溢
posts - 151,comments - 2801,trackbacks - 0
在hibernate里面调用session的delete方法以后,无论这个被删除的对象有没有被人外键引用到,都可以被删除,并且此时的外键设为null,也就是说他会自动帮我们去查看他被谁引用到了。然后把引用全部去掉后,再把自己删掉。而在JPA里面,如果调用EntityManager.remove方法时,传进去的对象,有被外键引用到,则会失败。因为JPA里面的实现就是直接执行delete语句,也不管他有没有被外键引用,此时,当然会出错了。

测试时候使用的两个类分别如下:

举的例子是部门和员工的关系。一个部门可以有多个员工。然后把部门删掉的时候,员工的部门属性就为null了,不过,按照严谨来说,还是JPA的严谨一些。这样可以防止误操作,呵呵。


部门的实体对象
/*
 * 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[id=" + id + "]";
    }
}

人员的实体对象

/*
 * 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[id=" + id + "]";
    }
}


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

<?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的代码如下:

 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的代码如下:

Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.getTransaction().begin();
        Department dept 
= (Department) session.load(Department.class2);
        session.delete(dept);
        session.getTransaction().commit();

最后发现是JPA是不能删除的,而hibernate这边的调用可以删除,一开始我还以为是toplink的实现问题,后来特意把实现改成hibernate的实现,也同样。所以有可能是JPA的要求必须得这样做,不能替我们自动完成一些东西,是利于安全。这可能就是标准和流行的差别吧。呵呵。






尽管千里冰封
依然拥有晴空

你我共同品味JAVA的浓香.
posted on 2008-10-21 08:23 千里冰封 阅读(6050) 评论(6)  编辑  收藏 所属分类: JAVAEE

FeedBack:
# re: JPA和hibernate对删除操作的不同
2008-10-21 08:44 | zd
不错  回复  更多评论
  
# re: JPA和hibernate对删除操作的不同
2008-10-21 09:34 | attend
从ORM的角度来说,我觉得hibernate的操作对点.员工和部门本来就是组合关系,员工离了部门也可以独立存在。  回复  更多评论
  
# re: JPA和hibernate对删除操作的不同
2008-10-21 09:42 | BeanSoft
很好 到底是 Oracle 的人做的JPA参考实现 考虑到了坏数据的问题 如果引用一环套一环 Hibernate 那样很容易造成大量不合要求的坏数据或者误删  回复  更多评论
  
# re: JPA和hibernate对删除操作的不同
2008-10-21 21:21 | leekiang
我用hibernate删被外键引用的数据时都删不掉,怎么你那里能删掉?是由于hibernate配置不同造成的?  回复  更多评论
  
# re: JPA和hibernate对删除操作的不同
2008-12-10 11:54 | 嗷嗷嗷
楼上的问题是配置文件里没配级联删除吧  回复  更多评论
  
# re: JPA和hibernate对删除操作的不同[未登录]
2016-04-21 23:24 | Rick
呵呵  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: