• Spring技术内幕之Spring Data JPA-自定义Repository实现


    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

  • 相关阅读:
    去中心化存储的QoS是什么?
    谈如何真正地做好去中心存储?
    Kowala协议:一组分布式,自我调节,资产跟踪特性的加密货币(二)
    MySQL主从备份
    Java面试总结-基础篇2
    Java面试总结-基础篇1
    锁定网络问题的方法
    我是如何在实际项目中解决MySQL性能问题
    serialVersionUID的作用
    Windows和Linux下如何自动备份MySQL
  • 原文地址:https://www.cnblogs.com/xiang--liu/p/9710244.html
Copyright © 2020-2023  润新知