凤影 2011-08-15
hibernate annotation一对多的级联删除,这个问题应该困扰了很多人吧,我也是被困扰了很久,为什么hibernate没有帮我们级联删除呢。
今天终于解决这个问题,下面给个例子大家,一定是可以级联删除的,之前在网上看了很多例子都无法做到,现在总结一下,给自己和给大家一点帮助。
annotation比xml的配置方便,却总感觉没有xml的功能强大。
用annotation的例子如下:
一个产品类型可以对多个产品,所以产品类型对产品的关系式一对多,产品类型的类如下:
import java.util.ArrayList;
import java.util.List;
import org.hibernate.annotations.Cascade;
//这里一定要用hibernate的annotation,不能用javax.persistence的
import org.hibernate.annotations.CascadeType;
import javax.persistence.Entity;
import javax.persistence.*;
import javax.persistence.Table;
import cn.com.dee.common.domain.DomainObject;
import cn.com.dee.dot.ProductTypeInfo;
/**
* 产品分类
* @author Dee
*/
@Entity
@Table(name = "RuixinPRODUCTTYPE")
public class ProductType implements DomainObject {
private static final long serialVersionUID = 3590445506272821257L;
private String id;
private String code;
private String name;
private String country;
private List<Product> products = new ArrayList<Product>(); //用于级联删除
public ProductType(){
}
public ProductType(ProductTypeInfo productTypeInfo) {
this.update(productTypeInfo);
}
public void update(ProductTypeInfo productTypeInfo){
this.code = productTypeInfo.getCode();
this.name = productTypeInfo.getName();
this.country = productTypeInfo.getCountry();
}
@Id
@Column(name = "ID", columnDefinition = "INT")
@GeneratedValue()
public String getId() {
return id;
}
@Column(name = "CODE", columnDefinition = "VARCHAR(40)")
public String getCode() {
return code;
}
@Column(name = "NAME", columnDefinition = "VARCHAR(50)")
public String getName() {
return name;
}
@Column(name = "COUNTRY", columnDefinition = "VARCHAR(50)")
public String getCountry() {
return country;
}
/**
* 用于hibernate级联删除,删除了产品类型,把它下面的所有产品都一起删除
* @return
*/
@OneToMany(targetEntity = Product.class,fetch = FetchType.LAZY)
@JoinColumn(name = "type")
@Cascade(value = {CascadeType.SAVE_UPDATE, CascadeType.DELETE_ORPHAN,CascadeType.ALL})
public List<Product> getProducts() {
return products;
}
public void setCountry(String country) {
this.country = country;
}
public void setCode(String code) {
this.code = code;
}
public void setId(String id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setProducts(List<Product> products) {
this.products = products;
}
}
产品的类如下:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import cn.com.dee.common.domain.DomainObject;
import cn.com.dee.dot.ProductInfo;
/**
* @author Ken
*/
@Entity
@Table(name = "RuixinPRODUCT")
public class Product implements DomainObject {
private static final long serialVersionUID = -4611900282670726153L;
private static final Log logger = LogFactory.getLog(Product.class);
private String id;
/**
* 产品全称
*/
private String fullName;
/**
* 产品类型
*/
private ProductType type; //关联产品类型那边
// get方法
@Id
@Column(name = "ID", columnDefinition = "INT")
@GeneratedValue() //自增
public String getId() {
return id;
}
//多对一对应product_type数据库里面的主码id
@ManyToOne
@JoinColumn(name = "TYPE", referencedColumnName = "ID", unique = false)
public ProductType getType() {
return type;
}
// set方法
public void setId(String id) {
this.id = id;
}
public void setType(ProductType type) {
this.type = type;
}
}
调用hibernate底层的删除方法如下,只有调用这个方法才可以级联删除,自己写的sql语句是不能级联删除的:
public void delete(O object) { //把产品类型的对象传进来
this.getHibernateTemplate().delete(object);
}
在service层的删除方法可以这样写:
/**
* 删除产品类型,同时也删除该类型下面的产品
*/
public void delete(ProductTypeInfo typeInfo) {
//把ProductTypeInfo转换为ProductType
ProductType type = new ProductType();
type.setId(typeInfo.getId());
type.setCode(typeInfo.getCode());
type.setCountry(typeInfo.getCountry());
type.setName(typeInfo.getName());
productTypeRepository.delete(type); //调用hibernate底层的delete方法删除产品类型
}
到这里就大功告成!快去尝试一下吧,级联删除解决了,其他要怎么设计数据库,设计外键你都可以放心去做了,不会被这个搞到如此痛苦。