Spring Boot学习笔记(六)Spring Data JPA:分类查询、自定义查询、联表(多表查询)

Spring Data JPA:分类查询、自定义查询、联表(多表查询)

上一篇:Spring Boot 参数校验、自定义Filter、自定义Property

  • JPA

    JPA(Java Persistence API)是 Sun 官⽅提出的 Java 持久化规范。它为 Java 开发⼈员提供了⼀种对象/关联映射工具来管理 Java 应用中的关系数据。
    JPA 是⼀套规范,不是⼀套产品,那么像 Hibernate、TopLink、JDO 它们是⼀套产品,如果说这些产品实现了这个 JPA 规范,那么就可以叫它们为 JPA 的实现产品。

  • Spring Data JPA

    Spring Data JPA是 Spring 基于 ORM 框架、JPA 规范的基础上封装的⼀套 JPA 应⽤框架,可使开发者用极简的代码即可实现对数据的访问和操作

  • 结构目录

    Spring Boot学习笔记(六)Spring Data JPA:分类查询、自定义查询、联表(多表查询)_第1张图片

  • pom.xml添加依赖
    
    	mysql
    	mysql-connector-java
    
    
    	org.springframework.boot
    	spring-boot-starter-data-jpa
    
    
  • application.properties

    数据库连接以及设置的相关语句,依情况语句可能会稍微有些差别

    # 数据库连接
    Spring.datasource.url=jdbc:mysql://localhost:3306/springdemo?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone = GMT
    Spring.datasource.username=root
    Spring.datasource.password=
    Spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    # 数据库设置
    Spring.jpa.properties.hibernate.hbm2ddl.auto=update
    Spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
    Spring.jpa.show-sql=true
    
    hibernate.hbm2ddl.auto 参数的作用主要用于:自动创建 | 更新 | 验证数据库表结构:

    create:每次加载 hibernate 时都会删除上⼀次的生成的表,然后根据 model 类重新生成新表
    create-drop:每次加载 hibernate 时根据 model 类生成表,但是 sessionFactory ⼀关闭,表就自动删除。
    update:最常用的属性,初次加载 hibernate 时根据 model 类会自动建立表结构(前提是先建立
    数据库),之后加载 hibernate 时根据 model 类⾃动更新表结构,即使表结构改变,表中的行仍
    然存在,不会删除以前的行。当部署到服务器后,第一次运行之后表结构才会被马上建立
    validate:每次加载 hibernate 时,验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,但是会插入新值。

    Spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect

    主要是指定⽣成表名的存储引擎为 InneoDB

    Spring.jpa.show-sql=true

    是否打印出自动⽣产的 SQL,⽅便调试的时候查看

  • 添加实体类:domain–User
    package wen.jpademo.domain;
    
    
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    import java.io.Serializable;
    
    @Entity
    public class User implements Serializable {
    
        @Id
        @GeneratedValue
        private int id;
    
        @Column(nullable = false, unique = true)
        private String username;
    
        @Column(nullable = false)
        private String password;
    
        @Column(nullable = false, unique = true)
        private String email;
    
        @Column(nullable = false, unique = true)
        private String nickname;
    
        @Column(nullable = false)
        private String regTime;
    
        public User() {
    
        }
    
        public User(String username, String password, String email, String nickname, String regTime) {
            this.id = id;
            this.username = username;
            this.password = password;
            this.email = email;
            this.nickname = nickname;
            this.regTime = regTime;
        }
        //get,set方法省略
    
    

    还可以用@Getter、@Setter注解的形式,点击参考

    package wen.jpademo.domain;
    
    
    import lombok.Getter;
    import lombok.Setter;
    
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    import java.io.Serializable;
    
    @Entity
    public class User implements Serializable {
    
        @Id
        @GeneratedValue
        @Getter
        @Setter
        private int id;
    
        @Getter
        @Setter
        @Column(nullable = false, unique = true)
        private String username;
    
        @Getter
        @Setter
        @Column(nullable = false)
        private String password;
    
        @Getter
        @Setter
        @Column(nullable = false, unique = true)
        private String email;
    
        @Getter
        @Setter
        @Column(nullable = false, unique = true)
        private String nickname;
    
        @Getter
        @Setter
        @Column(nullable = false)
        private String regTime;
    
        public User() {
    
        }
    
        public User(String username, String password, String email, String nickname, String regTime) {
            this.id = id;
            this.username = username;
            this.password = password;
            this.email = email;
            this.nickname = nickname;
            this.regTime = regTime;
        }
    }
    
    
  • dao层 UserRepository.java :继承JpaRepository类,并且可以根据方法名来自动产生SQL,如 findByUserName 会自动生产⼀个以 userName 为参数的查询方法,如findAll 自动会查询表里面的所有数据,如自动分页等等
    package wen.jpademo.repository;
    
    import org.springframework.data.domain.Page;
    import org.springframework.data.domain.Pageable;
    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.data.jpa.repository.Modifying;
    import org.springframework.data.jpa.repository.Query;
    import org.springframework.transaction.annotation.Transactional;
    import wen.jpademo.domain.User;
    
    public interface UserRepository extends JpaRepository {
    	 User findByUsername(String username);
    	
    	 User findByUsernameOrEmail(String username, String email);
    	
    	 //分页查询
    	 @Query("select u from User u")
    	 Page findALL(Pageable pageable);
    	
    	 Page findByNickname(String nickname, Pageable pageable);
    	
    	 //自定义查询
    	 @Transactional(timeout = 10)
    	 @Modifying
    	 @Query("update User set username = ?1 where id = ?2")
    	 int modifyById(String username, int id);
    	
    	 @Transactional
    	 @Modifying
    	 @Query("delete from User where id = ?1")
    	 void deleteById(int id);
    	
    	 @Query("select u from User u where u.email = ?1")
    	 User findByEmail(String email);
    }
    
    
  • 测试文件 JpademoApplicationTests:
    package wen.jpademo;
    
    import org.junit.Assert;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.data.domain.PageRequest;
    import org.springframework.data.domain.Pageable;
    import org.springframework.data.domain.Sort;
    import org.springframework.test.context.junit4.SpringRunner;
    import wen.jpademo.domain.User;
    import wen.jpademo.domain.UserDetail;
    import wen.jpademo.repository.UserInfo;
    import wen.jpademo.repository.UserDetailRepository;
    import wen.jpademo.repository.UserRepository;
    
    import javax.annotation.Resource;
    import java.text.DateFormat;
    import java.util.Date;
    import java.util.List;
    
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class JpademoApplicationTests {
    
       @Test
       public void contextLoads() {
       }
    
       @Resource
       private UserRepository userRepository;
    
       @Resource
       private UserDetailRepository userDetailRepository;
    
       //自带CRUD测试
       @Test
       public void test() {
           Date date = new Date();
           DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG);
           String formattedDate = dateFormat.format(date);
           userRepository.save(new User("aa", "[email protected]", "aa", "aa123456", formattedDate));
           userRepository.save(new User("bb", "[email protected]", "bb", "bb123456", formattedDate));
           userRepository.save(new User("cc", "[email protected]", "cc", "cc123456", formattedDate));
           Assert.assertEquals(3, userRepository.findAll().size());
           Assert.assertEquals("bb123456", userRepository.findByUsernameOrEmail("bb", "[email protected]").getNickname());
           userRepository.delete(userRepository.findByUsername("aa"));
       }
    
       @Test
       public void testUserDetail() {
           userDetailRepository.save(new UserDetail(35, "杏花村", "打球"));
       }
    
       //分页查询
       @Test
       public void testPageQuery() {
           int page = 1;
           int size = 2;
           Sort sort = new Sort(Sort.Direction.DESC, "id");
           Pageable pageable = new PageRequest(page, size, sort);
           userRepository.findALL(pageable);
           userRepository.findByNickname("bb123456", pageable);
       }
    
       //自定义查询
       @Test
       public void testCustomQuery() {
           userRepository.modifyById("bibi", 35);
           userRepository.deleteById(37);
           userRepository.findByEmail("cc");
       }
    }
    
    
  • 多表查询:多表查询在 Spring Data JPA 中有两种实现方式,第⼀种是利用 hibernate 的级联查询来实现,第⼆种是创建⼀个结果集的接口来接收连表查询后的结果

    第二种方式,创建用户详情类UserDetail.java:

    package wen.jpademo.domain;
    
    import lombok.Getter;
    import lombok.Setter;
    
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    import java.io.Serializable;
    
    @Entity
    public class UserDetail implements Serializable {
    
        @Id
        @GeneratedValue
        @Getter
        @Setter
        private int id;
    
        @Column(nullable = false, unique = true)
        @Getter
        @Setter
        private int userId;
    
        @Column(nullable = true)
        @Getter
        @Setter
        private String address;
    
        @Column(nullable = true)
        @Getter
        @Setter
        private String hobby;
    
        public UserDetail() {
    
        }
    
        public UserDetail(int userId, String address, String hobby) {
            this.userId = userId;
            this.address = address;
            this.hobby = hobby;
        }
    }
    
    
  • 定义结果集的接口类,接口类的内容来自用户表(User.java)和用户详情表(UserDetail.java)
    package wen.jpademo.repository;
    
    public interface UserInfo {	
        String getUsername();	
        String getEmail();	
        String getAddress();	
        String getHobby();
    }	
    
  • 建立dao层 UserDetailRepository:
    package wen.jpademo.repository;
    
    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.data.jpa.repository.Query;
    import wen.jpademo.domain.UserDetail;
    
    import java.util.List;
    
    public interface UserDetailRepository extends JpaRepository {
    
        @Query("select u.username as username, u.email as email, d.address as address, d.hobby as hobby from User u, UserDetail d " +
                "where u.id = d.userId and d.hobby =?1")
        List findUserInfo(String hobby);
    }
    
    

    这里用用的查询语句使HQL,必须声明类的名和属性

  • 测试文件, 在上面的JpademoApplicationTests.java 文件下添加以下代码:
    //多表查询
    @Test
    public void testUserInfo() {
        List userInfos = userDetailRepository.findUserInfo("打球");
        for (UserInfo userInfo : userInfos) {
            System.out.println("address: " + userInfo.getAddress());
        }
    }
    

    测试结果:
    Spring Boot学习笔记(六)Spring Data JPA:分类查询、自定义查询、联表(多表查询)_第2张图片
    数据库:
    Spring Boot学习笔记(六)Spring Data JPA:分类查询、自定义查询、联表(多表查询)_第3张图片
    下一章:SpringBoot:JPA + Druid 多数据源

你可能感兴趣的:(Spring,Boot学习笔记,Java,后端)