千里冰封
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"
  "//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 千里冰封 閱讀(5707) 評論(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
呵呵  回復  更多評論
  
{ganrao} 英超2020赛程表 捕鱼王者现金版2017 网络是靠什么赚钱的 棋牌游戏有哪些好玩 全民捕鱼下 大唐游戏 15选5中2个有钱吗 赚钱网游 九游棋牌官方下载 街机金蟾捕鱼 天津麻将经验 香港内部最准一头中特 不联网单机四人麻将 幸运赛车怎么看计划 香港正版四不像图 北京麻将玩法视频