不知道从何说起,就从entity说吧, hibernate集成了jpa以后,entity和数据库表直接的配置就简单了,就目前而言我们使用关系数据库都很少建表关系了,一般都是通过代码事物去管理。entity的配置如下:
@Entity
@Table(name="test")
@NamedStoredProcedureQueries({
@NamedStoredProcedureQuery(name = "test", procedureName = "sp_tesp_out", parameters = {
@StoredProcedureParameter(mode = ParameterMode.IN, name = "i_test", type = Long.class),
@StoredProcedureParameter(mode = ParameterMode.OUT, name = "o_test", type = Float.class) }) })
public class Test{
private Integer id;
private String name;
private int userId;
@Transient
private String userName;
......
}
@Entity标注为这个类是一个实体,@Table(name="test")标注为数据库对应的表,@Transient注解表示数据库中没有此字段,我们在java代码又要用到此字段时添加此注解,@NamedStoredProcedureQueries这是调用存储过程的一个注解,第一个name 在到层通过此名称调用,procedureName 存储过程名称,@StoredProcedureParamete定义存储过程参数,包括输入输出,参数名称,参数类型。 现在该说dao了,首先我会写一个base接口,写一些通用的方法,代码如下:
@NoRepositoryBean
public interface BaseRepository<T,K extends Serializable> extends JpaRepository<T,K>,JpaSpecificationExecutor<T> {
List<T> findAll(String fields,Specification<T> spec);
Page<T> findAll(String fields,Specification<T> spec, Pageable pageable);
}
BaseRepository接口中可以写一些通用的方法,以便代码的重用
public interface TestDao extends BaseRepository<TestDao ,Integer>,Test{
@Query("from Test f where f.id=?1")
public selectOne getById (Integer id);
}
hibernate封装了很多方法,继承一下就可以了,也可以同@Query注解写自己想要sql,这样写的缺点是每个参数都必须传,这样写的sql不是用表名而是用entity的类名,如果想按条件查询这就不行了,没问题,强大的hibernate早想到这一点了,只要实现这个接口就可以拼装复杂的hql了,代码如下:
public class TestDaoImpl extends TestDao {
@PersistenceContext
private EntityManager em;
public List<Test> query(Test m){
String hql =" select m from Test m where 1 = 1";
if(m.getName != null && !"".equals(m.getName)){
hql+=" and m.name like ' "+m.getName+"%'";
}
Query query = em.createQuery(hql);
List<Test> list=query.getResultList();
return list;
}
}
调用存储过程
@Procedure(name="test")
public void Test( @Param("i_test")String orderCodes);
@Procedure 中的name对应entiy中的存储过程名称,@Param存储过程中需要传人的参数。
hql的使用
public class TestDaoImpl{
@PersistenceContext
private EntityManager em;
public Page<Test> getList(TestVo vo){
Page<Test> result=null;
String hql="from Test b where b.id is null";
String countHql="select count(*) from Test b where b.id is null";
String param="";
param=createParam(vo);
hql +=param;
countHql += param;
Query query = em.createQuery(hql);
Query countQuery = em.createQuery(countHql);
long total =Long.parseLong(countQuery.getResultList().get(0).toString());
int start = pageInfo.getCurPage()*pageInfo.getPageSize();
if (total>0&&start<total && pageInfo.getPageSize()>0){
query.setFirstResult(start);
query.setMaxResults(pageInfo.getPageSize());
}
if (pageInfo.getPageSize()<=0) {
query.setFirstResult(start);
pageInfo.setPageSize((int)total);
query.setMaxResults((int)total);
}
List<Test> list=query.getResultList();
result = new PageImpl<Test>(list, new PageRequest(pageInfo.getCurPage(), pageInfo.getPageSize()), total);
return result;
}
}
createParam这是封装查询条件的一个方法,Page是spring的一个分页类(org.springframework.data.domain.Page), EntityManager是jpa封装的一个接口,具体没详细研究,通过@PersistenceContext注解调用就可以了。
service层
public interface SpecialAreaService extends BaseService<SpecialArea>{}
servic层我们一般会继承一个公共的方法,以便实现代码的重用。
@SuppressWarnings("rawtypes")
public interface BaseService<T extends BaseDomain> {
/**
* 保存数据,自动生成id<br/>
* 不支持复合主键生成,使用复合主键请覆盖此方法实现保存
* @param t
* @return
* @throws ServiceException
*/
public <E extends BaseDomain<E>> Result<E> save(E t) throws ServiceException;
public <E extends BaseDomain<E>> Result<Integer> delete(E t) throws ServiceException;
public <E extends BaseDomain<E>> Result<Integer> update(E t) throws ServiceException;
public <E extends BaseDomain<E>> Result<E> get(E t) throws ServiceException;
public Result<List<T>> findAll() throws ServiceException;
public Result<List<T>> findAll(T t) throws ServiceException;
/**
* 查询指定的属性值
* @param fields 属性名称,多个以逗号分隔
* @param t
* @return
* @throws ServiceException
*/
public Result<List<T>> findAll(String fields,T t) throws ServiceException;
public Result<Page<T>> findAll(T t,Pageable pageable) throws ServiceException;
/**
* 分页查询指定的属性值
* @param fields 属性名称,多个以逗号分隔
* @param t
* @return
* @throws ServiceException
*/
public Result<Page<T>> findAll(String fields,T filter,Pageable pageable) throws ServiceException;
public Result<T> findOne(T t) throws ServiceException;
}```
page是调用spring的一个分页接口
在: spring-data-commons这个jar中
org.springframework.data.domain.Page
Result是自己写的一个结果集封装,这个可以自己定义。
在这个接口中,可写自定义方法。
**serviceImpl层**
具体的业务实现层
@Service
@Transactional
public class SpecialAreaServiceImpl extends DefaultService<SpecialArea> implements SpecialAreaService {
@Resource
private SpecialAreaDao dao;
@Override
public BaseRepository getMainDao() {
return dao;
}
@Override
protected Specification<SpecialArea> buildSpec(final SpecialArea t) {
return new Specification<SpecialArea>(){
@Override
public Predicate toPredicate(Root<SpecialArea> root,
CriteriaQuery<?> query, CriteriaBuilder cb) {
Predicate result = null;
if (t != null){
if(StringUtils.isNotBlank(t.getProvince())){
Path<String> nameExp = root.get("province");
if(StringUtils.isNotBlank(t.getProvince())){
result = cb.equal(nameExp,t.getProvince());
}
}
if(StringUtils.isNotBlank(t.getCity())){
Path<String> nameExp = root.get("city");
if(StringUtils.isNotBlank(t.getCity())){
result = cb.equal(nameExp,t.getCity());
}
}
if(StringUtils.isNotBlank(t.getRegion())){
Path<String> nameExp = root.get("region");
if(StringUtils.isNotBlank(t.getCity())){
result = cb.equal(nameExp,t.getRegion());
}
}
if(StringUtils.isNotBlank(t.getRemark())){//备注
Path<String> nameExp = root.get("remark");
if(StringUtils.isNotBlank(t.getRemark())){
result = cb.like(nameExp,"%"+t.getRemark()+"%");
}}
}
return result;
}
};
}
}
@Service用于spring的service的依赖注入,只有有这个注解
@Resource private SpecialAreaService service;
在调用的时候才能获取的到实例。
buildSpec这个方法是用于hibernate的findAll方法的查询配置。
@Transactional是spring的事物注解配置,这里还有相关的配置就不细说了。