ProjectSimpleJpaRepository.java 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575
  1. /**
  2. * 文件名:@AfwSimpleJpaRepository.java <br/>
  3. * 包名:cn.efunbox.afw.data.jpa.spring.support <br/>
  4. * 项目名:afw-data <br/>
  5. * @author xtwin <br/>
  6. */
  7. package cn.efunbox.audio.repository.base;
  8. import cn.efunbox.audio.utils.SnowflakeIdUtil;
  9. import org.slf4j.Logger;
  10. import org.slf4j.LoggerFactory;
  11. import org.springframework.data.domain.Sort;
  12. import org.springframework.data.domain.Sort.Direction;
  13. import org.springframework.data.domain.Sort.Order;
  14. import org.springframework.data.jpa.domain.Specification;
  15. import org.springframework.data.jpa.repository.support.JpaEntityInformation;
  16. import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
  17. import org.springframework.transaction.annotation.Transactional;
  18. import org.springframework.util.ReflectionUtils;
  19. import org.springframework.util.StringUtils;
  20. import javax.persistence.EntityManager;
  21. import javax.persistence.TypedQuery;
  22. import javax.persistence.criteria.CriteriaBuilder;
  23. import javax.persistence.criteria.CriteriaQuery;
  24. import javax.persistence.criteria.Predicate;
  25. import javax.persistence.criteria.Root;
  26. import javax.persistence.metamodel.Attribute;
  27. import javax.persistence.metamodel.Attribute.PersistentAttributeType;
  28. import java.io.Serializable;
  29. import java.lang.reflect.Field;
  30. import java.lang.reflect.Member;
  31. import java.lang.reflect.Method;
  32. import java.util.ArrayList;
  33. import java.util.Iterator;
  34. import java.util.List;
  35. /**
  36. * 类名:AfwSimpleJpaRepository <br />
  37. *
  38. * 功能:Jpa仓库基础实现
  39. *
  40. * @author xtwin <br />
  41. * 创建时间:2016年7月26日 下午3:19:42 <br />
  42. * @version 2016年7月26日
  43. */
  44. public class ProjectSimpleJpaRepository<E, ID extends Serializable> extends SimpleJpaRepository<E, ID> implements ProjectJpaRepository<E, ID> {
  45. // 日志记录器
  46. private static final Logger logger = LoggerFactory.getLogger(ProjectSimpleJpaRepository.class);
  47. // jpa管理器对象
  48. private EntityManager entityManager;
  49. // 实体信息
  50. private JpaEntityInformation<E, ID> entityInformation;
  51. /**
  52. * 构造方法
  53. */
  54. public ProjectSimpleJpaRepository(JpaEntityInformation<E, ID> entityInformation, EntityManager entityManager) {
  55. super(entityInformation, entityManager);
  56. // 保留该对象,方便后续使用
  57. this.entityInformation = entityInformation;
  58. this.entityManager = entityManager;
  59. }
  60. /**
  61. * 功能: <br/>
  62. *
  63. * 重写:xtwin <br/>
  64. *
  65. * @version :2016年7月26日 下午3:23:06<br/>
  66. *
  67. * @param sample
  68. * @return <br/>
  69. * @see ProjectJpaRepository#count(Object)
  70. */
  71. @Override
  72. public long count(E sample) {
  73. return count(getSpecification(sample));
  74. }
  75. /**
  76. * 功能: <br/>
  77. *
  78. * 重写:xtwin <br/>
  79. *
  80. * @version :2016年8月17日 下午12:05:21<br/>
  81. *
  82. * @param sample
  83. * @return <br/>
  84. * @see ProjectJpaRepository#exists(Object)
  85. */
  86. @Override
  87. public boolean exists(E sample) {
  88. return count(sample) > 0L;
  89. }
  90. /**
  91. * 功能: <br/>
  92. *
  93. * 重写:xtwin <br/>
  94. *
  95. * @version :2016年7月26日 下午3:23:06<br/>
  96. *
  97. * @param id
  98. * @return <br/>
  99. * @see ProjectJpaRepository#find(Serializable)
  100. */
  101. @Override
  102. public E find(ID id) {
  103. return findOne(id);
  104. }
  105. /**
  106. * 功能:根据ids查询 <br/>
  107. *
  108. * @author xtwin <br/>
  109. * @version 2016年3月30日 下午6:28:23 <br/>
  110. */
  111. public List<E> findByIds(List<ID> ids){
  112. return findAll(ids);
  113. }
  114. /**
  115. * 功能: <br/>
  116. *
  117. * 重写:xtwin <br/>
  118. *
  119. * @version :2016年7月26日 下午3:23:06<br/>
  120. *
  121. * @param start
  122. * @param offset
  123. * @return <br/>
  124. * @see ProjectJpaRepository#find(Integer, Integer)
  125. */
  126. @Override
  127. public List<E> find(Integer start, Integer offset) {
  128. return find(start, offset, null);
  129. }
  130. /**
  131. * 功能: <br/>
  132. *
  133. * 重写:xtwin <br/>
  134. *
  135. * @version :2016年7月29日 上午10:20:21<br/>
  136. *
  137. * @param start
  138. * @param offset
  139. * @param sort
  140. * @return <br/>
  141. * @see ProjectJpaRepository#find(Integer, Integer, Sort)
  142. */
  143. @Override
  144. public List<E> find(Integer start, Integer offset, Sort sort) {
  145. return find(null, start, offset, sort);
  146. }
  147. /**
  148. * 功能: <br/>
  149. *
  150. * 重写:xtwin <br/>
  151. *
  152. * @version :2016年8月2日 上午11:58:30<br/>
  153. *
  154. * @param sample
  155. * @return <br/>
  156. * @see ProjectJpaRepository#findFirst(Object)
  157. */
  158. @Override
  159. public E findFirst(E sample) {
  160. return findFirst(sample, null);
  161. }
  162. /**
  163. * 功能: <br/>
  164. *
  165. * 重写:xtwin <br/>
  166. *
  167. * @version :2016年8月2日 上午11:58:30<br/>
  168. *
  169. * @param sample
  170. * @param sort
  171. * @return <br/>
  172. * @see ProjectJpaRepository#findFirst(Object, Sort)
  173. */
  174. @Override
  175. public E findFirst(E sample, Sort sort) {
  176. List<E> list = find(sample, 0, 1, sort);
  177. return null == list || list.isEmpty() ? null : list.get(0);
  178. }
  179. /**
  180. * 功能: <br/>
  181. *
  182. * 重写:xtwin <br/>
  183. *
  184. * @version :2016年7月26日 下午3:23:06<br/>
  185. *
  186. * @param sample
  187. * @return <br/>
  188. * @see ProjectJpaRepository#find(Object)
  189. */
  190. @Override
  191. public List<E> find(E sample) {
  192. return find(sample, null);
  193. }
  194. /**
  195. * 功能: <br/>
  196. *
  197. * 重写:xtwin <br/>
  198. *
  199. * @version :2016年7月29日 上午10:20:21<br/>
  200. *
  201. * @param sample
  202. * @param sort
  203. * @return <br/>
  204. * @see ProjectJpaRepository#find(Object, Sort)
  205. */
  206. @Override
  207. public List<E> find(E sample, Sort sort) {
  208. return find(sample, null, null,sort);
  209. }
  210. /**
  211. * 功能: <br/>
  212. *
  213. * 重写:xtwin <br/>
  214. *
  215. * @version :2016年7月26日 下午3:23:06<br/>
  216. *
  217. * @param sample
  218. * @param start
  219. * @param offset
  220. * @return <br/>
  221. * @see ProjectJpaRepository#find(Object, Integer, Integer)
  222. */
  223. @Override
  224. public List<E> find(E sample, Integer start, Integer offset) {
  225. return find(sample, start, offset, null);
  226. }
  227. /**
  228. * 功能: <br/>
  229. *
  230. * 重写:xtwin <br/>
  231. *
  232. * @version :2016年7月29日 上午9:44:56<br/>
  233. *
  234. * @param sample
  235. * @param start
  236. * @param offset
  237. * @param sort
  238. * @return <br/>
  239. * @see ProjectJpaRepository#find(Object, Integer, Integer, Sort)
  240. */
  241. @Override
  242. public List<E> find(E sample, Integer start, Integer offset, Sort sort) {
  243. // 创建qbe
  244. Specification<E> spec = getSpecification(sample);
  245. if (null == sort) {
  246. // 默认按id降序排序
  247. sort = new Sort(new Order(Direction.DESC, entityInformation.getIdAttribute().getName()));
  248. }
  249. // 取得查询对象
  250. TypedQuery<E> query = getQuery(spec, sort);
  251. // 起始条数,从零开始
  252. if (null != start) {
  253. // TODO 此处只接受整形值
  254. query.setFirstResult(start.intValue());
  255. }
  256. // 查询条数
  257. if (null != offset) {
  258. query.setMaxResults(offset);
  259. }
  260. // 执行查询
  261. return query.getResultList();
  262. }
  263. /**
  264. * 功能: 更新操作,不更新为null的字段 <br/>
  265. *
  266. * 重写:xtwin <br/>
  267. *
  268. * @version :2016年8月1日 上午9:37:15<br/>
  269. *
  270. * @param entity
  271. * @return <br/>
  272. * @see ProjectJpaRepository#update(Object)
  273. */
  274. @Transactional
  275. public E update(E entity) {
  276. return update(entity, true);
  277. }
  278. /**
  279. * Saves all given entities.
  280. *
  281. * @param entities
  282. * @return the saved entities
  283. * @throws IllegalArgumentException in case the given domain is {@literal null}.
  284. */
  285. @Override
  286. @Transactional
  287. public <S extends E> List<S> save(Iterable<S> entities) {
  288. return insertOrUpdateBatch(entities);
  289. }
  290. /**
  291. * Saves a given domain. Use the returned instance for further operations as the save operation might have changed the
  292. * domain instance completely.
  293. *
  294. * @param entity
  295. * @return the saved domain
  296. */
  297. @Transactional
  298. public <S extends E> S save(S entity) {
  299. if (entityInformation.isNew(entity)) {
  300. setSnowflakeIdId(entity);
  301. entityManager.persist(entity);
  302. return entity;
  303. } else {
  304. return entityManager.merge(entity);
  305. }
  306. }
  307. /**
  308. * 功能: 动态数据更新,可以选择是否需要更新null字段 <br/>
  309. *
  310. * 重写:xtwin <br/>
  311. *
  312. * @version :2016年8月1日 上午9:37:05<br/>
  313. *
  314. * @param entity
  315. * @param ignoreNull
  316. * @return <br/>
  317. * @see ProjectJpaRepository#update(Object, boolean)
  318. */
  319. @Transactional
  320. public E update(E entity, boolean ignoreNull) {
  321. // 取得当前实体的id
  322. ID id = entityInformation.getId(entity);
  323. // 检查id是否为空Ø
  324. if (null == id) {
  325. throw new RuntimeException("The update domain id must be not empty !");
  326. }
  327. // 查询库中当前对象的信息
  328. E persist = find(id);
  329. // 检查该id对应的数据是否存在
  330. if (null == persist) {
  331. throw new RuntimeException("The update domain id is not exist : " + id);
  332. }
  333. // 标识是否发生了变化
  334. boolean isChanged = false;
  335. // 取得所有属性
  336. for (Attribute<? super E, ?> attr : entityManager.getMetamodel().entity(getDomainClass()).getAttributes()) {
  337. // 依次处理每个字段
  338. /*PersistentAttributeType patype = attr.getPersistentAttributeType();
  339. if (PersistentAttributeType.MANY_TO_ONE.equals(patype)
  340. || PersistentAttributeType.ONE_TO_MANY.equals(patype)) {
  341. // 忽略
  342. continue;
  343. }*/
  344. Member member = attr.getJavaMember();
  345. Field field = null;
  346. if (member instanceof Field) {
  347. field = (Field) member;
  348. } else {
  349. field = ReflectionUtils.findField(getDomainClass(), attr.getName());
  350. }
  351. // 取得字段值
  352. Object value = ReflectionUtils.getField(field, entity);
  353. if (null != value || ! ignoreNull) {
  354. // 旧值
  355. Object oldValue = ReflectionUtils.getField(field, persist);
  356. if ((null == value && null != oldValue)
  357. || (null != value && ! value.equals(oldValue))) {
  358. // 将新值更新到持久化对象中
  359. ReflectionUtils.setField(field, persist, value);
  360. // 标记为发生了更新
  361. isChanged = true;
  362. }
  363. }
  364. }
  365. if (isChanged) {
  366. persist = save(persist);
  367. } else {
  368. // 没有发生变更,忽略更新
  369. logger.debug("has no changed : {}", id);
  370. }
  371. // 执行保存并返回
  372. return persist;
  373. }
  374. /**
  375. * update all given entities.
  376. *
  377. * @param entities
  378. * @return the saved entities
  379. * @throws IllegalArgumentException in case the given domain is {@literal null}.
  380. */
  381. @Transactional
  382. public <S extends E> List<S> update(Iterable<S> entities) {
  383. return insertOrUpdateBatch(entities);
  384. }
  385. private <S extends E> List<S> insertOrUpdateBatch(Iterable<S> entities) {
  386. List<S> result = new ArrayList<>();
  387. if (entities == null) {
  388. return result;
  389. }
  390. Iterator<S> iterator = entities.iterator();
  391. int i = 0;
  392. int count = 0;
  393. //遍历循环 每20个 insert 批量插入/更新 一次库
  394. while (iterator.hasNext()) {
  395. S entity = iterator.next();
  396. if (entityInformation.isNew(entity)) {
  397. // setSnowflakeIdId(entity);
  398. entityManager.persist(entity);
  399. } else {
  400. update(entity);
  401. }
  402. result.add(entity);
  403. i++;
  404. if (i % 20 == 0) {
  405. entityManager.flush();
  406. entityManager.clear();
  407. count=0;
  408. }else {
  409. count++;
  410. }
  411. }
  412. //判断 是否有剩余未flush的 最后flush
  413. if (count>0){
  414. entityManager.flush();
  415. entityManager.clear();
  416. }
  417. return result;
  418. }
  419. /**
  420. * 功能:获取qbe <br/>
  421. *
  422. * @author xtwin <br/>
  423. * @version 2016年7月29日 上午9:43:25 <br/>
  424. */
  425. protected Specification<E> getSpecification(E sample) {
  426. return null == sample ? null : new Specification<E>() {
  427. @Override
  428. public Predicate toPredicate(Root<E> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
  429. try {
  430. // 获取qbe
  431. return ProjectSimpleJpaRepository.this.toPredicate(sample, root, query, cb);
  432. } catch (Exception e) {
  433. throw new RuntimeException("toPredicate fail with error : " + String.valueOf(e), e);
  434. }
  435. }
  436. };
  437. }
  438. /**
  439. * 功能:转为查询样板,可以由子类重写 <br/>
  440. *
  441. * @author xtwin <br/>
  442. * @version 2016年7月29日 上午10:15:27 <br/>
  443. * @throws IllegalAccessException
  444. * @throws IllegalArgumentException
  445. */
  446. protected Predicate toPredicate(E sample, Root<E> root, CriteriaQuery<?> query, CriteriaBuilder cb) throws Exception {
  447. // 存放查询条件
  448. List<Predicate> list = new ArrayList<Predicate>();
  449. // 处理实体中的所有字段
  450. for (Attribute<? super E, ?> attr : entityManager.getMetamodel().entity(getDomainClass()).getAttributes()) {
  451. // 依次处理每个字段
  452. PersistentAttributeType patype = attr.getPersistentAttributeType();
  453. // 打印日志
  454. logger.debug("the attr type is : {}", patype);
  455. if (PersistentAttributeType.MANY_TO_ONE.equals(patype)
  456. || PersistentAttributeType.ONE_TO_MANY.equals(patype)) {
  457. // 忽略
  458. continue;
  459. }
  460. Object value = null;
  461. Member member = attr.getJavaMember();
  462. if (member instanceof Method) {
  463. value = ReflectionUtils.invokeMethod((Method) member, sample);
  464. } else if (member instanceof Field) {
  465. //((Field) member).setAccessible(true);
  466. // 确保可以访问
  467. ReflectionUtils.makeAccessible((Field) member);
  468. // 取得字段的值
  469. value = ((Field) member).get(sample);
  470. }
  471. if (null != value) {
  472. Predicate tmp = null;
  473. //like 查询放在最前面
  474. List<Predicate> likePredicate = new ArrayList<Predicate>();
  475. if (String.class.isAssignableFrom(attr.getJavaType()) ) {
  476. if(!StringUtils.isEmpty(value)){
  477. StringBuilder stringBuilder=new StringBuilder(((String) value).trim());
  478. //如果以 % 开头和结尾 表示 like 查询
  479. if("%".equals(stringBuilder.substring(0,1)) || stringBuilder.toString().endsWith("%")){
  480. tmp = cb.like(root.get(attr.getName()), (String) value);
  481. likePredicate.add(tmp);
  482. }else{
  483. tmp = cb.equal(root.get(attr.getName()), value);
  484. list.add(tmp);
  485. }
  486. }
  487. } else {
  488. tmp = cb.equal(root.get(attr.getName()), value);
  489. list.add(tmp);
  490. }
  491. if(likePredicate.size()>0){
  492. list.addAll(0,likePredicate);
  493. }
  494. }
  495. }
  496. // where条件
  497. return list.isEmpty() ? null : cb.and(list.toArray(new Predicate[list.size()]));
  498. }
  499. protected void setSnowflakeIdId(E entity){
  500. try {
  501. Field field = ReflectionUtils.findField(entity.getClass(),entityInformation.getIdAttribute().getName());
  502. if(entityInformation.getIdAttribute().getType().getJavaType().getName().equals("java.lang.Long")){
  503. ReflectionUtils.makeAccessible(field);
  504. ReflectionUtils.setField(field, entity, SnowflakeIdUtil.getSnowflakeIdUtil().nextId());
  505. }else if(entityInformation.getIdAttribute().getType().getJavaType().getName().equals("java.lang.String")) {
  506. logger.debug(" uuid entityInformation.getIdAttribute().getName() ={}",entityInformation.getIdAttribute().getName());
  507. ReflectionUtils.makeAccessible(field);
  508. ReflectionUtils.setField(field, entity, SnowflakeIdUtil.getSnowflakeIdUtil().nextCode());
  509. }
  510. }catch (Exception e){
  511. logger.error("Reflect set id 出错 mag ={}",e.getMessage(),e);
  512. }
  513. }
  514. }