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 ...
随机推荐
- day5 io模型
五种概览:http://www.cnblogs.com/xiehongfeng100/p/4763225.html http://sukai.me/linux-five-io-models/ 内有多 ...
- Codeforces 1027E Inverse Coloring 【DP】
Codeforces 1027E Inverse Coloring 题目链接 #include<bits/stdc++.h> using namespace std; #define N ...
- hive表数据导出到csv乱码原因及解决方案
转载自http://blog.csdn.net/lgdlxc/article/details/42126225 Hive表中的数据使用hive - e"select * from table ...
- asp.net core microservices 架构之 分布式自动计算(一)
一:简介 自动计算都是常驻内存的,没有人机交互.我们经常用到的就是console job和sql job了.sqljob有自己的宿主,与数据库产品有很关联,暂时不提.console job使 ...
- cannot find lstdc++
centos下编译grpc-java时遇到的问题,google了一下 : sudo yum install libstdc++-static
- selenium数据驱动
Selenium最后一个知识点——数据驱动.学会了这个Selenium就算学完啦~ 看代码: 这是修改的testSell.py文件. # coding: utf-8 import ddtimport ...
- 通过修改注册表建立Windows自定义协议
引言 本文主要介绍注册表的概念与其相关根项的功能,以及浏览器如何通过连接调用自定义协议并与客户端进行数据通信.文中讲及如何通过C#程序.手动修改.安装项目等不同方式对注册表进行修改.其中通过安装项目对 ...
- ubuntu :安装好了搜狗输入法但是没法用
用 im-config 命令打开一个配置器窗口 默认是ibus,需要修改为 fcitx 重启 ubuntu 系统就可以了.
- RTMP(实时信息传输协议)详解
RTMP协议是Real Time Message Protocol(实时信息传输协议)的缩写,它是由Adobe公司提出的一种应用层的协议,用来解决多媒体数据传输流的多路复用(Multiplexing) ...
- js正则验证
/判断输入内容是否为空 function IsNull(){ var str = document.getElementById('str').value.trim(); ...