1 /** 2 * 3 */ 4 package pw.lizi.base; 5 6 import java.io.Serializable; 7 import java.lang.reflect.ParameterizedType; 8 import java.lang.reflect.Type; 9 import java.util.ArrayList; 10 import java.util.Collection; 11 import java.util.LinkedHashMap; 12 import java.util.List; 13 import java.util.Map; 14 15 import javax.annotation.Resource; 16 import javax.persistence.EntityManager; 17 import javax.persistence.Query; 18 19 import org.slf4j.Logger; 20 import org.slf4j.LoggerFactory; 21 import org.springframework.transaction.annotation.Propagation; 22 import org.springframework.transaction.annotation.Transactional; 23 24 import pw.lizi.util.AssertUtil; 25 import pw.lizi.util.CollectionUtil; 26 import pw.lizi.util.StringUtil; 27 28 /** 29 * 说明: 30 * 34 * 2018年9月29日 下午2:03:17 35 */ 36 @SuppressWarnings("unchecked") 37 @Transactional 38 public abstract class BaseServiceImpl<T, ID> implements BaseService<T, ID> { 39 40 static Logger log = LoggerFactory.getLogger(BaseServiceImpl.class); 41 42 //实体类class 43 private Class<T> entityClass = null; 44 45 //ID字段的class 46 private Class<ID> idClass = null; 47 48 { 49 50 //getSuperclass 返回直接继承的父类(由于编译擦除,没有显示泛型参数) 51 //getGenericSuperclass 返回直接继承的父类(包含泛型参数) 52 Type type = getClass().getGenericSuperclass(); 53 54 //解决多层继承拿泛型类型 //BaseServiceImpl<User> <- UserService <- PassportService 55 while(!(type instanceof ParameterizedType)){ 56 type = ((Class<?>)type).getGenericSuperclass(); 57 //为了避免写错代码出现死循环,加上这个保险。 58 if(type == null || "java.lang.Object".equals(type.getClass())){ 59 break; 60 } 61 } 62 63 if(type instanceof ParameterizedType){ 64 ParameterizedType parameterizedType = (ParameterizedType)type; 65 Type[] genericTypies = parameterizedType.getActualTypeArguments(); 66 entityClass = (Class<T>)genericTypies[0]; 67 idClass = (Class<ID>)genericTypies[1]; 68 } 69 } 70 71 /** 72 * 从strter-jpa里面取出entityManager 73 */ 74 @Resource 75 protected EntityManager entityManager; 76 77 /* (non-Javadoc) 78 * @see pw.lizi.base.BaseService#save(T) 79 */ 80 @Override 81 public void save(T entity){ 82 entityManager.persist(entity); 83 } 84 85 /* (non-Javadoc) 86 * @see pw.lizi.base.BaseService#delete(T) 87 */ 88 @Override 89 public void delete(T entity){ 90 entityManager.remove(entity); 91 } 92 93 /* (non-Javadoc) 94 * @see pw.lizi.base.BaseService#delete(java.io.Serializable) 95 */ 96 @Override 97 public int delete(Serializable id){ 98 Query query = entityManager.createQuery("DELETE FROM " + entityClass.getName() + " WHERE " + getIdField() + "=?"); 99 query.setParameter(0, id); 100 return query.executeUpdate(); 101 } 102 103 104 /* (non-Javadoc) 105 * @see pw.lizi.base.BaseService#update(java.io.Serializable, java.util.LinkedHashMap) 106 */ 107 @Override 108 public int update(Serializable id, LinkedHashMap<String, Object> values){ 109 LinkedHashMap<String, Object> conditions = new LinkedHashMap<>(); 110 conditions.put(getIdField(), id); //where uid=? 111 return updates(conditions, values); 112 } 113 114 115 /* (non-Javadoc) 116 * @see pw.lizi.base.BaseService#updates(java.util.LinkedHashMap, java.util.LinkedHashMap) 117 */ 118 @Override 119 public int updates(LinkedHashMap<String, Object> conditions, LinkedHashMap<String, Object> values){ 120 AssertUtil.notEmpty(values, "要更新的值不能空"); 121 //update entityClass set field1=?,field2=?, where field1=? AND field2=? AND 122 StringBuilder jpql = new StringBuilder("UPDATE ").append(entityClass.getName()).append(" SET "); 123 for(Map.Entry<String, Object> v : values.entrySet()){ 124 jpql.append(v.getKey()).append("=?,"); 125 } 126 jpql.deleteCharAt(jpql.length() - 1); 127 128 Collection<Object> params = new ArrayList<Object>(); 129 params.addAll(values.values()); 130 131 if(conditions != null && conditions.size() > 0){ 132 jpql.append(" WHERE "); 133 for(Map.Entry<String, Object> condition : conditions.entrySet()){ 134 jpql.append(condition.getKey()).append("=? AND "); 135 } 136 jpql.delete(jpql.length() - 5, jpql.length()); 137 138 params.addAll(conditions.values()); 139 } 140 141 log.debug("更新语句:" + jpql.toString()); 142 143 Query query = entityManager.createQuery(jpql.toString()); 144 145 int i = 0; 146 for (Object value : params) { 147 query.setParameter(++i, value); 148 } 149 150 return query.executeUpdate(); 151 } 152 153 /* (non-Javadoc) 154 * @see pw.lizi.base.BaseService#findOne(java.io.Serializable) 155 */ 156 @Override 157 @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true) 158 public T findOne(Serializable id){ 159 return entityManager.find(entityClass, id); 160 } 161 162 163 /* (non-Javadoc) 164 * @see pw.lizi.base.BaseService#finds() 165 */ 166 @Override 167 @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true) 168 public List<T> finds(){ 169 return entityManager.createQuery("from " + entityClass.getName()).getResultList(); 170 } 171 172 /* (non-Javadoc) 173 * @see pw.lizi.base.BaseService#finds(java.util.LinkedHashMap) 174 */ 175 @Override 176 @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true) 177 public List<T> finds(Sort sort){ 178 return finds(null, null, null, sort); 179 } 180 181 /* (non-Javadoc) 182 * @see pw.lizi.base.BaseService#finds(pw.lizi.base.Page) 183 */ 184 @Override 185 @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true) 186 public List<T> finds(Page page){ 187 return finds(null, null, page, null); 188 } 189 190 /* (non-Javadoc) 191 * @see pw.lizi.base.BaseService#finds(pw.lizi.base.Page, java.util.LinkedHashMap) 192 */ 193 @Override 194 @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true) 195 public List<T> finds(Page page, Sort sort){ 196 return finds(null, null, page, sort); 197 } 198 199 /* (non-Javadoc) 200 * @see pw.lizi.base.BaseService#finds(java.util.LinkedHashMap, pw.lizi.base.Page, java.util.LinkedHashMap) 201 */ 202 @Override 203 @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true) 204 public List<T> finds(LinkedHashMap<String, Object> conditions, Page page, Sort sort){ 205 return finds(null, conditions, page, sort); 206 } 207 208 /* (non-Javadoc) 209 * @see pw.lizi.base.BaseService#finds(java.lang.String, java.util.LinkedHashMap, pw.lizi.base.Page, java.util.LinkedHashMap) 210 */ 211 @Override 212 @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true) 213 public List<T> finds(String fields, LinkedHashMap<String, Object> conditions, Page page, Sort sort){ 214 215 //准备返回字段,如果没自定义就返回* 216 fields = StringUtil.hasLength(fields) ? "new " + entityClass.getName() + "(" + fields + ") " : "o "; 217 218 //拼查询语句:select o.* from entityClass as o where f=v order by xxx 219 StringBuilder JPQL = new StringBuilder("SELECT ").append(fields).append(" FROM ").append(entityClass.getName()).append(" as o"); 220 221 //拼统计语句:select count(getIdField()) from entityClass where f=v 222 StringBuilder countJPQL = new StringBuilder("SELECT count(o.").append(getIdField()).append(')') 223 .append(" FROM ").append(entityClass.getName()).append(" as o"); 224 225 //拼条件 226 if(CollectionUtil.notEmpty(conditions)){ 227 JPQL.append(" WHERE "); 228 countJPQL.append(" WHERE "); 229 230 for(Map.Entry<String, Object> condition : conditions.entrySet()){ 231 JPQL.append("o.").append(condition.getKey()).append("=? AND "); 232 countJPQL.append("o.").append(condition.getKey()).append("=? AND "); 233 } 234 JPQL.delete(JPQL.length() - 5, JPQL.length()); 235 countJPQL.delete(JPQL.length() - 5, JPQL.length()); 236 } 237 238 /* 分页:只分第1页,后面的记录总页数就可以算出总记录数,从而不需要再统计 239 * (98条|100条)=总页面相等 240 * http://localhsot/news/list?pageIndex=2&pageCount=10 241 */ 242 if(page != null && page.getTotalCount() == 0){ 243 log.debug("统计语句:" + countJPQL.toString()); 244 Query query = entityManager.createQuery(countJPQL.toString()); 245 if(conditions != null){ 246 setParameter(query, conditions.values()); 247 } 248 long count = (Long) query.getSingleResult(); 249 page.setTotalCount((int)count); 250 } 251 252 //排序 253 if(CollectionUtil.notEmpty(sort)){ 254 JPQL.append(" ORDER BY "); 255 for(Map.Entry<String, Boolean> order : sort.entrySet()){ 256 JPQL.append("o.").append(order.getKey()).append(' ').append(order.getValue() ? "ASC" : "DESC").append(','); 257 } 258 JPQL.deleteCharAt(JPQL.length() - 1); 259 } 260 261 log.debug("查询语句:" + JPQL.toString()); 262 263 //生成查询对象,绑定参数 264 Query query = entityManager.createQuery(JPQL.toString()); 265 if(conditions != null){ 266 setParameter(query, conditions.values()); 267 } 268 269 //设置分页 limit 50,10 270 query.setFirstResult(page.getOffset()).setMaxResults(page.getPageSize()); 271 272 //返回查询结果 273 List<T> result = query.getResultList(); 274 275 return result; 276 } 277 278 //--------------------------------------------private----------------------------------------- 279 280 private void setParameter(Query query, Collection<Object> params){ 281 int i = 0; 282 for (Object object : params) { 283 query.setParameter(++i, object);//JPA是从1开始 284 } 285 } 286 287 private String getIdField(){ 288 289 /* 290 //第1个bug:拿不到父类的field,除非父类的属性设为public 291 //第2个bug:如果注解是放在get方法上的,那还得要遍历方法 292 //第3个问题:性能较关 293 Field[] fields = entityClass.getDeclaredFields(); 294 for (Field field : fields) { 295 Id id = field.getAnnotation(Id.class); 296 if(id != null){ 297 return field.getName(); 298 } 299 } 300 */ 301 302 String idField = entityManager.getMetamodel().entity(entityClass).getId(idClass).getName(); 303 304 return idField; 305 } 306 }
1 package pw.lizi.base; 2 3 import java.io.Serializable; 4 import java.util.LinkedHashMap; 5 import java.util.List; 6 7 8 /** 9 * 说明: 10 * 11 * 12 * 2018年9月30日 上午9:07:42 13 */ 14 public interface BaseService<T, ID> { 15 16 /** 17 * 功能说明:保存<br> 18 * @param entity 19 * void 20 */ 21 public abstract void save(T entity); 22 23 /** 24 * 功能说明:删除实体<br> 25 * @param entity 26 * void 27 */ 28 public abstract void delete(T entity); 29 30 /** 31 * 功能说明:根据ID删除<br> 32 * @param id 33 * void 34 */ 35 public abstract int delete(Serializable id); 36 37 /** 38 * 功能说明:根据ID更新单条记录<br> 39 * @param id 40 * @param values 41 * void 42 */ 43 public abstract int update(Serializable id, 44 LinkedHashMap<String, Object> values); 45 46 /** 47 * 功能说明:批量更新<br> 48 * @param conditions 49 * @param values 50 * @return 51 * int 52 */ 53 public abstract int updates(LinkedHashMap<String, Object> conditions, 54 LinkedHashMap<String, Object> values); 55 56 public abstract T findOne(Serializable id); 57 58 public abstract List<T> finds(); 59 60 /** 61 * 功能说明:排序查询<br> 62 * @param orders 63 * @return 64 * List<T> 65 */ 66 public abstract List<T> finds(Sort sort); 67 68 /** 69 * 功能说明:分页查询<br> 70 * @param page 71 * @return 72 * List<T> 73 */ 74 public abstract List<T> finds(Page page); 75 76 /** 77 * 功能说明:分页排序查询<br> 78 * @param page 79 * @param orders 80 * @return 81 * List<T> 82 */ 83 public abstract List<T> finds(Page page, Sort sort); 84 85 /** 86 * 功能说明:分页排序多条件查询<br> 87 * @param conditions 88 * @param page 89 * @param orders 90 * @return 91 * List<T> 92 */ 93 public abstract List<T> finds(LinkedHashMap<String, Object> conditions, Page page, Sort sort); 94 95 /** 96 * 功能说明:分页排序多条件,且可自定义字段查询<br> 97 * @param fields 98 * @param conditions 99 * @param page 100 * @param orders 101 * @return 102 * List<T> 103 */ 104 public abstract List<T> finds(String fields, LinkedHashMap<String, Object> conditions, Page page, Sort sort); 105 106 }
1 /** 2 * 3 */ 4 package pw.lizi.base; 5 6 import java.io.Serializable; 7 8 /** 9 * 说明: 10 * 11 * 12 * 2018年9月30日 上午8:15:31 13 */ 14 public class Page implements Serializable { 15 16 private static final long serialVersionUID = 1L; 17 18 private int pageIndex = 1; 19 20 private int pageSize; 21 22 private int totalCount; 23 24 25 public Page(int pageIndex, int pageSize) { 26 super(); 27 this.pageIndex = pageIndex; 28 this.pageSize = pageSize; 29 } 30 31 public int getOffset(){ 32 return (this.getPageIndex() - 1 ) * this.getPageSize(); 33 } 34 35 public int getPageIndex() { 36 return pageIndex; 37 } 38 39 public void setPageIndex(int pageIndex) { 40 this.pageIndex = pageIndex; 41 } 42 43 public int getPageSize() { 44 return pageSize; 45 } 46 47 public void setPageSize(int pageSize) { 48 this.pageSize = pageSize; 49 } 50 51 public int getTotalCount() { 52 return totalCount; 53 } 54 55 public void setTotalCount(int totalCount) { 56 this.totalCount = totalCount; 57 } 58 59 60 }

1 /** 2 * 3 */ 4 package pw.lizi.base; 5 6 import java.util.LinkedHashMap; 7 8 /** 9 * 说明: 10 * 11 * 12 * 2018年9月30日 上午9:38:02 13 */ 14 public class Sort extends LinkedHashMap<String, Boolean> { 15 16 private static final long serialVersionUID = 1L; 17 18 public Sort(String field, boolean asc){ 19 put(field, asc); 20 } 21 22 public Sort add(String field, boolean asc){ 23 put(field, asc); 24 return this; 25 } 26 public static Sort newInstance(String field, boolean asc){ 27 Sort sort = new Sort(field, asc); 28 return sort; 29 } 30 }