详细介绍springData

1.什么是SpringData?
Spring Data 项目的目的是为了简化构建基于 Spring 框架应用的数据访问计数,包括非关系数据库、Map-Reduce 框架、云数据服务等等;另外也包含对关系数据库的访问支持。

Spring Data 包含多个子项目:

Commons - 提供共享的基础框架,适合各个子项目使用,支持跨数据库持久化
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、高级队列和高级数据类型
JPA - 简化创建 JPA 数据访问层和跨存储的持久层功能
Mapping - 基于 Grails 的提供对象映射框架,支持不同的数据库
Examples - 示例程序、文档和图数据库
Guidance - 高级文档

看了这么多专业的介绍,其实Spring Data项目旨在为大家提供一种通用的编码模式,统一我们的API。

2.HelloWorld展示
学习任何东西,从一个简单易懂的DEMO学起,会非常重要,下面先来看一个简单的HelloWorlddemo
直接看一下Dao层吧!

 * @FileName: PersonRepotory.java     
 * @Package:com.tgb.springdata.Entity     
 * @Description: TODO    
 * @author: LUCKY      
 * @date:2015年11月8日 下午6:38:58     
 * @version V1.0       
 */    
package com.tgb.springdata.Entity;    
    
import java.util.Date;    
import java.util.List;    
    
import org.hibernate.type.TrueFalseType;    
import org.springframework.data.jpa.repository.JpaRepository;    
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;    
import org.springframework.data.jpa.repository.Modifying;    
import org.springframework.data.jpa.repository.Query;    
import org.springframework.data.jpa.repository.support.JpaRepositoryFactory;    
import org.springframework.data.repository.CrudRepository;    
import org.springframework.data.repository.PagingAndSortingRepository;    
import org.springframework.data.repository.Repository;    
import org.springframework.data.repository.query.Param;    
    
/**    
 * @ClassName: PersonRepotory     
 * @Description: TODO    
 * @author: LUCKY    
 * @date:2015年11月8日 下午6:38:58       
 */    
    
/*  
 * 1.Repository是一个空接口,即是一个标记接口  
 * 2.若我们定义的接口继承了Repository,则该接口会被IOC容器识别为一个Repository Bean  
 * 注入到IOC容器中,进而可以在该接口中定义满足一定规则的接口  
 * 3.实际上也可以通过一个注解@RepositoryDefination 注解来替代Repository接口  
 */    
/*  
 * 在Repository子接口中声明方法  
 * 1.不是随便声明的,而需要符合一定的规范  
 * 2.查询方法以find|read|get开发  
 * 3.涉及条件查询,条件的属性需要定义关键字连接  
 * 4.要注意的额是,条件的属性以字母大写  
 * 5.支持属性的级联查询,若当前类有符合条件的属性,则优先使用,则不使用级联属性  
 * 若需要使用级联属性,则属性之间使用——进行连接  
 */    
//@RepositoryDefinition(domainClass=Person.class,idClass=Integer.class)    
public interface PersonRepotory  extends JpaRepository<Person,Integer>,JpaSpecificationExecutor<Person>,PersonDao  {    
    
        
    //根据lastname,来获取对应的Person    
    Person getByLastName(String lastName);    
        
    //Where lastName like ?% and id<?    
    List<Person> getByLastNameStartingWithAndIdLessThan(String lastName,Integer id);    
        
        
    //Where lastName like ?% and id<?    
    List<Person> getByLastNameEndingWithAndIdLessThan(String lastName,Integer id);    
        
    //where email In(?,?,?) Or birth < ?    
    List<Person> getByEmailInOrBirthLessThan(List<String> emails,Date birth);    
        
    //where a.id>?    
    List<Person> getByAddressIdGreaterThan(Integer id);    
        
    //查询id值最大的那个person    
    //使用@Query注解可以自定义JPQL语句,语句可以实现更灵活的查询    
@Query("SELECT p FROM Person p WHERE p.id=(SELECT max(p2.id) FROM Person p2)")    
Person getMaxIdPerson();    
    
    //为@Query注解传递参数的方式1:使用占位符    
@Query("SELECT P FROM Person P where P.lastName=?1 AND P.email=?2")    
List<Person> testQueryAnnotationParams1(String lastName,String email);    
        
        
        
    //为@Query注解传递参数的方式2:使用命名参数方式    
  

  @Query("SELECT P FROM Person P where P.lastName=:lastName AND P.email=:email")    
    List<Person> testQueryAnnotationParams2(@Param("email")String email,@Param("lastName")String lastName);    
            
            
        //Spring Data 运行在占位符上添加%%    
        @Query("select p from Person p where p.lastName like %?1% or p.email like %?2%")    
        List<Person> testQueryAnnotationLikeParam(String lastName,String email);    
            
        //设置nativeQuery=true 可以使用原生的sql查询    
        @Query(value="SELECT count(id) FROM jpa_persons",nativeQuery=true)    
        public long getTotalCount();    
            
            
        //可以通过自定义的JPQL 完成update和delete操作,注意:JPQL不支持Insert操作    
        //在@Query注解中编写JPQL语句,但必须使用@Modify进行修饰,以通知SpringData,这是一个Update或者Delete    
        //Update或者delete操作,需要使用事务,此时需要定义Service层,在service层的方法上添加事务操作    
        //默认情况下,SpringData的每个方法上有事务,但都是一个只读事务,他们不能完成修改操作    
        @Modifying    
        @Query("update Person p set p.email=:email where id=:id")    
        void updatePersonEmail(@Param("id")Integer id,@Param("email")String email);    
            
            
}   

在Spring Data JPA中通过继承接口就可以了,下面来看一下是如何来调用的

 * @FileName: SpringDataTest.java     
 * @Package:com.tgb.test     
 * @Description: TODO    
 * @author: LUCKY      
 * @date:2015年11月8日 下午5:35:37     
 * @version V1.0       
 */    
package com.tgb.test;    
    
import static org.junit.Assert.*;    
    
import java.sql.SQLException;    
import java.util.ArrayList;    
import java.util.Arrays;    
import java.util.Date;    
import java.util.List;    
    
import javax.persistence.criteria.CriteriaBuilder;    
import javax.persistence.criteria.CriteriaQuery;    
import javax.persistence.criteria.Path;    
import javax.persistence.criteria.Predicate;    
import javax.persistence.criteria.Root;    
import javax.sql.DataSource;    
    
import org.junit.Test;    
import org.springframework.context.ApplicationContext;    
import org.springframework.context.support.ClassPathXmlApplicationContext;    
import org.springframework.data.domain.Page;    
import org.springframework.data.domain.PageRequest;    
import org.springframework.data.domain.Pageable;    
import org.springframework.data.domain.Sort;    
import org.springframework.data.domain.Sort.Direction;    
import org.springframework.data.domain.Sort.Order;    
import org.springframework.data.jpa.domain.Specification;    
    
import com.tgb.springdata.Entity.Person;    
import com.tgb.springdata.Entity.PersonRepotory;    
import com.tgb.springdata.Service.PersonService;    
    
/**    
 * @ClassName: SpringDataTest     
 * @Description: TODO    
 * @author: LUCKY    
 * @date:2015年11月8日 下午5:35:37       
 */    
public class SpringDataTest {    
    
    private PersonRepotory personRepotory=null;    
    private PersonService personService;    
    private ApplicationContext ctx=null;    
    {    
        ctx=new ClassPathXmlApplicationContext("applicationContext.xml");    
        personRepotory=ctx.getBean(PersonRepotory.class);    
        personService=ctx.getBean(PersonService.class);    
    }    
        
        
    @Test    
    public void testKeyWorlds(){    
        List<Person> persons=personRepotory.getByLastNameStartingWithAndIdLessThan("BB", 10);    
        System.out.println(persons);    
            
        List<Person> persons1=personRepotory.getByLastNameEndingWithAndIdLessThan("BB", 10);    
        System.out.println(persons);    
        System.out.println(persons1);    
            
        persons=personRepotory.getByEmailInOrBirthLessThan(Arrays.asList("aa@qq.com","bb@qq.com"),new Date());    
        System.out.println(persons.size());    
    }    
        
        
        
        
        
    @Test    
    public void testDataSource() throws SQLException{    
        DataSource dataSource=ctx.getBean(DataSource.class);    
        System.out.println(dataSource.getConnection());    
    }    
        
    @Test    
    public void TestJpa(){    
            
    }    
        
    @Test    
    public void testKeyWorlds2(){    
        List<Person> persons=personRepotory.getByAddressIdGreaterThan(1);    
        System.out.println(persons);    
    }    
        
    @Test    
    public void testQueryAnnotation(){    
        Person person=personRepotory.getMaxIdPerson();    
//      System.out.println(person);    
            
        List<Person> persons=personRepotory.testQueryAnnotationParams1("AA", "bb");    
        System.out.println(persons);    
            
        List<Person> persons1=personRepotory.testQueryAnnotationParams2("bb", "AA");    
        System.out.println(persons1);    
    }    
        
        
    @Test    
    public void testModifing(){    
//      personRepotory.updatePersonEmail(1, "@@qq.com");    
        personService.updatePersonEmail("aa@aa", 1);    
    }    
        
    @Test    
    public void testQueryLikeAnnotationParam(){    
        List<Person> persons=personRepotory.testQueryAnnotationLikeParam("%AA%", "%b%");    
        System.out.println(persons);    
            
        long count=personRepotory.getTotalCount();    
        System.out.println(count);    
    }    
        
        
        
        
    @Test    
    public void HelloWorldSpringData(){    
        PersonRepotory personRepotory=ctx.getBean(PersonRepotory.class);    
        System.out.println(personRepotory.getClass().getName());    
        Person person=personRepotory.getByLastName("AA");    
        System.out.println(person);    
            
        }    
        
        
    @Test    
    public void testCrudRepository()    
    {    
        List<Person> persons=new ArrayList<Person>();    
        for (int i = 1; i < 10000; i++) {    
            Person person=new Person();    
            person.setBirth(new Date());    
            person.setEmail("@2"+i+" com");    
            persons.add(person);    
        }    
            
        long startTime=System.currentTimeMillis();    
        personService.savePersons(persons);    
        long endTime=System.currentTimeMillis();    
        System.out.println((endTime-startTime)/1000);    
    }    
        
        
    @Test    
    public void testPagingAndSortingRespository(){    
        //pageNumber是从0开始的    
        int pageNumber=4;    
        int pageSize=5;    
        //PageAble 接口通常用的是PageRequest实现类,其中封装了需要分页的信息    
        //排序相关的,sor封装了排序的信息    
        Order order1=new Order(Direction.DESC, "id");    
            
        Order order2=new Order(Direction.DESC, "email");    
        Sort sort=new Sort(order1,order2);    
            
            
        Pageable pageable=new PageRequest(pageNumber, pageSize,sort);    
        Page<Person> page=personRepotory.findAll(pageable);    
        System.out.println("总记录数"+page.getTotalElements());    
        System.out.println("当前第几页"+page.getNumber());    
        System.out.println("总页数"+page.getTotalPages());    
        System.out.println("当前页面的List"+page.getContent());    
        System.out.println("当前页面的记录数"+page.getNumberOfElements());    
    }    
        
        
    @Test    
    public void testJpaRepository(){    
        Person person=new Person();    
        person.setBirth(new Date());    
        person.setEmail("aa");    
        person.setLastName("xyz");    
        personRepotory.saveAndFlush(person);    
            
            
    }    
        
        
    /*  
     * 实现带查询条件的分页效果 id>5  
     * 调用JpaSpecificationExecutor的page<T> findAll(Speciation<T>,PageAble pageable)  
     * specification:封装了JPA Criteria 查询的条件  
     * pageable:封装了请求分页的消息,例如pageno,pagesize,sort  
     */    
    @Test    
    public void testJpaSpeciationExecutor(){    
        int pageNo=0;    
        int pageSize=5;    
        PageRequest pageRequest=new PageRequest(pageNo, pageSize);    
        //通常使用Specification 的匿名内部类,    
        Specification<Person> specification=new Specification<Person>() {    
    
        /*  
         * @param root:代表的查询的实体类  
         * @param query:可以从中得到Root对象,即告知JPA Criteria查询要查询哪一个实体类,  
         * 还可以来添加查询条件,还可以结合EntityManager对象得到最终查询的TypedQuery 对象  
         * @Param cb:criteriabuildre对象,用于创建Criteria相关的对象工程,当然可以从中获取到predicate类型  
         * @return:代表一个查询条件  
         */    
            @Override    
            public Predicate toPredicate(Root<Person> root,    
                    CriteriaQuery<?> query, CriteriaBuilder cb) {    
//              Path path=root.get("id");    
//              Predicate predicate=cb.gt(path, 5);    
                    
                Predicate p1=cb.like(root.get("id").as(String.class), "%"+"1"+"%");    
                Predicate p2=cb.equal(root.get("lastName").as(String.class), "sd");    
                Predicate p3=cb.like(root.get("email").as(String.class), "%s%");    
//              构建组合的Predicate示例:    
                Predicate p = cb.and(p3,cb.or(p1,p2));    
                    
                return p;    
            }    
                
        };    
            
        Page<Person> page=personRepotory.findAll(specification,pageRequest);    
        
        System.out.println("总记录数"+page.getTotalElements());    
        System.out.println("当前第几页"+page.getNumber());    
        System.out.println("总页数"+page.getTotalPages());    
        System.out.println("当前页面的List"+page.getContent());    
        System.out.println("当前页面的记录数"+page.getNumberOfElements());    
    }    
        
        
    @Test    
    public void testCustomRepositoryMethod(){    
        personRepotory.test();    
    }    
        
        
}  

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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">



    <bean id="datasource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="url" value="jdbc:mysql://localhost:3306/test"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean>

    <context:component-scan base-package="com.zcl"/>
</beans>

PersonServiceImpl

package com.zcl.test.service.impl;

import com.zcl.test.bean.Person;
import com.zcl.test.dao.IEmpInfoDAO;
import com.zcl.test.dao.PersonRepotory;
import com.zcl.test.service.PersonService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

@Service("personService")
public class PersonServiceImpl implements PersonService {
    //注入一个dao的接口
    @Resource(name="personRepotory")
    private PersonRepotory personRepotory;
    @Override
    public void updatePersonEmail(String s, int i) {

    }

    @Override
    public void savePersons(List<Person> persons) {
        personRepotory.save(persons);

    }
}

或许会感到奇怪,为何Dao只单纯的是一个接口,没

有实现类呢?其实这就是Spring Data JPA为我们封装了,只要按照Spring Data JPA的规范来定义,就会自动为我们生成一个默认的代理实现类。

3.Repository 接口

基础的 Repository提供了最基本的数据访问功能,其几个子接口则扩展了一些功能。它们的继承关系如下:
–Repository:仅仅是一个标识,表明任何继承它的均为仓库接口类
–CrudRepository:继承Repository,实现了一组CRUD相关的方法
–PagingAndSortingRepository:继承CrudRepository,实现了一组分页排序相关的方法
–JpaRepository:继承PagingAndSortingRepository,实现一组JPA规范相关的方法
–自定义的 XxxxRepository需要继承 JpaRepository,这样的XxxxRepository接口就具备了通用的数据访问控制层的能力。
–JpaSpecificationExecutor:不属于Repository体系,实现一组JPACriteria查询相关的方法

4.@Query 注解
这种查询可以声明在 Repository方法中,摆脱像命名查询那样的约束,将查询直接在相应的接口方法中声明,结构更为清晰,这是Springdata 的特有实现。
//查询id值最大的那个person
//使用@Query注解可以自定义JPQL语句,语句可以实现更灵活的查询
@Query(“SELECT p FROM Person p WHERE p.id=(SELECT max(p2.id) FROM Person p2)”)
Person getMaxIdPerson();

5.@Modifying 注解

@Query 与 @Modifying这两个annotation一起声明,可定义个性化更新操作,例如只涉及某些字段更新时最为常用,示例如下
//可以通过自定义的JPQL 完成update和delete操作,注意:JPQL不支持Insert操作
//在@Query注解中编写JPQL语句,但必须使用@Modify进行修饰,以通知SpringData,这是一个Update或者Delete
//Update或者delete操作,需要使用事务,此时需要定义Service层,在service层的方法上添加事务操作
//默认情况下,SpringData的每个方法上有事务,但都是一个只读事务,他们不能完成修改操作
@Modifying
@Query(“update Person p set p.email=:email where id=:id”)
void updatePersonEmail(@Param(“id”)Integer id,@Param(“email”)String email);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值