在使用hibernate的情况下,很多时候都是以对象的形式对数据库进行增删改查,除非特别的业务,如复杂的联表查询需要特别的做。
这时候很多业务的crud方法都是相同的,只是操作的对象不同。
所以就用刀类泛型编程,结合hibernate一起开发的话,可以有效减少重复性代码的开发。
先定义通用的dao接口
/**
* @ClassName: IBaseDao
* @author YangXuan
* @date Aug 4, 2013 7:44:55 PM
* @param <M>
* @param <PK>
*/
public interface IBaseDao<M extends Serializable, PK extends Serializable> {
public void save(M model);
public M get(PK id);
}
然后是这个通用的 dao接口的实现
/**
* @ClassName: BaseDao
* @author YangXuan
* @date Aug 4, 2013 7:47:02 PM
* @param <M>
* @param <PK>
*/
public abstract class BaseDao<M extends Serializable, PK extends Serializable>
implements IBaseDao<M, PK> {
private Class<M> entityClass;
private HibernateTemplate ht;
@Resource(name = "hibernateTemplate")
public void setHt(HibernateTemplate ht) {
this.ht = ht;
}
@SuppressWarnings("unchecked")
@PostConstruct
public void init() { // 初始化全局参数
// 1、通过反射获取注解“M”(即模型对象)的类类型 例如有个Aaa.java , this.entityClass=Aaa.class
this.entityClass = (Class<M>) ((ParameterizedType) getClass()
.getGenericSuperclass()).getActualTypeArguments()[0];
// 2、得到模型对象的实体名 //entityName=Aaa
String entityName = ht.getSessionFactory()
.getClassMetadata(this.entityClass).getEntityName();
}
public void save(M model) {
ht.save(model);
}
@SuppressWarnings("unchecked")
public M get(PK id) {
return (M) ht.get(this.entityClass, id);
}
}
通用的service接口
/**
* @ClassName: IBaseService
* @author YangXuan
* @date Aug 4, 2013 7:56:41 PM
* @param <M>
* @param <PK>
*/
public interface IBaseService<M extends Serializable, PK extends Serializable> {
public M save(M model);
public M get(PK i);
}
通用的service接口的实现
/**
* @ClassName: BaseService
* @author YangXuan
* @date Aug 4, 2013 7:58:07 PM
* @param <M>
* @param <PK>
*/
public abstract class BaseService<M extends Serializable, PK extends Serializable>
implements IBaseService<M, PK> {
protected IBaseDao<M, PK> baseDao;
public void setBaseDao(IBaseDao<M, PK> baseDao) {
this.baseDao = baseDao;
}
public IBaseDao<M, PK> getBaseDao() {
return this.baseDao;
}
public M save(M model) {
getBaseDao().save(model);
return model;
}
public M get(PK id) {
return getBaseDao().get(id);
}
}
然后对不同对象的crud操作只需要继承这个接口和实现类就可以了,如果有特别的业务只需要写在类本身就ok,下面以操作一个为例
Product对象dao接口
/**
* @ClassName: IProductDao
* @author YangXuan
* @date Aug 4, 2013 7:51:47 PM
*/
public interface IProductDao extends IBaseDao<Product, Integer> {
}
然后是Product对象dao接口的实现
/**
* @ClassName: ProductDao
* @author YangXuan
* @date Aug 4, 2013 7:53:12 PM
*/
@Repository("productDao")
public class ProductDao extends BaseDao<Product, Integer> implements IProductDao {
}
Product对象的service接口
/**
* @ClassName: IProductService
* @author YangXuan
* @date Aug 4, 2013 7:59:56 PM
*/
public interface extends IBaseService<Product, Integer> {
}
/**
* @ClassName: ProductService
* @author YangXuan
* @date Aug 4, 2013 8:01:03 PM
*/
@Service("productService")
public class ProductService extends BaseService<Product, Integer> implements
IProductService {
@Resource(name = "productDao")
public void setProductDao(IProductDao productDao) { //这里是最需要注意的,因为数据的是通用BaseDao,所以set的时候要setBaseDao
super.setBaseDao(productDao); //之前我也是很久才发现这里出问题,因为之前set的事ProductDao
}
public IProductDao getProductDao() {
return (IProductDao) getBaseDao();
}
}