1.自定义Repository方法接口,让接口的实现类来继承这个中间接口而不是Repository接口

  1. package com.data.jpa.dao;
  2. import java.io.Serializable;
  3. import java.util.List;
  4. import java.util.Map;
  5. import org.springframework.data.jpa.repository.JpaRepository;
  6. import org.springframework.data.repository.NoRepositoryBean;
  7. /**
  8. * 自定义Repository的方法接口
  9. * @author xiaowen
  10. * @param <T> 领域对象即实体类
  11. * @param <ID>领域对象的注解
  12. */
  13. @NoRepositoryBean
  14. public interface CustomRepository <T, ID extends Serializable> extends JpaRepository<T, ID> {
  15. /**
  16. * 保存对象<br/>
  17. * 注意:如果对象id是字符串,并且没有赋值,该方法将自动设置为uuid值
  18. * @param item
  19. * 持久对象,或者对象集合
  20. * @throws Exception
  21. */
  22. public void store(Object... item);
  23. /**
  24. * 更新对象数据
  25. *
  26. * @param item
  27. * 持久对象,或者对象集合
  28. * @throws Exception
  29. */
  30. public void update(Object... item);
  31. /**
  32. * 执行ql语句
  33. * @param qlString 基于jpa标准的ql语句
  34. * @param values ql中的?参数值,单个参数值或者多个参数值
  35. * @return 返回执行后受影响的数据个数
  36. */
  37. public int executeUpdate(String qlString, Object... values);
  38. /**
  39. * 执行ql语句
  40. * @param qlString 基于jpa标准的ql语句
  41. * @param params key表示ql中参数变量名,value表示该参数变量值
  42. * @return 返回执行后受影响的数据个数
  43. */
  44. public int executeUpdate(String qlString, Map<String, Object> params);
  45. /**
  46. * 执行ql语句,可以是更新或者删除操作
  47. * @param qlString 基于jpa标准的ql语句
  48. * @param values ql中的?参数值
  49. * @return 返回执行后受影响的数据个数
  50. * @throws Exception
  51. */
  52. public int executeUpdate(String qlString, List<Object> values);
  53. /***还可以定义分页相关方法,此处暂不支持**/
  54. }

2.自定义repository的方法接口实现类,作为Repository代理的自定义类来执行,该类主要提供自定义的公用方法

  1. package com.data.jpa.dao.impl;
  2. import java.io.Serializable;
  3. import java.lang.reflect.Field;
  4. import java.lang.reflect.Method;
  5. import java.util.List;
  6. import java.util.Map;
  7. import javax.persistence.EntityManager;
  8. import javax.persistence.Id;
  9. import javax.persistence.Query;
  10. import org.apache.log4j.Logger;
  11. import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
  12. import com.data.jpa.dao.CustomRepository;
  13. import com.data.jpa.util.ReflectHelper;
  14. import com.data.jpa.util.UUIDUtil;
  15. /**
  16. * 自定义repository的方法接口实现类,该类主要提供自定义的公用方法
  17. *
  18. * @author xiaowen
  19. * @date 2016年5月30日 @ version 1.0
  20. * @param <T>
  21. * @param <ID>
  22. */
  23. public class CustomRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, Serializable>
  24. implements CustomRepository<T, Serializable> {
  25. @SuppressWarnings("unused")
  26. private Logger logger = Logger.getLogger(CustomRepositoryImpl.class);
  27. /**
  28. * 持久化上下文
  29. */
  30. private final EntityManager entityManager;
  31. public CustomRepositoryImpl(Class<T> domainClass, EntityManager em) {
  32. super(domainClass, em);
  33. this.entityManager = em;
  34. }
  35. @Override
  36. public void store(Object... item) {
  37. if(null!=item){
  38. for(Object entity : item){
  39. innerSave(entity);
  40. }
  41. }
  42. }
  43. @Override
  44. public void update(Object... item) {
  45. if (null != item) {
  46. for (Object entity : item) {
  47. entityManager.merge(entity);
  48. }
  49. }
  50. }
  51. @Override
  52. public int executeUpdate(String qlString, Object... values) {
  53. Query query = entityManager.createQuery(qlString);
  54. if (values != null) {
  55. for (int i = 0; i < values.length; i++) {
  56. query.setParameter(i + 1, values[i]);
  57. }
  58. }
  59. return query.executeUpdate();
  60. }
  61. @Override
  62. public int executeUpdate(String qlString, Map<String, Object> params) {
  63. Query query = entityManager.createQuery(qlString);
  64. for (String name : params.keySet()) {
  65. query.setParameter(name, params.get(name));
  66. }
  67. return query.executeUpdate();
  68. }
  69. @Override
  70. public int executeUpdate(String qlString, List<Object> values) {
  71. Query query = entityManager.createQuery(qlString);
  72. for (int i = 0; i < values.size(); i++) {
  73. query.setParameter(i + 1, values.get(i));
  74. }
  75. return query.executeUpdate();
  76. }
  77. /**
  78. * 保存对象
  79. * @param item 保存对象
  80. * @return
  81. */
  82. private Serializable innerSave(Object item) {
  83. try {
  84. if(item==null)return null;
  85. Class<?> clazz = item.getClass();
  86. Field idField = ReflectHelper.getIdField(clazz);
  87. Method getMethod = null;
  88. if(idField!=null){
  89. Class<?> type = idField.getType();
  90. Object val = idField.get(item);
  91. if(type == String.class && (val==null || "".equals(val))){
  92. idField.set(item, UUIDUtil.uuid());
  93. }
  94. }else{
  95. Method[] methods = clazz.getDeclaredMethods();
  96. for (Method method : methods) {
  97. Id id = method.getAnnotation(Id.class);
  98. if (id != null) {
  99. Object val = method.invoke(item);
  100. if(val==null || "".equals(val)){
  101. String methodName = "s" + method.getName().substring(1);
  102. Method setMethod = clazz.getDeclaredMethod(methodName, method.getReturnType());
  103. if(setMethod!=null){
  104. setMethod.invoke(item, UUIDUtil.uuid());
  105. }
  106. }
  107. getMethod = method;
  108. break;
  109. }
  110. }
  111. }
  112. entityManager.persist(item);
  113. entityManager.flush();
  114. if(idField!=null){
  115. return (Serializable) idField.get(item);
  116. }
  117. if(getMethod!=null){
  118. return (Serializable)getMethod.invoke(item);
  119. }
  120. return null;
  121. } catch (Exception e) {
  122. e.printStackTrace();
  123. throw new RuntimeException(e);
  124. }
  125. }
  126. }

3. 扩展jpaRepository,让所有的repository共享起自定义的方法 

  1. package com.data.jpa.config;
  2. import java.io.Serializable;
  3. import javax.persistence.EntityManager;
  4. import org.springframework.data.jpa.repository.JpaRepository;
  5. import org.springframework.data.jpa.repository.support.JpaRepositoryFactory;
  6. import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean;
  7. import org.springframework.data.repository.core.RepositoryMetadata;
  8. import org.springframework.data.repository.core.support.RepositoryFactorySupport;
  9. import com.data.jpa.dao.impl.CustomRepositoryImpl;
  10. /**
  11. * 创建一个自定义的FactoryBean去替代默认的工厂类
  12. * @author xiaowen
  13. * @date 2016年5月30日
  14. * @ version 1.0
  15. * @param <R>
  16. * @param <T>
  17. * @param <I>
  18. */
  19. public class CustomRepositoryFactoryBean <R extends JpaRepository<T, I>, T, I extends Serializable>
  20. extends JpaRepositoryFactoryBean<R, T, I> {
  21. @SuppressWarnings("rawtypes")
  22. protected RepositoryFactorySupport createRepositoryFactory(EntityManager em) {
  23. return new CustomRepositoryFactory(em);
  24. }
  25. private static class CustomRepositoryFactory<T, I extends Serializable>
  26. extends JpaRepositoryFactory {
  27. private final EntityManager em;
  28. public CustomRepositoryFactory(EntityManager em) {
  29. super(em);
  30. this.em = em;
  31. }
  32. @SuppressWarnings("unchecked")
  33. protected Object getTargetRepository(RepositoryMetadata metadata) {
  34. return new CustomRepositoryImpl<T, I>(
  35. (Class<T>) metadata.getDomainType(), em);
  36. }
  37. protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
  38. return CustomRepositoryImpl.class;
  39. }
  40. }
  41. }

4.配置factory-class

  1. package com.data.jpa.config;
  2. import org.springframework.context.annotation.Configuration;
  3. import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
  4. import org.springframework.data.web.config.EnableSpringDataWebSupport;
  5. /**
  6. * 通过注解配置factory-class
  7. * @author xiaowen
  8. * @date 2016年5月30日
  9. * @ version 1.0
  10. */
  11. @Configuration
  12. @EnableJpaRepositories(basePackages = "com.data.jpa**.dao",
  13. repositoryFactoryBeanClass = CustomRepositoryFactoryBean.class)
  14. @EnableSpringDataWebSupport
  15. public class JpaDataConfig {
  16. }

当然也可以在xml文件中配置

  1. <repositories base-package="com.acme.repository"
  2. factory-class="com.acme.MyRepositoryFactoryBean" />

5.使用自定义的CustomRepository接口

  1. package com.data.jpa.dao;
  2. import com.data.jpa.dao.domain.Persion;
  3. /**
  4. * PersionRepository,通过继承自定义的CustomRepository获取提供自定义的公用方法,当然也可以自定义方法
  5. * @author xiaowen
  6. * @date 2016年5月30日
  7. * @ version 1.0
  8. */
  9. public interface PersionRepository extends CustomRepository<Persion, Integer> {
  10. /**
  11. * 通过用户名查询用户
  12. * @param userName
  13. * @return
  14. */
  15. public Persion findByuserName(String userName);
  16. }

6.使用PersionRepository,直接通过Spring的注解注入即可

  1. package com.data.jpa.controller;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.stereotype.Controller;
  4. import org.springframework.web.bind.annotation.RequestMapping;
  5. import org.springframework.web.bind.annotation.ResponseBody;
  6. import com.data.jpa.dao.PersionRepository;
  7. @Controller
  8. @RequestMapping("/perison")
  9. public class PersionController {
  10. @Autowired
  11. private PersionRepository persionRepository;
  12. @RequestMapping("/index")
  13. public String index(){
  14. return "index";
  15. }
  16. @RequestMapping("/search")
  17. public @ResponseBody String search(String userName){
  18. persionRepository.findByuserName(userName);
  19. return "success!";
  20. }
  21. }

相关实体类/工具类代码

1.Persion

  1. package com.data.jpa.dao.domain;
  2. import javax.persistence.Entity;
  3. import javax.persistence.Id;
  4. import javax.persistence.Table;
  5. /**
  6. * persion类
  7. * @author xiaowen
  8. * @date 2016年5月30日
  9. * @ version 1.0
  10. */
  11. @Entity
  12. @Table(name = "t_persion")
  13. public class Persion {
  14. @Id
  15. private String id;
  16. private String userName;
  17. private String userSex;
  18. /**
  19. * @return the id
  20. */
  21. public String getId() {
  22. return id;
  23. }
  24. /**
  25. * @param id the id to set
  26. */
  27. public void setId(String id) {
  28. this.id = id;
  29. }
  30. /**
  31. * @return the userName
  32. */
  33. public String getUserName() {
  34. return userName;
  35. }
  36. /**
  37. * @param userName the userName to set
  38. */
  39. public void setUserName(String userName) {
  40. this.userName = userName;
  41. }
  42. /**
  43. * @return the userSex
  44. */
  45. public String getUserSex() {
  46. return userSex;
  47. }
  48. /**
  49. * @param userSex the userSex to set
  50. */
  51. public void setUserSex(String userSex) {
  52. this.userSex = userSex;
  53. }
  54. }

2.UUID工具类

  1. package com.data.jpa.util;
  2. import java.util.UUID;
  3. /**
  4. * UUID工具类
  5. * @author xiaowen
  6. * @date 2016年5月30日
  7. * @ version 1.0
  8. */
  9. public class UUIDUtil {
  10. /**
  11. * 获取生成的uuid
  12. * @return
  13. */
  14. public static String uuid(){
  15. return UUID.randomUUID().toString().replaceAll("-", "");
  16. }
  17. }

3. 反射相关方法工具类

  1. package com.data.jpa.util;
  2. import java.lang.reflect.Field;
  3. import javax.persistence.Id;
  4. /**
  5. * 反射相关方法工具类
  6. * @author xiaowen
  7. * @date 2016年5月30日
  8. * @ version 1.0
  9. */
  10. public class ReflectHelper {
  11. /**
  12. * 获取实体类的字段信息
  13. * @param clazz 实体类
  14. * @return 字段集合
  15. */
  16. public static Field getIdField(Class<?> clazz){
  17. Field[] fields = clazz.getDeclaredFields();
  18. Field item = null;
  19. for (Field field : fields) {
  20. //获取实体类中标识@Id的字段
  21. Id id = field.getAnnotation(Id.class);
  22. if (id != null) {
  23. field.setAccessible(true);
  24. item = field;
  25. break;
  26. }
  27. }
  28. if(item==null){
  29. Class<?> superclass = clazz.getSuperclass();
  30. if(superclass!=null){
  31. item = getIdField(superclass);
  32. }
  33. }
  34. return item;
  35. }
  36. }

https://blog.csdn.net/u011659172/article/details/51537602

Spring技术内幕之Spring Data JPA-自定义Repository实现的更多相关文章

  1. Spring技术内幕:Spring AOP的实现原理(二)

    **二.AOP的设计与实现 1.JVM的动态代理特性** 在Spring AOP实现中, 使用的核心技术时动态代理.而这样的动态代理实际上是JDK的一个特性.通过JDK的动态代理特性,能够为随意Jav ...

  2. 深入探索spring技术内幕(一): spring概述

    一.Spring是什么? Spring是一个开源的控制反转 ( IoC ) 和面向切面 ( AOP ) 的容器框架, 它的主要目的是简化企业开发. 二.控制反转(IoC) 控制反转: 所谓的控制反转就 ...

  3. Spring技术内幕:Spring AOP的实现原理(一)

    一.SpringAOP的概述 1.AOP概念 AOP是Aspect-Oriented Programming(面向切面编程)的简称.维基百科的解释例如以下: Aspect是一种新的模块化机制,用来描写 ...

  4. Spring技术内幕:Spring AOP的实现原理(三)

    生成SingleTon代理对象在getSingleTonInstance方法中完毕,这种方法时ProxyFactoryBean生成AopProxy对象的入口.代理对象会封装对target目标对象的调用 ...

  5. Spring技术内幕:Spring AOP的实现原理(五)

    7.Advice通知的实现 AopProxy代理对象生成时,其拦截器也一并生成.以下我们来分析下Aop是怎样对目标对象进行增强的.在为AopProxy配置拦截器的实现中,有一个取得拦截器配置过程,这个 ...

  6. Spring技术内幕:设计理念和整体架构概述(转)

    程序员都很崇拜技术大神,很大一部分是因为他们发现和解决问题的能力,特别是线上出现紧急问题时,总是能够快速定位和解决. 一方面,他们有深厚的技术基础,对应用的技术知其所以然,另一方面,在采坑的过程中不断 ...

  7. 扩展spring data jpa的repository

    在我们编写代码的过程中,spring data jpa为我们的持久层提供的极大的方便,但有时spring data jpa提供的repository并不能完全满足我们开发的需求,因此就需要进行扩展.s ...

  8. 《spring技术内幕》读书笔记(1)——什么是POJO模式

    今天在看<spring技术内幕>,第一章中多次提到了使用POJO来完成开发,就百度了一下,在此保留 1.     什么是POJO POJO的名称有多种,pure old java obje ...

  9. Spring技术内幕:SpringIOC原理学习总结

    前一段时候我把Spring技术内幕的关于IOC原理一章看完,感觉代码太多,不好掌握,我特意又各方搜集了一些关于IOC原理的资料,特加深一下印象,以便真正掌握IOC的原理. IOC的思想是:Spring ...

随机推荐

  1. BZOJ5194: [Usaco2018 Feb]Snow Boots(排序&set)(可线段树优化)

    5194: [Usaco2018 Feb]Snow Boots Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 102  Solved: 79[Subm ...

  2. bzoj 4303 数列

    bzoj 4303 数列 二维 \(KD-Tree\) 模板题. \(KD-Tree\) 虽然在更新和查询的方式上类似于线段树,但其本身定义是类似于用 \(splay/fhq\ treap\) 维护区 ...

  3. CaptureMouse/CaptureStylus 可能会失败

    在 WPF 中,如果我们要做拖动效果,通常会调用一下 CaptureMouse/CaptureStylus 以便当鼠标或手指离开控件的时候依然能够响应 Move 和 Up 事件.不知有没有注意到这两个 ...

  4. C++ sort 函数用法

    MSDN中的定义: template<class RanIt>void sort(RanIt first, RanIt last); //--> 1)template<clas ...

  5. oracle数据库存储过程分页

    CREATE OR REPLACE PROCEDURE prc_query (p_tableName in varchar2, --表名 p_columnNames in varchar2, --字段 ...

  6. iOS7 自己定义动画跳转

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/Liar0606/article/details/26399125 简单介绍 在iOS7系统中,假设你 ...

  7. springboot使用hibernate validator校验方式

    一.参数校验 在开发中经常需要写一些字段校验的代码,比如字段非空,字段长度限制,邮箱格式验证等等,写这些与业务逻辑关系不大的代码个人感觉有两个麻烦: 验证代码繁琐,重复劳动 方法内代码显得冗长 每次要 ...

  8. 笔记:NPM 无限需要依赖问题解决

    笔记:NPM 无限需要依赖问题解决 起因 因为想学一下 VUE,开始跟着教程一步一步输出命令,开始也没有什么问题,一切都很顺利. 突然不知道是哪一步出了问题,一直让我安装依赖,没完没了,开始并不觉得有 ...

  9. volatile浅析

    volatile的意思是不稳定的.易变的,但在多线程中却跟字面意思一毛钱关系没有.作为一个变量修饰符,它主要有两个作用:一个是告诉大家,该变量是一个在多个线程之间均可见的变量:另一个是告诉java虚拟 ...

  10. ipvsadm的命令参考

    相信很多同学和我差不多,半桶水,貌似在配置lvs双机的时候,直接用的keepalived,ipvsadm就用来看看,感觉没啥用,今天无聊到处逛发现,某大神说,keepalived只是ipvsadm的一 ...