sophia0 2012-03-21
hibernateannotation一对多的级联删除,这个问题应该困扰了很多人吧,我也是被困扰了很久,为什么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; /** * 产品分类 */ @Entity @Table(name = "PRODUCTTYPE") 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; @Entity @Table(name = "PRODUCT") 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语句是不能级联删除的:
publicvoiddelete(Oobject){//把产品类型的对象传进来
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方法删除产品类型 }
到这里就大功告成!快去尝试一下吧,级联删除解决了,其他要怎么设计数据库,设计外键你都可以放心去做了,不会被这个搞到如此痛苦。