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. day5 io模型

    五种概览:http://www.cnblogs.com/xiehongfeng100/p/4763225.html http://sukai.me/linux-five-io-models/  内有多 ...

  2. Codeforces 1027E Inverse Coloring 【DP】

    Codeforces 1027E Inverse Coloring 题目链接 #include<bits/stdc++.h> using namespace std; #define N ...

  3. hive表数据导出到csv乱码原因及解决方案

    转载自http://blog.csdn.net/lgdlxc/article/details/42126225 Hive表中的数据使用hive - e"select * from table ...

  4. asp.net core microservices 架构之 分布式自动计算(一)

       一:简介   自动计算都是常驻内存的,没有人机交互.我们经常用到的就是console job和sql job了.sqljob有自己的宿主,与数据库产品有很关联,暂时不提.console job使 ...

  5. cannot find lstdc++

    centos下编译grpc-java时遇到的问题,google了一下 : sudo yum install libstdc++-static

  6. selenium数据驱动

    Selenium最后一个知识点——数据驱动.学会了这个Selenium就算学完啦~ 看代码: 这是修改的testSell.py文件. # coding: utf-8 import ddtimport ...

  7. 通过修改注册表建立Windows自定义协议

    引言 本文主要介绍注册表的概念与其相关根项的功能,以及浏览器如何通过连接调用自定义协议并与客户端进行数据通信.文中讲及如何通过C#程序.手动修改.安装项目等不同方式对注册表进行修改.其中通过安装项目对 ...

  8. ubuntu :安装好了搜狗输入法但是没法用

    用 im-config 命令打开一个配置器窗口 默认是ibus,需要修改为 fcitx 重启 ubuntu 系统就可以了.

  9. RTMP(实时信息传输协议)详解

    RTMP协议是Real Time Message Protocol(实时信息传输协议)的缩写,它是由Adobe公司提出的一种应用层的协议,用来解决多媒体数据传输流的多路复用(Multiplexing) ...

  10. js正则验证

    /判断输入内容是否为空    function IsNull(){        var str = document.getElementById('str').value.trim();      ...