千里冰封
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 千里冰封 阅读(5968) 评论(6)  编辑  收藏 所属分类: javaee

feedback:
# re: jpa和hibernate对删除操作的不同
2008-10-21 08:44 |
不错  回复  
  
# re: jpa和hibernate对删除操作的不同
2008-10-21 09:34 |
从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 |
呵呵  回复  
  
网站地图