Spring技术内幕之Spring Data JPA-自定义Repository实现
1.自定义Repository方法接口,让接口的实现类来继承这个中间接口而不是Repository接口
- package com.data.jpa.dao;
- import java.io.Serializable;
- import java.util.List;
- import java.util.Map;
- import org.springframework.data.jpa.repository.JpaRepository;
- import org.springframework.data.repository.NoRepositoryBean;
- /**
- * 自定义Repository的方法接口
- * @author xiaowen
- * @param <T> 领域对象即实体类
- * @param <ID>领域对象的注解
- */
- @NoRepositoryBean
- public interface CustomRepository <T, ID extends Serializable> extends JpaRepository<T, ID> {
- /**
- * 保存对象<br/>
- * 注意:如果对象id是字符串,并且没有赋值,该方法将自动设置为uuid值
- * @param item
- * 持久对象,或者对象集合
- * @throws Exception
- */
- public void store(Object... item);
- /**
- * 更新对象数据
- *
- * @param item
- * 持久对象,或者对象集合
- * @throws Exception
- */
- public void update(Object... item);
- /**
- * 执行ql语句
- * @param qlString 基于jpa标准的ql语句
- * @param values ql中的?参数值,单个参数值或者多个参数值
- * @return 返回执行后受影响的数据个数
- */
- public int executeUpdate(String qlString, Object... values);
- /**
- * 执行ql语句
- * @param qlString 基于jpa标准的ql语句
- * @param params key表示ql中参数变量名,value表示该参数变量值
- * @return 返回执行后受影响的数据个数
- */
- public int executeUpdate(String qlString, Map<String, Object> params);
- /**
- * 执行ql语句,可以是更新或者删除操作
- * @param qlString 基于jpa标准的ql语句
- * @param values ql中的?参数值
- * @return 返回执行后受影响的数据个数
- * @throws Exception
- */
- public int executeUpdate(String qlString, List<Object> values);
- /***还可以定义分页相关方法,此处暂不支持**/
- }
2.自定义repository的方法接口实现类,作为Repository代理的自定义类来执行,该类主要提供自定义的公用方法
- package com.data.jpa.dao.impl;
- import java.io.Serializable;
- import java.lang.reflect.Field;
- import java.lang.reflect.Method;
- import java.util.List;
- import java.util.Map;
- import javax.persistence.EntityManager;
- import javax.persistence.Id;
- import javax.persistence.Query;
- import org.apache.log4j.Logger;
- import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
- import com.data.jpa.dao.CustomRepository;
- import com.data.jpa.util.ReflectHelper;
- import com.data.jpa.util.UUIDUtil;
- /**
- * 自定义repository的方法接口实现类,该类主要提供自定义的公用方法
- *
- * @author xiaowen
- * @date 2016年5月30日 @ version 1.0
- * @param <T>
- * @param <ID>
- */
- public class CustomRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, Serializable>
- implements CustomRepository<T, Serializable> {
- @SuppressWarnings("unused")
- private Logger logger = Logger.getLogger(CustomRepositoryImpl.class);
- /**
- * 持久化上下文
- */
- private final EntityManager entityManager;
- public CustomRepositoryImpl(Class<T> domainClass, EntityManager em) {
- super(domainClass, em);
- this.entityManager = em;
- }
- @Override
- public void store(Object... item) {
- if(null!=item){
- for(Object entity : item){
- innerSave(entity);
- }
- }
- }
- @Override
- public void update(Object... item) {
- if (null != item) {
- for (Object entity : item) {
- entityManager.merge(entity);
- }
- }
- }
- @Override
- public int executeUpdate(String qlString, Object... values) {
- Query query = entityManager.createQuery(qlString);
- if (values != null) {
- for (int i = 0; i < values.length; i++) {
- query.setParameter(i + 1, values[i]);
- }
- }
- return query.executeUpdate();
- }
- @Override
- public int executeUpdate(String qlString, Map<String, Object> params) {
- Query query = entityManager.createQuery(qlString);
- for (String name : params.keySet()) {
- query.setParameter(name, params.get(name));
- }
- return query.executeUpdate();
- }
- @Override
- public int executeUpdate(String qlString, List<Object> values) {
- Query query = entityManager.createQuery(qlString);
- for (int i = 0; i < values.size(); i++) {
- query.setParameter(i + 1, values.get(i));
- }
- return query.executeUpdate();
- }
- /**
- * 保存对象
- * @param item 保存对象
- * @return
- */
- private Serializable innerSave(Object item) {
- try {
- if(item==null)return null;
- Class<?> clazz = item.getClass();
- Field idField = ReflectHelper.getIdField(clazz);
- Method getMethod = null;
- if(idField!=null){
- Class<?> type = idField.getType();
- Object val = idField.get(item);
- if(type == String.class && (val==null || "".equals(val))){
- idField.set(item, UUIDUtil.uuid());
- }
- }else{
- Method[] methods = clazz.getDeclaredMethods();
- for (Method method : methods) {
- Id id = method.getAnnotation(Id.class);
- if (id != null) {
- Object val = method.invoke(item);
- if(val==null || "".equals(val)){
- String methodName = "s" + method.getName().substring(1);
- Method setMethod = clazz.getDeclaredMethod(methodName, method.getReturnType());
- if(setMethod!=null){
- setMethod.invoke(item, UUIDUtil.uuid());
- }
- }
- getMethod = method;
- break;
- }
- }
- }
- entityManager.persist(item);
- entityManager.flush();
- if(idField!=null){
- return (Serializable) idField.get(item);
- }
- if(getMethod!=null){
- return (Serializable)getMethod.invoke(item);
- }
- return null;
- } catch (Exception e) {
- e.printStackTrace();
- throw new RuntimeException(e);
- }
- }
- }
3. 扩展jpaRepository,让所有的repository共享起自定义的方法
- package com.data.jpa.config;
- import java.io.Serializable;
- import javax.persistence.EntityManager;
- import org.springframework.data.jpa.repository.JpaRepository;
- import org.springframework.data.jpa.repository.support.JpaRepositoryFactory;
- import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean;
- import org.springframework.data.repository.core.RepositoryMetadata;
- import org.springframework.data.repository.core.support.RepositoryFactorySupport;
- import com.data.jpa.dao.impl.CustomRepositoryImpl;
- /**
- * 创建一个自定义的FactoryBean去替代默认的工厂类
- * @author xiaowen
- * @date 2016年5月30日
- * @ version 1.0
- * @param <R>
- * @param <T>
- * @param <I>
- */
- public class CustomRepositoryFactoryBean <R extends JpaRepository<T, I>, T, I extends Serializable>
- extends JpaRepositoryFactoryBean<R, T, I> {
- @SuppressWarnings("rawtypes")
- protected RepositoryFactorySupport createRepositoryFactory(EntityManager em) {
- return new CustomRepositoryFactory(em);
- }
- private static class CustomRepositoryFactory<T, I extends Serializable>
- extends JpaRepositoryFactory {
- private final EntityManager em;
- public CustomRepositoryFactory(EntityManager em) {
- super(em);
- this.em = em;
- }
- @SuppressWarnings("unchecked")
- protected Object getTargetRepository(RepositoryMetadata metadata) {
- return new CustomRepositoryImpl<T, I>(
- (Class<T>) metadata.getDomainType(), em);
- }
- protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
- return CustomRepositoryImpl.class;
- }
- }
- }
4.配置factory-class
- package com.data.jpa.config;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
- import org.springframework.data.web.config.EnableSpringDataWebSupport;
- /**
- * 通过注解配置factory-class
- * @author xiaowen
- * @date 2016年5月30日
- * @ version 1.0
- */
- @Configuration
- @EnableJpaRepositories(basePackages = "com.data.jpa**.dao",
- repositoryFactoryBeanClass = CustomRepositoryFactoryBean.class)
- @EnableSpringDataWebSupport
- public class JpaDataConfig {
- }
当然也可以在xml文件中配置
- <repositories base-package="com.acme.repository"
- factory-class="com.acme.MyRepositoryFactoryBean" />
5.使用自定义的CustomRepository接口
- package com.data.jpa.dao;
- import com.data.jpa.dao.domain.Persion;
- /**
- * PersionRepository,通过继承自定义的CustomRepository获取提供自定义的公用方法,当然也可以自定义方法
- * @author xiaowen
- * @date 2016年5月30日
- * @ version 1.0
- */
- public interface PersionRepository extends CustomRepository<Persion, Integer> {
- /**
- * 通过用户名查询用户
- * @param userName
- * @return
- */
- public Persion findByuserName(String userName);
- }
6.使用PersionRepository,直接通过Spring的注解注入即可
- package com.data.jpa.controller;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.ResponseBody;
- import com.data.jpa.dao.PersionRepository;
- @Controller
- @RequestMapping("/perison")
- public class PersionController {
- @Autowired
- private PersionRepository persionRepository;
- @RequestMapping("/index")
- public String index(){
- return "index";
- }
- @RequestMapping("/search")
- public @ResponseBody String search(String userName){
- persionRepository.findByuserName(userName);
- return "success!";
- }
- }
相关实体类/工具类代码
1.Persion
- package com.data.jpa.dao.domain;
- import javax.persistence.Entity;
- import javax.persistence.Id;
- import javax.persistence.Table;
- /**
- * persion类
- * @author xiaowen
- * @date 2016年5月30日
- * @ version 1.0
- */
- @Entity
- @Table(name = "t_persion")
- public class Persion {
- @Id
- private String id;
- private String userName;
- private String userSex;
- /**
- * @return the id
- */
- public String getId() {
- return id;
- }
- /**
- * @param id the id to set
- */
- public void setId(String id) {
- this.id = id;
- }
- /**
- * @return the userName
- */
- public String getUserName() {
- return userName;
- }
- /**
- * @param userName the userName to set
- */
- public void setUserName(String userName) {
- this.userName = userName;
- }
- /**
- * @return the userSex
- */
- public String getUserSex() {
- return userSex;
- }
- /**
- * @param userSex the userSex to set
- */
- public void setUserSex(String userSex) {
- this.userSex = userSex;
- }
- }
2.UUID工具类
- package com.data.jpa.util;
- import java.util.UUID;
- /**
- * UUID工具类
- * @author xiaowen
- * @date 2016年5月30日
- * @ version 1.0
- */
- public class UUIDUtil {
- /**
- * 获取生成的uuid
- * @return
- */
- public static String uuid(){
- return UUID.randomUUID().toString().replaceAll("-", "");
- }
- }
3. 反射相关方法工具类
- package com.data.jpa.util;
- import java.lang.reflect.Field;
- import javax.persistence.Id;
- /**
- * 反射相关方法工具类
- * @author xiaowen
- * @date 2016年5月30日
- * @ version 1.0
- */
- public class ReflectHelper {
- /**
- * 获取实体类的字段信息
- * @param clazz 实体类
- * @return 字段集合
- */
- public static Field getIdField(Class<?> clazz){
- Field[] fields = clazz.getDeclaredFields();
- Field item = null;
- for (Field field : fields) {
- //获取实体类中标识@Id的字段
- Id id = field.getAnnotation(Id.class);
- if (id != null) {
- field.setAccessible(true);
- item = field;
- break;
- }
- }
- if(item==null){
- Class<?> superclass = clazz.getSuperclass();
- if(superclass!=null){
- item = getIdField(superclass);
- }
- }
- return item;
- }
- }
https://blog.csdn.net/u011659172/article/details/51537602
Spring技术内幕之Spring Data JPA-自定义Repository实现的更多相关文章
- Spring技术内幕:Spring AOP的实现原理(二)
**二.AOP的设计与实现 1.JVM的动态代理特性** 在Spring AOP实现中, 使用的核心技术时动态代理.而这样的动态代理实际上是JDK的一个特性.通过JDK的动态代理特性,能够为随意Jav ...
- 深入探索spring技术内幕(一): spring概述
一.Spring是什么? Spring是一个开源的控制反转 ( IoC ) 和面向切面 ( AOP ) 的容器框架, 它的主要目的是简化企业开发. 二.控制反转(IoC) 控制反转: 所谓的控制反转就 ...
- Spring技术内幕:Spring AOP的实现原理(一)
一.SpringAOP的概述 1.AOP概念 AOP是Aspect-Oriented Programming(面向切面编程)的简称.维基百科的解释例如以下: Aspect是一种新的模块化机制,用来描写 ...
- Spring技术内幕:Spring AOP的实现原理(三)
生成SingleTon代理对象在getSingleTonInstance方法中完毕,这种方法时ProxyFactoryBean生成AopProxy对象的入口.代理对象会封装对target目标对象的调用 ...
- Spring技术内幕:Spring AOP的实现原理(五)
7.Advice通知的实现 AopProxy代理对象生成时,其拦截器也一并生成.以下我们来分析下Aop是怎样对目标对象进行增强的.在为AopProxy配置拦截器的实现中,有一个取得拦截器配置过程,这个 ...
- Spring技术内幕:设计理念和整体架构概述(转)
程序员都很崇拜技术大神,很大一部分是因为他们发现和解决问题的能力,特别是线上出现紧急问题时,总是能够快速定位和解决. 一方面,他们有深厚的技术基础,对应用的技术知其所以然,另一方面,在采坑的过程中不断 ...
- 扩展spring data jpa的repository
在我们编写代码的过程中,spring data jpa为我们的持久层提供的极大的方便,但有时spring data jpa提供的repository并不能完全满足我们开发的需求,因此就需要进行扩展.s ...
- 《spring技术内幕》读书笔记(1)——什么是POJO模式
今天在看<spring技术内幕>,第一章中多次提到了使用POJO来完成开发,就百度了一下,在此保留 1. 什么是POJO POJO的名称有多种,pure old java obje ...
- Spring技术内幕:SpringIOC原理学习总结
前一段时候我把Spring技术内幕的关于IOC原理一章看完,感觉代码太多,不好掌握,我特意又各方搜集了一些关于IOC原理的资料,特加深一下印象,以便真正掌握IOC的原理. IOC的思想是:Spring ...
随机推荐
- BZOJ5194: [Usaco2018 Feb]Snow Boots(排序&set)(可线段树优化)
5194: [Usaco2018 Feb]Snow Boots Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 102 Solved: 79[Subm ...
- bzoj 4303 数列
bzoj 4303 数列 二维 \(KD-Tree\) 模板题. \(KD-Tree\) 虽然在更新和查询的方式上类似于线段树,但其本身定义是类似于用 \(splay/fhq\ treap\) 维护区 ...
- CaptureMouse/CaptureStylus 可能会失败
在 WPF 中,如果我们要做拖动效果,通常会调用一下 CaptureMouse/CaptureStylus 以便当鼠标或手指离开控件的时候依然能够响应 Move 和 Up 事件.不知有没有注意到这两个 ...
- C++ sort 函数用法
MSDN中的定义: template<class RanIt>void sort(RanIt first, RanIt last); //--> 1)template<clas ...
- oracle数据库存储过程分页
CREATE OR REPLACE PROCEDURE prc_query (p_tableName in varchar2, --表名 p_columnNames in varchar2, --字段 ...
- iOS7 自己定义动画跳转
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/Liar0606/article/details/26399125 简单介绍 在iOS7系统中,假设你 ...
- springboot使用hibernate validator校验方式
一.参数校验 在开发中经常需要写一些字段校验的代码,比如字段非空,字段长度限制,邮箱格式验证等等,写这些与业务逻辑关系不大的代码个人感觉有两个麻烦: 验证代码繁琐,重复劳动 方法内代码显得冗长 每次要 ...
- 笔记:NPM 无限需要依赖问题解决
笔记:NPM 无限需要依赖问题解决 起因 因为想学一下 VUE,开始跟着教程一步一步输出命令,开始也没有什么问题,一切都很顺利. 突然不知道是哪一步出了问题,一直让我安装依赖,没完没了,开始并不觉得有 ...
- volatile浅析
volatile的意思是不稳定的.易变的,但在多线程中却跟字面意思一毛钱关系没有.作为一个变量修饰符,它主要有两个作用:一个是告诉大家,该变量是一个在多个线程之间均可见的变量:另一个是告诉java虚拟 ...
- ipvsadm的命令参考
相信很多同学和我差不多,半桶水,貌似在配置lvs双机的时候,直接用的keepalived,ipvsadm就用来看看,感觉没啥用,今天无聊到处逛发现,某大神说,keepalived只是ipvsadm的一 ...