您的位置:首页 > 编程语言 > Java开发

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

2016-05-30 15:12 531 查看
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;

}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: