美文网首页WEB
Spring Data学习 04:Spring Data JPA

Spring Data学习 04:Spring Data JPA

作者: 我问你瓜保熟吗 | 来源:发表于2019-05-01 11:17 被阅读8次

    Spring Data 学习 01 :JDBC 访问 MySQL

    Spring Data 学习 02 :Spring JdbcTemplate 访问 MySQL

    Spring Data 学习 03 :JPA

    Spring Data 学习 04:Spring Data JPA


    一、什么是Spring Data JPA:

    • 是更大的Spring Data家族的一部分
    • 对基于JPA的数据访问层的增强支持
    • 更易于构建基于使用Spring数据访问技术栈的应用程序

    二、Jpa、Hibernate、Spring Data Jpa三者之间的关系

    JPA是ORM规范,它仅仅定义了一些接口。Hibernate、TopLink是实现了JPA规范的ORM框架,具体实现了JPA定义的接口。Spring Data JpaJPA 是对JPA规范的再次封装抽象(Repository层的实现)。Spring Data JPA的核心目标之一是减少代码并简化数据访问层

    三、Repository

    • Repository是Spring Data的核心接口,不提供任何方法,包含JpaRepository ,PagingAndSortingRepository等子接口。
    定义:
    public interface Repository<T, ID extends Serializable>{
    
    }
    
    使用:User是实体类,int代表User的id的类型
         添加注解和继承Repository效果一样
    // @RepositoryDefinition(domainClass = User.class, idClass = int.class)
    public interface UserRepository extends Repository<User, int>{
            public User findByName(String name);
    }
    

    Repository同Serializable一样是一个空接口,没有包含方法声明的接口被称之为标记接口

    • CrudRepository: 继承Repository ,提供基本的增删改查
    public interface CrudRepository<T,ID extends Serializable>
        extends Repository<T,ID> {
        <S extends T> S save(S entity);
        T findOne(ID primaryKey);
        Iterable<T> findAll();
        Long count();
        void delete(T entity);
        boolean exists(ID primaryKey);
    }
    
    • PagingAndSortingRepository ,继承 CrudRepository ,实现 分页、排序:
    public interface PagingAndSortingRepository<T,ID extends Serializable>
        extends CrudRepository<T,ID> {
        Iterable<T> findAll(Sort sort);
        Page<T> findAll(Pageable pageable);
    }
    
    • JpaRepository :继承PagingAndSortingRepository ,具有CrudRepository和PagingAndSortingRepository的所有函数,实现JPA的相关规范,例如刷新持久化上下文和批量删除记录

    四、根据方法名创建自定义查询

    • 实例
    public interface PersonRepository extends JpaRepository<User,Long>{
        List<Person> findByEmailAddressAndLastname(EmailAddress emailAddress, String lastname);
        
        // 启用 distinct 标志(去重:放在前面后面都可以)
        List<Person> findDistinctPeopleByLastnameOrFirstname(String lastname, String firstname);
        List<Person> findPeopleDistinctByLastnameOrFirstname(String lastname, String firstname);
    
        // 给独立的属性启用 ignore case(忽略大小写)
        List<Person> findByLastnameIgnoreCase(String lastname);
        // 给所有合适的属性启用 ignore case
        List<Person> findByLastnameAndFirstnameAllIgnoreCase(String lastname, String firstname);
    
        // 启用 ORDER BY(排序)
        List<Person> findByLastnameOrderByFirsnameAsc(String lastname);
        List<Person> findByLastnameOrderByFirsnameDesc(String lastname);
    }
    
    • Spring Data JPA 自定义查询接口约定命名规则:
    Spring Data JPA接口约定命名规则

    五、实体类注解

    数据库实体类是一个 POJO Bean 对象。

    1、常用注解解释:

     * @Entity 用来标示这个类是实体类
     * @Table  实体类与数据表的映射,通过name确定在表名(默认类名为表名)比如类Users 和表 users;
     * @Id         主键注解,表示该字段为主键
     * @GeneratedValue 定义主键规则,默认AUTO
     * @Column 类属性与表字段映射注解,其中可以设置在字段名,长度等信息
     * @ManyToOne  多对一,可以设置数据加载方式等 默认加载方式是EAGER 就是使用left join
     * @OneToMany  一对多 默认加载方式是 LAZY 懒加载
     * @JoinColumn 与*对*配合使用,用来设置外键名等信息
     * @Basic  实体类中会默认为每一个属性加上这个注解,表示与数据表存在关联,
     *              没有使用Column注解的类属性会以属性名作为字段名,驼峰命名需要转为_
     * @Temporal 对于Date属性的格式化注解,有 TIME,DATE,TIMESTAMP 几个选择
     * @Transient 标注该属性不做与表的映射(原因:可能表中没有该属性对应的字段)有该注解,在执行sql语句时,就不会出现该属性,否则会有,若表中没有该字段则会报错。若存在不想与数据表映射的属性,则需要加上该注解,
    
    

    2、主键上的注解

        // 1、id生成策略自动增长 
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private String id;
    
        // 2、配置uuid,本来jpa是不支持uuid的,但借用hibernate的方法
        @Id
        @GeneratedValue(generator = "uuid")     可以实现。
        @GenericGenerator(name = "uuid", strategy = "uuid")
        private String id;
    
    • UUID可以自动生成一个36字符组成的字符串,UUID是由10个阿拉伯数字加上26个字母组成,8-4-4-4-12的形式组成,例如:4c47cf4a-a55a-4fce-8cd9-024a790714b010。
    • 产生UUID的方法:String uuid=UUID.randomUUID().toString();

    六、依赖与配置

    • gradle:build.gradle
    // 添加 Spring Data JPA依赖
        implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    // 添加 MySQL连接驱动依赖
        runtimeOnly 'mysql:mysql-connector-java'
    
    • maven:pom.xml
           <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <scope>runtime</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-jpa</artifactId>
            </dependency>
    
    • 配置:application.properties
    #通用数据源配置
    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    spring.datasource.url=jdbc:mysql://127.0.0.1:3306/student?charset=utf8mb4&useSSL=false
    spring.datasource.username=root
    spring.datasource.password=root
    # Hikari 数据源专用配置
    spring.datasource.hikari.maximum-pool-size=20
    spring.datasource.hikari.minimum-idle=5
    # JPA 相关配置
    spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect  // 在 SrpingBoot 2.0 版本中,Hibernate 创建数据表的时候,默认的数据库存储引擎选择的是 MyISAM ?这个参数是在建表的时候,将默认的存储引擎切换为 InnoDB.
    spring.jpa.show-sql = true    // 控制台显示sql
    spring.jpa.hibernate.ddl-auto=create    // 只能开发中使用:删除数据,重新创建表结构。
    

    七、实战操作

    1、建数据库student和表student

    CREATE TABLE `student` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `name` varchar(255) DEFAULT NULL,
      `age` int(11) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
    

    2、建立数据库实体类

    package com.example.demo.Entity;
    
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    
    @Entity 
    public class Student {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
        private String name;
        private int age;
    
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    }
    
    

    3、创建数据库持久层

    package com.example.demo.Repository;
    
    import com.example.demo.Entity.Student;
    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.data.jpa.repository.Modifying;
    import org.springframework.data.jpa.repository.Query;
    import org.springframework.data.repository.query.Param;
    
    import java.util.List;
    
    
    public interface StudentRepository extends JpaRepository<Student, Long> {
    
        // 利用注解自定义查询预警
        @Query("select o from Student o where id = (select max(id) from Student o)") // Student 是对象
        public Student getStudentByMaxId();
    
        // 根据索引参数进行查询
        @Query("select o from  Student o where o.name=?1 and o.age=?2")
        public List<Student>queryParams(String name, int age);
    
        // 根据别名参数进行查询
        @Query("select o from  Student o where o.name=:name and o.age=:age")
        public List<Student>queryParams2(@Param("name")String name,@Param("age") int age);
    
        // 原生SQL语句查询
        @Query(nativeQuery = true,value = "select count(1) from student")  // student是表名
        public long getCount();
    
        // @query注解 修改、新增、删除等,要添加@Modifying注解,要在Service里面处理,并增加事务注解 @Transactional
        @Modifying
        @Query("update Student o set o.age = :age where o.id = :id")
        public void update(@Param("id") Long id, @Param("age") int age);
    }
    

    4、创建Service

    增删改操作需要事务支持,事务要放在Service层,一个service可能要调用多个dao调用,要保证多个调用在一个事务里。

    package com.example.demo.Service;
    
    import com.example.demo.Repository.StudentRepository;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import javax.transaction.Transactional;
    
    
    @Service
    public class StudentService {
    
        @Autowired
        private StudentRepository studentRepository;
    
        @Transactional
        public void update(Long id, int age){
           studentRepository.update(id,age);
        }
    }
    

    5、对持久层 增删改查等操作 进行单元测试

    package com.example.demo;
    
    import com.example.demo.Entity.Student;
    import com.example.demo.Repository.StudentRepository;
    import com.example.demo.Service.StudentService;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.data.domain.Page;
    import org.springframework.data.domain.PageRequest;
    import org.springframework.data.domain.Sort;
    import org.springframework.test.context.junit4.SpringRunner;
    
    import java.util.ArrayList;
    import java.util.List;
    
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class DemoApplicationTests {
    
        @Autowired
        private StudentRepository studentRepository;
    
        @Autowired
        private StudentService studentService;
    
        // 自建操作测试
        @Test
        public void getByMaxId(){
            Student student = studentRepository.getStudentByMaxId();
            System.out.println("id:"+student.getId()+"name:"+student.getName()+"age:"+student.getAge());
        }
        @Test
        public void queryParams(){
            List<Student> students = studentRepository.queryParams("护士", 24);
            for (Student student:students){
                System.out.println("id:"+student.getId()+"name:"+student.getName()+"age:"+student.getAge());
            }
        }
        @Test
        public void queryParams2(){
            List<Student> students = studentRepository.queryParams("护士", 24);
            for (Student student:students){
                System.out.println("id:"+student.getId()+"name:"+student.getName()+"age:"+student.getAge());
            }
        }
        @Test
        public void getCount(){
            long count = studentRepository.getCount();
            System.out.println(count);
        }
        @Test
        public void update(){
            studentService.update(1L,19);
        }
    
        // 自带增加、删除、查询、分页、排序 测试
        @Test
        public void add() {
            // 增加一个
            Student student = new Student();
            student.setName("老师");
            student.setAge(23);
            studentRepository.save(student);
        }
        @Test
        public void delete() {
            // 增加一个
            Student student = new Student();
            student.setName("老师");
            student.setAge(23);
            studentRepository.deleteById(1L);
        }
        @Test
        public void findall(){
            // 查询所有
            ArrayList<Student> all = new ArrayList<>();
            for (Student student:studentRepository.findAll()){
                System.out.println("id:"+student.getId()+"name:"+student.getName()+"age:"+student.getAge());
            }
        }
        // 分页和排序
        @Test
        public void testPage(){
    
            Sort sort= new Sort(Sort.Direction.DESC, "id");
    
            PageRequest Request = PageRequest.of(0,5, sort);
            Page<Student> allPage = studentRepository.findAll(Request);
    
            System.out.println("查询总页数"+allPage.getTotalPages());
            System.out.println("查询总记录数"+allPage.getTotalElements());
            System.out.println("查询当前是第几页"+(allPage.getNumber()+1));
            System.out.println("查询当前页面的内容集合"+allPage.getContent());
            System.out.println("查询当前页面的记录数"+allPage.getNumberOfElements());
    
    
        }
    
    }
    

    相关文章

      网友评论

        本文标题:Spring Data学习 04:Spring Data JPA

        本文链接:https://www.haomeiwen.com/subject/wxminqtx.html