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 ...
随机推荐
- [Java]如何为一个自定义类型的List排序。
好吧,三年了,又重拾我的博客了,是因为啥呢,哈哈哈.今天被问到一个题目,当场答不出来,动手动的少了,再此记录下来. Q:有一个MyObject类型的List,MyObject定义如下: class M ...
- Mysql 分组查询最高分
今天告诉我要写一个服务,目的是按照每个班中各分组中竞赛最高分组平分小组得分给各个成员的服务,于是就有两个技术需求 1 查询每个班的冠军团队 2 增加一组人的分数 从“1”中,查出每个班N个分组中的得分 ...
- BZOJ3196 Tyvj1730 二逼平衡树 【树套树】 【线段树套treap】
BZOJ3196 Tyvj1730 二逼平衡树 Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间内排名 ...
- 剑指offer第二章
剑指offer第二章 1.二维数组中的查找 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含 ...
- HTML5的28个常用特性
1. 新的Doctype 尽管使用<!DOCTYPE html>,即使浏览器不懂这句话也会按照标准模式去渲染 2. Figure元素 用<figure>和<figcapt ...
- 在一个form中有两个submit,值分别为修改和删除,如何在提交时用js判断submit值为修改还是删除呢
同一个form里,不管哪个 submit 都是直接提交form表单里的内容. 要达到你的目的,就不能用类型为 submit 的按钮,要用 button,然后加onclick 方法来自定义预处理参数,然 ...
- db_recovery_file_dest_size 修改大一点及删除归档日志 |转|
今天给客户测 试问题,让客户把数据发过来了.解压缩后一看,他们还是用的oracle 815版本的(他们exp导出时,带了导出日志,从导出日志中看出来是oracle 815版本的),不过没有关系,低版本 ...
- HDFS(一)
HDFS的概念 HDFS首先是文件系统(FileSystem,FS),尽管这个FS是基于OS原生的文件系统之上:而且这个文件系统是一个抽象概念,HDFS作为一个整体出现,对外(client)隐藏了其内 ...
- 关于RAS加密中pfx格式提取字符串私钥 (转)
openssl 使用以下命令 如果如果执行出错,请查看是否安装环境或在命令前面加上openssl --提取出来的无法直接使用 pkcs12 -in zhaoshang2.pfx -nocerts -n ...
- "废物利用"也抄袭——废旧喷墨打印机和光驱DIY"绘图仪"
很长时间没有写博客,因为各种各样的事情占去大块时间,只有零碎时间偶尔在CSDN逛逛也偶尔回几个帖子.很久以前就看到一些光驱DIY雕刻机之类的,很是向往,最近这几天得闲就TB了一套Arduino UNO ...