天天看点

java数据库连接——Spring Data JPA 1.Spring data 2.Spring data jpa3.例子4.例子详解

最近实习的公司用的JPA,这两天简单整理了下JPA的介绍与使用方法,如下。       

1.Spring data 

      Java访问数据库经历了几个阶段,第一个阶段是直接通过JDBC访问,这种方式工作量极大,而且会做大量的重复劳动,之后出现了一些现成的ORM框架,如hibernate、Mybatis等,这些框架封装了大量的数据库的访问操作,但是我们依然要对这些框架进行二次封装。

       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 - 高级文档

说了这么多,SpringData就是给我们提供了一种通用的代码格式,统一数据访问API。并且对于不同的数据库有很好的支持,不仅是关系型数据库,非关系型数据库也可以

2.Spring data jpa

Spring data jpa就是其中一个重要的子项目。Spring Data JPA等于在ORM之上又进行了一次封装,但具体的对数据库的访问依然要依赖于底层的ORM框架,Spring Data JPA默认是通过Hibernate实现的(当你导入jpa的依赖包时你会发现里面有个hibernate的jar文件):

java数据库连接——Spring Data JPA 1.Spring data 2.Spring data jpa3.例子4.例子详解

3.例子

首先,导入依赖(省略),然后在resource文件夹下配置application.properties文件

#开启包的自动扫描
entitymanager.packagesToScan= org.konghao.model
# 数据库连接
spring.datasource.url=jdbc:mysql://localhost:3306/springboot
# 用户名
spring.datasource.username=root
# 密码
spring.datasource.password=123
# 数据库驱动
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
# 自动更新表
spring.jpa.properties.hibernate.hbm2ddl.auto=update
# 使用MYSQL5作为数据库访问方言
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
#显示sql语句
spring.jpa.properties.hibernate.show_sql=true
           

创建Student的model对象

/*
* 以下两个代码其实就是Hiberate声明实体的annotation
* */
@Entity
@Table(name="t_stu")
public class Student {
 
    @Id()
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;
    private String name;
    private String address;
    private int age;
    ....
}
           

我们首先看一下Spring Data JPA中的几个接口

java数据库连接——Spring Data JPA 1.Spring data 2.Spring data jpa3.例子4.例子详解

最高层的

Repository<T,ID>

是一个空接口,我们定义的数据访问类只要实现这个接口,这个数据访问类就可以被spring data所管理,就此可以使用spring为我们提供操作方法(在原来的spring data中我们需要配置很多和Spring Data Repository相关的设置,但是现在有了spring boot,全部都已经自动配置好了)。这个接口要实现有两个泛型参数,第一个T表示实体类,第二个表示主键的类型,我们写一个数据库访问接口。

//@RepositoryDefinition(domainClass = Student.class, idClass = Integer.class)   //方法1
public interface StudentRepository extends Repository<Student,Integer> {        //方法2
 

    //注意,这里from后的不是数据表名,而是对于的实体类名
    @Query("select * from Student o where id=(select max(id) from Student t1)")
    public Student getStudentByMaxId();

    //这里的?是占位符,在执行是会替换成对应位置的参数,比如这里?1会被替换成name的值
    @Query("select * from Student o where o.name=?1 and o.age=?2")
    public List<Student> queryParams1(String name, Integer age);

    //这里的:+参数名则是绑定参数,在参数列中使用@Param注解绑定参数,则可在SQL语句中使用:+参数名得到相应参数的值
    @Query("select o from Student o where o.name=:name and o.age=:age")
    public List<Student> queryParams2(@Param("name")String name, @Param("age")Integer age);

    @Query("select s from Student s where s.id=?1")
    public Student loadById(int id);


    @Modifying
    @Query("update Student o set o.age = :age where o.id = :id")
    public void update(@Param("id")Integer id, @Param("age")Integer age);

    //注意,这里使用原生的SQL语句,from后的表名应该是数据库表名
    @Query(nativeQuery = true, value = "select count(1) from student")
    public long getCount();

 
    //根据地址和年龄进行查询
    public List<Student> findByAddressAndAge(String address, int age);
    //根据id获取对象,即可返回对象,也可以返回列表
    public Student readById(int id);
    //根据id获取列表,这里如果确定只有一个对象,也可以返回对象
    public List<Student> getById(int id);
    //根据id获取一个对象,同样也可以返回列表
    public Student findById(int id);
}
           

这个接口实现了Repository接口,我们定义了两类方法,这两类方法代表Repository使用的基本方式。第一类方法增加了一个Query或者Modifying的注解,通过这个声明,Spring Data JPA就知道该使用什么HQL去查询数据。第二个函数我们并没有定义任何的注解,但是它也可以查询得出来,在Spring Data JPA中提供了一种衍生查询,只要函数的声明有findBy,getBy,readBy,他就会去读取,findByAddressAnAge表示根据address和age进行查询,方法的第一个参数就是address,第二个参数就是age,readByXX,getByXX都是一样的道理,这些方法的返回值可以是一个列表,也可以是一个对象,spring Data JPA会自动根据返回类型来进行处理。我们不用写实现类,Spring Data JPA会自动帮助我们实现查询。很多时候在项目中会用到这些简单的查询,但是不得不写个方法来实现,但是现在使用了Spring Data JPA之后,这个操作被完全简化了。

接着看一下测试类的实现。

@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {
    //注入刚才定义的接口
    @Autowired
    private StudentRepository studentRepository;
 
    @Test
    public void testStudent() {
        Assert.assertEquals(2,studentRepository.findByAddressAndAge("zt",22).size());
        Assert.assertEquals("foo",studentRepository.readById(1).getName());
        Assert.assertEquals(1,studentRepository.getById(1).size());
        Assert.assertEquals("foo",studentRepository.findById(1).getName());
        
       
        Assert.assertEquals("foo",studentRepository.loadById(1).getName());
        
    }
}
           

4.例子详解

4.1 dao层接口的定义

第一种

public interface StudentRepository extends Repository<Student,Integer>{
    public Student findByName(String name);
}
           

第二种

@RepositoryDefinition(domainClass = Student.class, idClass = Integer.class)
public interface StudentRepository {
    public Student findByName(String name);
}
           

Repository接口中第一个类型是你要映射的实体类类型(Student.class),第二个类型是主键的类型(Integer.class),继承之后框架就能帮你实现映射功能。

2. 方法的编写

SpringData框架可以根据你的方法名,自动生成对应的SQL语句并执行

java数据库连接——Spring Data JPA 1.Spring data 2.Spring data jpa3.例子4.例子详解

我们可以根据自己的SQL语句,编写对应的方法,但又有一个问题,对于简单的查询还能接受,如果是一些很复杂的查询,那么方法名就会变得很长很长,读起来很辛苦怎么办?SpringData也考虑到这个问题,我们可以通过注解的方式,将自己写的SQL语句传进去,方法名就自由啦。

对于不同的数据库厂商,SpringData提供了不同的Repository接口。

以JDBC为例,我们可以看到有JpaRepository,它是继承了PagingAndSortingRepository接口,PagingAndSortingRepository接口继承了CrudRepository接口,CrudRepository接口又继承了Repository。

所以JpaRepository的功能相比Repository要丰富了许多,除了基本的CRUD操作之外,还支持分页和排序功能。