在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
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
return persons;
}
public void setPersons(Set
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 + "]";
}
}
人員的實體對象
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[id=" + id + "]";
}
}
由於JPA是不需要配置的,代碼裡面已經包括了注釋,所以下面附上Hibernate的映射文件,為了使數據庫裡面更清楚一些,所以兩者使用的表不是同一張表,JPA的表是帶JPA前綴的,用@Table這個注釋聲明了這一點。
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
-->
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.Net/hibernate-mapping-3.0.dtd">
調用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的要求必須得這樣做,不能替我們自動完成一些東西,是利於安全。這可能就是標准和流行的差別吧。呵呵。