
com.github.jnoee.xo.jpa.dao.Dao Maven / Gradle / Ivy
The newest version!
package com.github.jnoee.xo.jpa.dao;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.List;
import javax.persistence.Cache;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.FlushModeType;
import javax.persistence.Id;
import javax.persistence.LockModeType;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.query.Query;
import com.github.jnoee.xo.jpa.query.Criteria;
import com.github.jnoee.xo.model.Page;
import com.github.jnoee.xo.model.PageQuery;
import com.github.jnoee.xo.utils.BeanUtils;
import com.github.jnoee.xo.utils.CollectionUtils;
import com.github.jnoee.xo.utils.StringUtils;
import lombok.Getter;
/**
* 泛型Dao。
*
* @param 业务实体类型
*/
public class Dao {
@Getter
protected Class entityClass;
@PersistenceContext
protected EntityManager entityManager;
/**
* 构造方法。
*
* @param entityClass 业务实体类
*/
public Dao(Class entityClass) {
this.entityClass = entityClass;
}
/**
* 获取EntityManagerFactory。
*
* @return 返回EntityManagerFactory。
*/
public EntityManagerFactory getEntityManagerFactory() {
return entityManager.getEntityManagerFactory();
}
/**
* 获取CriteriaBuilder。
*
* @return 返回CriteriaBuilder。
*/
public CriteriaBuilder getCriteriaBuilder() {
return entityManager.getCriteriaBuilder();
}
/**
* 创建TypedQuery。
*
* @param jpql JPQL语句
* @param values 参数值
* @return 返回TypedQuery。
*/
public TypedQuery createQuery(String jpql, Object... values) {
TypedQuery query = entityManager.createQuery(jpql, entityClass);
for (int i = 0; i < values.length; i++) {
query.setParameter(i, values[i]);
}
return query;
}
/**
* 创建Criteria。
*
* @return 返回Criteria。
*/
public Criteria createCriteria() {
return new Criteria<>(entityClass, entityManager);
}
/**
* 加载指定ID的业务实体。
*
* @param id 实体ID
* @return 返回指定ID的业务实体,如果不存在抛出异常。
*/
public E load(Serializable id) {
return entityManager.getReference(entityClass, id);
}
/**
* 获取指定ID的业务实体。
*
* @param id 实体ID
* @return 返回指定ID的业务实体,如果没有找到则返回null。
*/
public E get(Serializable id) {
return get(id, LockModeType.NONE);
}
/**
* 获取指定ID的业务实体。
*
* @param id 实体ID
* @param lockMode 锁定模式
* @return 返回指定ID的业务实体,如果没有找到则返回null。
*/
@SuppressWarnings("unchecked")
public E get(Serializable id, LockModeType lockMode) {
E entity = entityManager.find(entityClass, id, lockMode);
// 如果获取的是一个代理对象,则从代理对象中获取实际的实体对象返回。
if (entity instanceof HibernateProxy) {
entity = (E) ((HibernateProxy) entity).getHibernateLazyInitializer().getImplementation();
}
return entity;
}
/**
* 保存业务实体。
*
* @param entity 业务实体
*/
public void save(E entity) {
entityManager.persist(entity);
}
/**
* 更新业务实体。
*
* @param entity 业务实体
* @return 返回更新后的业务实体(持久状态的)。
*/
public E merge(E entity) {
return entityManager.merge(entity);
}
/**
* 强制更新业务实体。
*
* @param entity 业务实体
*/
public void forceMerge(E entity) {
detach(entity);
merge(entity);
}
/**
* 清理业务实体。
*
* @param entity 业务实体
*/
public void detach(E entity) {
entityManager.detach(entity);
}
/**
* 删除业务实体。
*
* @param entity 业务实体
*/
public void remove(E entity) {
entityManager.remove(entity);
}
/**
* 删除多个业务实体。
*
* @param entitys 业务实体列表
*/
public void remove(List entitys) {
for (E entity : entitys) {
remove(entity);
}
}
/**
* 删除指定ID的业务实体。
*
* @param id 业务实体ID
*/
public void remove(Serializable id) {
remove(get(id));
}
/**
* 删除多个指定ID的业务实体。
*
* @param ids 业务实体ID数组
*/
public void remove(Serializable[] ids) {
for (Serializable id : ids) {
remove(id);
}
}
/**
* 根据属性批量删除业务实体。
*
* @param name 属性名
* @param value 属性值
* @return 返回删除记录数。
*/
public Integer removeBy(String name, Object value) {
String sql = String.format("delete from %s where %s = :value", entityClass.getName(), name);
javax.persistence.Query query = entityManager.createQuery(sql);
query.setParameter("value", value);
return query.executeUpdate();
}
/**
* 获取所有业务实体。
*
* @return 返回指定类型的所有业务实体。
*/
public List getAll() {
Criteria criteria = createCriteria();
return criteria.toTypedQuery().getResultList();
}
/**
* 获取所有业务实体并进行排序。
*
* @param orderBy 排序的属性名
* @param isAsc 是否升序
* @return 返回排序后的指定类型的所有业务实体。
*/
public List getAll(String orderBy, Boolean isAsc) {
Criteria criteria = createCriteria();
if (isAsc) {
criteria.asc(orderBy);
} else {
criteria.desc(orderBy);
}
return criteria.toTypedQuery().getResultList();
}
/**
* 根据属性的值查找业务实体。
*
* @param name 属性名
* @param value 属性值
* @return 返回属性值相符的业务实体集合,如果没有找到返回一个空的集合。
*/
public List findBy(String name, Object value) {
Criteria criteria = createCriteria();
if (value == null) {
criteria.isNull(name);
} else {
criteria.eq(name, value);
}
return findBy(criteria);
}
/**
* 根据属性的值查找业务实体并进行排序。
*
* @param name 属性名
* @param value 属性值
* @param orderBy 排序属性
* @param isAsc 是否升序
* @return 返回排序后的属性值相符的业务实体集合,如果没有找到返回一个空的集合。
*/
public List findBy(String name, Object value, String orderBy, boolean isAsc) {
Criteria criteria = createCriteria();
if (isAsc) {
criteria.asc(orderBy);
} else {
criteria.desc(orderBy);
}
if (value == null) {
criteria.isNull(name);
} else {
criteria.eq(name, value);
}
return findBy(criteria);
}
/**
* 根据条件查找业务实体。
*
* @param criteria 查询条件
* @return 返回条件相符的业务实体集合,如果没有找到返回一个空的集合。
*/
public List findBy(Criteria criteria) {
return criteria.toTypedQuery().getResultList();
}
/**
* 判断是否存在属性重复的业务实体。
*
* @param entity 待判断的业务实体
* @param names 属性名
* @return 如果存在重复的业务实体返回false,否则返回true。
*/
public Boolean isUnique(E entity, String... names) {
Criteria criteria = createCriteria();
for (String name : names) {
criteria.eq(name, BeanUtils.getField(entity, name));
}
Object id = getId(entity);
if (id != null) {
criteria.notEq(getIdName(), id);
}
return criteria.count() == 0;
}
/**
* 根据属性的值查找唯一的业务实体。
*
* @param name 属性名
* @param value 属性值
* @return 返回指定唯一的业务实体,如果没有找到则返回null。
*/
public E findUnique(String name, Object value) {
Criteria criteria = createCriteria();
criteria.eq(name, value);
return findUnique(criteria);
}
/**
* 根据条件查找唯一的业务实体。
*
* @param criteria 查询条件
* @return 返回指定唯一的业务实体,如果没有找到则返回null。
*/
public E findUnique(Criteria criteria) {
try {
TypedQuery query = criteria.toTypedQuery();
// 启用查询缓存
query.setHint("org.hibernate.cacheable", true);
// 用于解决spring-data-jpa的审计功能bug
// 可参考:http://forum.spring.io/forum/spring-projects/data/106312-spring-data-jpa-infinite-loop-when-updating-but-not-saving-an-auditable-object
query.setFlushMode(FlushModeType.COMMIT);
return query.getSingleResult();
} catch (NoResultException e) {
return null;
}
}
/**
* 执行count查询获得记录总数。
*
* @return 返回记录总数。
*/
public Integer count() {
Criteria criteria = createCriteria();
return criteria.count();
}
/**
* 根据JPQL查询语句进行分页查询。
*
* @param jpql JPQL查询语句
* @param pageNum 待获取的页数
* @param pageSize 每页的记录数
* @param values 参数值
* @return 返回查询得到的分页对象。
*/
public Page findPage(String jpql, Integer pageNum, Integer pageSize, Object... values) {
Integer count = count(jpql, values);
if (count < 1) {
return new Page<>(pageSize);
}
Page page = new Page<>(count, pageNum, pageSize);
TypedQuery query = createQuery(jpql, values);
List list = query.setFirstResult((page.getNumber() - 1) * pageSize).setMaxResults(pageSize)
.getResultList();
page.setContents(list);
return page;
}
/**
* 根据查询条件进行分页查询。
*
* @param query TypedQuery
* @param pageNum 待获取的页数
* @param pageSize 每页的记录数
* @return 返回查询得到的分页对象。
*/
public Page findPage(TypedQuery query, Integer pageNum, Integer pageSize) {
String jpql = query.unwrap(Query.class).getQueryString();
return findPage(jpql, pageNum, pageSize);
}
/**
* 根据查询条件进行分页查询。
*
* @param criteriaQuery CriteriaQuery
* @param pageNum 待获取的页数
* @param pageSize 每页的记录数
* @return 返回查询得到的分页对象。
*/
public Page findPage(CriteriaQuery criteriaQuery, Integer pageNum, Integer pageSize) {
TypedQuery query = entityManager.createQuery(criteriaQuery);
return findPage(query, pageNum, pageSize);
}
/**
* 根据查询条件进行分页查询。
*
* @param criteria 查询条件
* @param pageNum 待获取的页数
* @param pageSize 每页的记录数
* @return 返回查询得到的分页对象。
*/
public Page findPage(Criteria criteria, Integer pageNum, Integer pageSize) {
Integer count = criteria.count();
if (count < 1) {
return new Page<>(pageSize);
}
Page page = new Page<>(count, pageNum, pageSize);
List list = criteria.toTypedQuery().setFirstResult((page.getNumber() - 1) * pageSize)
.setMaxResults(pageSize).getResultList();
page.setContents(list);
return page;
}
/**
* 根据查询条件进行分页查询。
*
* @param criteria 查询条件
* @param pageQuery 搜索模型
* @param likeFields 模糊查询字段
* @return 返回搜索得到的分页对象。
*/
public Page findPage(Criteria criteria, PageQuery pageQuery, String... likeFields) {
String keyword = pageQuery.getKeyword();
if (StringUtils.isNotBlank(keyword) && CollectionUtils.isNotEmpty(likeFields)) {
criteria.like(CollectionUtils.toList(likeFields), keyword);
}
return findPage(criteria, pageQuery.getPageNum(), pageQuery.getPageSize());
}
/**
* 获取查询所能获得的对象总数。
* 本函数只能自动处理简单的JPQL语句,复杂的JPQL查询请另行编写count语句查询。
*
* @param jpql 查询语句
* @param values 查询参数
* @return 返回查询结果总数。
*/
public Integer count(String jpql, Object... values) {
String fromJpql = "from " + StringUtils.substringBetween(jpql, "from", "order by");
String countJpql = "select count(*) " + fromJpql;
TypedQuery query = entityManager.createQuery(countJpql, Integer.class);
for (int i = 0; i < values.length; i++) {
query.setParameter(i, values[i]);
}
return query.getSingleResult();
}
/**
* 获取业务实体的缓存对象。
*
* @return 返回业务实体的缓存对象。
*/
public Cache getCache() {
return getEntityManagerFactory().getCache();
}
/**
* 清理业务实体缓存。
*/
public void evictCache() {
getCache().evict(entityClass);
}
/**
* 清理指定ID的业务实体缓存。
*
* @param id 业务实体ID
*/
public void evictCache(Serializable id) {
getCache().evict(entityClass, id);
}
/**
* 获取实体类的主键值。
*
* @param entity 业务实体
* @return 返回实体类的主键值。
*/
private Object getId(E entity) {
return getEntityManagerFactory().getPersistenceUnitUtil().getIdentifier(entity);
}
/**
* 获取实体类的主键名。
*
* @return 返回实体类的主键名。
*/
private String getIdName() {
List fields = BeanUtils.findField(entityClass, Id.class);
if (CollectionUtils.isNotEmpty(fields)) {
return fields.get(0).getName();
} else {
return null;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy