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 }
sort