一、maven配置文件加入依赖


Spring Data JPA 依赖,最新稳定的版本为1.10.1.RELEASE,这里需要说明下的是,其依然依赖hibernate JPA相关JAR,hibernate-core之类的是不需要的。hibernate是JPA规范的一种实现,所以需要加入其依赖。ehcache是hibernate二级缓存的配置,不是必须的。


        org.springframework.data
        spring-data-jpa
        1.10.1.RELEASE



    org.hibernate
    hibernate-ehcache
    5.1.0.Final


    org.hibernate
	hibernate-validator
	5.2.4.Final


	org.hibernate
	hibernate-entitymanager
	5.1.0.Final

二、声明持久层接口


这里给大家说说几个常见的很重要的核心类文件,源码下面也贴上了。


Spring Data JPA 1.10.1 详解二之快速Demo_第1张图片


大家可以看到这个类的继承结构,这里值得说的是,Spring Data JPA的持久层的借口命名是有一套规范的,后面你加入的自定义方法满足其规范之后,你的实现类都是可以不需要写的,而且事务管理也帮你做好了。是不是觉得很神奇呢!

JpaRepository继承了PagingAndSortingRepository、QueryByExampleExecutor,PagingAndSortingRepository又继承了CrudRepository,CrudRepository 大家通过看名字也应该是干啥的,其就是CRUD的,PagingAndSortingRepository里面加了分页的相关方法。

CrudRepository.java

package org.springframework.data.repository;

import java.io.Serializable;

@NoRepositoryBean
public interface CrudRepository extends Repository {

	 S save(S entity);

	 Iterable save(Iterable entities);

	T findOne(ID id);

	boolean exists(ID id);

	Iterable findAll();

	Iterable findAll(Iterable ids);

	long count();

	void delete(ID id);

	void delete(T entity);

	void delete(Iterable entities);

	void deleteAll();
}

Repository.java 是一个空的接口

package org.springframework.data.repository;

import java.io.Serializable;

public interface Repository {

}

大伙可以看看其源码,源码里面的注释我就不贴出来了,大家看方法名应该就知道其具体的意思了。
package org.springframework.data.jpa.repository;

import java.io.Serializable;
import java.util.List;

import javax.persistence.EntityManager;

import org.springframework.data.domain.Example;
import org.springframework.data.domain.Sort;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.repository.query.QueryByExampleExecutor;

@NoRepositoryBean
public interface JpaRepository
		extends PagingAndSortingRepository, QueryByExampleExecutor {

	List findAll();

	List findAll(Sort sort);

	List findAll(Iterable ids);

	 List save(Iterable entities);

	void flush();

	 S saveAndFlush(S entity);

	void deleteInBatch(Iterable entities);

	void deleteAllInBatch();

	T getOne(ID id);

	@Override
	 List findAll(Example example);

	@Override
	 List findAll(Example example, Sort sort);

}


大家用maven的时候,可以将源码顺便下下来,myeclipse里面设置一下即可,如图所示:

Spring Data JPA 1.10.1 详解二之快速Demo_第2张图片


我这里的接口如下:

package com.example.dao;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;

import com.example.entity.UserInfo;

public interface UserDaoSpringJpa extends JpaRepository{

	public List findByUsername(String username);//注意这个命名,Spring会自动根据这个username去数据库里面取值,可以看到后面生成的sql语句,where条件里面就加了 where user_name =?,这就是Spring Data JPA查询命名的方便之处,只要按规则命名,他会采取一定的策略,通过解析方法名称创建查询,来生成sql语句。
}


JpaRepository 这里是泛型接口,UserInfo是我们的实体类,String是主键类型,也称为id,大家以前写hibernatebasedao的时候可能是见过了的。这叫 泛型限定式依赖注入,也是Spring4的一大特性。之前有篇博文也提到了 http://enetq.blog.51cto.com/479739/1783339


三、在接口中声明自定义业务方法

Spring Data JPA将会根据指定的策略(后续会有文章说明,本此只是简单的介绍下,能跑起来。)为该方法生成实现代码,用户不需要实现该接口,这样就只需要写接口就行了。


四、Spring配置文件相关配置

配置文件中加入 jpa:repositories,启用扫描并自动创建代理 Spring 初始化容器时将会扫描 base-package 指定的包目录及其子目录,为继承 Repository 或其子接口的接口创建代理对象,并将代理对象注册为 Spring Bean,业务层便可以通过 Spring autowired来直接使用该对象。


此需要jpa命名空间:

xmlns:jpa="

xsi:schemaLocation="
       http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
       "

具体的配置参加如下:各参数的含义配置文件里面已经给出了详细的解释,同时给出了相关配置类的源码。

Spring Data JPA 1.10.1 详解二之快速Demo_第3张图片

一些配置的属性,大家在源码里面也是可以找到的。

Spring Data JPA 1.10.1 详解二之快速Demo_第4张图片


 		 

	 
 
 
    
          
        
        
        
        
            
        
        
        
            
                
                
                
                
            
        
        
        
            
        
        
        
            
        
                 
				
				
				
				
				
				
				

				
				
				
				
				
				
				
                
            
        
    
    
    
    
        
    
 		


jpaVendorAdapter 相关参数的设置AbstractJpaVendorAdapter 类里面有详细说明:如下图所示:

Spring Data JPA 1.10.1 详解二之快速Demo_第5张图片

Spring Data JPA 1.10.1 详解二之快速Demo_第6张图片

五、测试

package com.example.action;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;

import com.example.entity.UserInfo;
import com.example.service.impl.UserInfoService;
import com.google.gson.Gson;

@Controller
public class UserInfoAction {
	 
	@Autowired
	private UserInfoService userInfoService;
	 
	private Logger log = Logger.getLogger(this.getClass());

	@RequestMapping("findByUserName.do")
	public void findByUserName(HttpServletRequest request,
			HttpServletResponse response, ModelMap map) throws IOException{
		List listUserInfo = userInfoService.findByUsername("wj");
		
		for(UserInfo userInfo:listUserInfo){
			log.info(userInfo.getUsername()+":"+userInfo.getEmail());
		}
		
		Gson gson = new Gson();
		String jsonStr = gson.toJson(listUserInfo);
		response.getWriter().println(jsonStr);
	}
	
	@RequestMapping("saveUser.do")
	public void saveUser(HttpServletRequest request,
			HttpServletResponse response, ModelMap map) throws IOException{
		List listUserInfo = new ArrayList();
		
		for(int i=0;i<10;i++){
			UserInfo userInfo = new UserInfo();
			
			userInfo.setId(UUID.randomUUID().toString());
			userInfo.setUsername(Math.random()+"wj"+i);
			userInfo.setPassword(Math.random()+"ss"+i);
			listUserInfo.add(userInfo);
		}
		
		listUserInfo = userInfoService.save(listUserInfo);//可以直接保存一个list集合,当然这里只是测试,实际的批量新增,批量更新的时候,是需要到一定的条数之后,flush一下的,比如20条,这根hibernate是类似的。
		
		userInfoService.delete("21");//删除
		
		UserInfo userInfo = userInfoService.findOne("2eab2884-e0e9-419c-8871-1d198b399813");
		userInfo.setUsername("zhangsan");
		userInfoService.saveAndFlush(userInfo);//更新
		Gson gson = new Gson();
		String jsonStr = gson.toJson(listUserInfo);
		response.getWriter().println(jsonStr);
	}
}

经过测试,大家发现 新增、查询、删除、修改都是正常的

Hibernate: select userinfo0_.id as id1_4_, userinfo0_.birthday as birthday2_4_, userinfo0_.contact as contact3_4_, userinfo0_.create_time as create_t4_4_, userinfo0_.create_user as create_u5_4_, userinfo0_.delete_flag as delete_f6_4_, userinfo0_.email as email7_4_, userinfo0_.last_login_ip as last_log8_4_, userinfo0_.last_login_time as last_log9_4_, userinfo0_.last_logout_time as last_lo10_4_, userinfo0_.modify_time as modify_11_4_, userinfo0_.online_state as online_12_4_, userinfo0_.password as passwor13_4_, userinfo0_.register_time as registe14_4_, userinfo0_.sex as sex15_4_, userinfo0_.user_state as user_st16_4_, userinfo0_.username as usernam17_4_ from rbac.user_info userinfo0_ where userinfo0_.username=?

Hibernate: insert into rbac.user_info (birthday, contact, create_time, create_user, delete_flag, email, last_login_ip, last_login_time, last_logout_time, modify_time, online_state, password, register_time, sex, user_state, username, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)

insert 语句打印了10条,


delete from rbac.user_info where id=?

Hibernate: update rbac.user_info set birthday=?, contact=?, create_time=?, create_user=?, delete_flag=?, email=?, last_login_ip=?, last_login_time=?, last_logout_time=?, modify_time=?, online_state=?, password=?, register_time=?, sex=?, user_state=?, username=? where id=?