一 .Spring data简介:
Spring Data是一个用于简化数据库访问,并支持云服务的开源框架。其主要目标是使得对数据的访问变得方便快捷,并支持map-reduce框架和云计算数据服务。 Spring Data 包含多个子项目:
Commons - 提供共享的基础框架,适合各个子项目使用,支持跨数据库持久化
JPA - 简化创建 JPA 数据访问层和跨存储的持久层功能
Hadoop - 基于 Spring 的 Hadoop 作业配置和一个 POJO 编程模型的 MapReduce 作业
Key-Value - 集成了 Redis 和 Riak ,提供多个常用场景下的简单封装
Document - 集成文档数据库:CouchDB 和 MongoDB 并提供基本的配置映射和资料库支持
Graph - 集成 Neo4j 提供强大的基于 POJO 的编程模型
Graph Roo AddOn - Roo support for Neo4j
JDBC Extensions - 支持 Oracle RAD、高级队列和高级数据类型
Mapping - 基于 Grails 的提供对象映射框架,支持不同的数据库
Examples - 示例程序、文档和图数据库
Guidance - 高级文档
二.Spring data JPA提供给用户使用的,主要有以下几个接口:
Repository:仅仅是一个标识,表明任何继承它的均为仓库接口类,方便Spring自动扫描识别
CrudRepository:继承Repository,实现了一组CRUD相关的方法
PagingAndSortingRepository:继承CrudRepository,实现了一组分页排序相关的方法
JpaRepository:继承PagingAndSortingRepository,实现一组JPA规范相关的方法
JpaSpecificationExecutor:比较特殊,不属于Repository体系,实现一组JPA Criteria查询相关的方法
三.spring data jpa作用
我们都知道,在使用持久化工具的时候,一般都有一个对象来操作数据库,在原生的Hibernate中叫做Session,在JPA中叫做EntityManager,在MyBatis中叫做SqlSession,通过这个对象来操作数据库。我们一般按照三层结构来看的话,Service层做业务逻辑处理,Dao层和数据库打交道,在Dao中,就存在着上面的对象。那么ORM框架本身提供的功能有什么呢?答案是基本的CRUD,所有的基础CRUD框架都提供,我们使用起来感觉很方便,很给力,业务逻辑层面的处理ORM是没有提供的,如果使用原生的框架,业务逻辑代码我们一般会自定义,会自己去写SQL语句,然后执行。在这个时候,Spring-data-jpa的威力就体现出来了,ORM提供的能力他都提供,ORM框架没有提供的业务逻辑功能Spring-data-jpa也提供,全方位的解决用户的需求。使用Spring-data-jpa进行开发的过程中,常用的功能,我们几乎不需要写一条sql语句
四.实例
实体类:
domain里Dept.java:
package cn.itcast.domain;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.hibernate.annotations.GenericGenerator;
@Table(name="DEPT_P")
@Entity
public class Dept implements Serializable{
@Id
@Column(name="DEPT_ID")
@GeneratedValue(generator="sys-uuid")
@GenericGenerator(name="sys-uuid",strategy="uuid")
private String id; //部门id
@Column(name="DEPT_NAME")
private String deptName; //部门名称
@ManyToOne
@JoinColumn(name="PARENT_ID",referencedColumnName="DEPT_ID")
private Dept parent; //父部门
@Column(name="STATE")
private Integer state; //状态 0:取消 1:运营
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
public Dept getParent() {
return parent;
}
public void setParent(Dept parent) {
this.parent = parent;
}
public Integer getState() {
return state;
}
public void setState(Integer state) {
this.state = state;
}
}
dao层:
package cn.itcast.dao;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import cn.itcast.domain.Dept;
public interface DeptDao extends JpaRepository<Dept, String>,JpaSpecificationExecutor<Dept>{
@Query("from Dept where deptName = ?1") //jpql
public List<Dept> findDeptByName(String name);
}
service层:提供CRUD接口
package cn.itcast.service;
import java.util.Collection;
import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import cn.itcast.domain.Dept;
public interface DeptService {
//查询所有,带条件查询
public List<Dept> find(Specification<Dept> spec);
//获取一条记录
public Dept get(String id);
//分页查询,将数据封装到一个page分页工具类对象
public Page<Dept> findPage(Specification<Dept> spec, Pageable pageable);
//新增和修改保存
public void saveOrUpdate(Dept entity);
//批量新增和修改保存
public void saveOrUpdateAll(Collection<Dept> entitys);
//单条删除,按id
public void deleteById( String id);
//批量删除
public void delete(String[] ids);
}
serviceImpl:实现类,直接调dao层的方法即可
package cn.itcast.service.impl;
import java.util.Collection;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import cn.itcast.dao.DeptDao;
import cn.itcast.domain.Dept;
import cn.itcast.service.DeptService;
@Service
public class DeptServiceImpl implements DeptService{
@Autowired
private DeptDao deptDao;
@Override
public List<Dept> find(Specification<Dept> spec) {
// TODO Auto-generated method stub
return deptDao.findAll(spec);
}
@Override
public Dept get(String id) {
// TODO Auto-generated method stub
return deptDao.findOne(id);
}
@Override
public Page<Dept> findPage(Specification<Dept> spec, Pageable pageable) {
// TODO Auto-generated method stub
return deptDao.findAll(spec, pageable);
}
@Override
public void saveOrUpdate(Dept entity) {
// TODO Auto-generated method stub
deptDao.save(entity);
}
@Override
public void saveOrUpdateAll(Collection<Dept> entitys) {
// TODO Auto-generated method stub
deptDao.save(entitys);
}
@Override
public void deleteById(String id) {
// TODO Auto-generated method stub
deptDao.delete(id);
}
@Override
public void delete(String[] ids) {
// TODO Auto-generated method stub
for (String id : ids) {
deptDao.delete(id);
}
}
}
测试类:
package cn.itcast.test;
import java.util.List;
import org.aspectj.weaver.reflect.DeferredResolvedPointcutDefinition;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import cn.itcast.dao.DeptDao;
import cn.itcast.domain.Dept;
import cn.itcast.service.DeptService;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class JpaTest {
@Autowired
private DeptDao deptDao;
@Autowired
private DeptService deptService;
@Test
public void testFindDept(){
Dept dept = deptDao.findOne("100");
System.out.println(dept.getDeptName());
}
//新增
@Test
public void testAddDept(){
Dept dept = new Dept();
dept.setDeptName("测试部门");
dept.setState(1);
deptService.saveOrUpdate(dept);
System.out.println("新增完成");
}
//根据id数据库查询对象,查到更新所有属性,没查到根据本次提交的属性进行新增
@Test
public void testUpdateDept(){
Dept dept = new Dept();
dept.setId("11111");
dept.setDeptName("测试3");
deptService.saveOrUpdate(dept);
}
@Test
public void testDeleteDept(){
deptService.deleteById("8a7e863b60fe47c60160fe47ceb90000");
}
@Test
public void testFindDeptByName(){
List<Dept> findDeptByName = deptDao.findDeptByName("测试3");
for (Dept dept : findDeptByName) {
System.out.println(dept.getDeptName());
}
}
}
配饰文件applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
<!-- 1.dataSource-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="oracle.jdbc.driver.OracleDriver" />
<property name="jdbcUrl" value="jdbc:oracle:thin:@localhost:1521:mldn" />
<property name="user" value="itcast297" />
<property name="password" value="itcast297" />
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="cn.itcast.domain" />
<property name="persistenceProvider">
<bean class="org.hibernate.jpa.HibernatePersistenceProvider" />
</property>
<!--JPA的供应商适配器-->
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="generateDdl" value="false" />
<property name="database" value="ORACLE" />
<property name="databasePlatform" value="org.hibernate.dialect.Oracle10gDialect" />
<property name="showSql" value="true" />
</bean>
</property>
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
</property>
<property name="jpaPropertyMap">
<map>
<entry key="hibernate.query.substitutions" value="true 1, false 0" />
<entry key="hibernate.default_batch_fetch_size" value="16" />
<entry key="hibernate.max_fetch_depth" value="2" />
<entry key="hibernate.enable_lazy_load_no_trans" value="true"></entry>
<entry key="hibernate.generate_statistics" value="true" />
<entry key="hibernate.bytecode.use_reflection_optimizer"
value="true" />
<entry key="hibernate.cache.use_second_level_cache" value="false" />
<entry key="hibernate.cache.use_query_cache" value="false" />
</map>
</property>
</bean>
<!-- JdbcTemplate配置 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 告诉spring生成shiro代理子类时,采用cglib方式生成 -->
<aop:aspectj-autoproxy proxy-target-class="true" />
<!-- 3.事务管理器-->
<!-- 整合spring data jpa-->
<jpa:repositories base-package="cn.itcast.dao"
transaction-manager-ref="transactionManager"
entity-manager-factory-ref="entityManagerFactory"></jpa:repositories>
<!-- JPA事务管理器 -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<!-- 4.txAdvice-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED"/>
<tx:method name="insert*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="delete*" propagation="REQUIRED"/>
<tx:method name="get*" read-only="true"/>
<tx:method name="find*" read-only="true"/>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!-- 5.aop-->
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* cn.itcast.service.*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut" />
</aop:config>
<context:component-scan base-package="cn.itcast"></context:component-scan>
<!--组装其它 配置文件-->
</beans>
结果:如测试testFindDept方法:
这里可以发现实际上是EntityManager在作用,连接数据库,并且里面有多个写好的方法,直接调用即可