Spring Boot 学习总结之JPA【分页+自定义SQL+多表查询】

目录

Spring Data JPA简介

JPA(Java Persistence API)是 Sun 官方提出的 Java 持久化规范。它为 Java 开发人员提供了一种对象/关联映射工具来管理 Java 应用中的关系数据。它的出现主要是为了简化现有的持久化开发工作和整合 ORM 技术,结束现在 Hibernate、TopLink、JDO 等 ORM 框架各自为营的局面。值得注意的是,JPA 是在充分吸收了现有 Hibernate、TopLink、JDO 等 ORM 框架的基础上发展而来的,具有易于使用、伸缩性强等优点。

注意:JPA 是一套规范,不是一套产品,那么像 Hibernate、TopLink、JDO 它们是一套产品,如果说这些产品实现了这个 JPA 规范,那么就可以叫它们为 JPA 的实现产品。

与mybatis对比

  • jpa是对象与对象之间的映射,而mybatis是对象和结果集的映射。
  • jpa移植性比较好,不用关心用什么数据库,因为mybatis自由写sql语句,所以当项目移植的时候还需要改sql。
  • 修改字段时JPA更简单,mybatis需要修改一堆的xml,mapper等文件很麻烦。
  • mybatis自定义sql,比较灵活,也可以写复杂的sql,JPA只适合简单的单表sql

    总结:mybatis和JPA各有优势,如果sql简单,则jpa使用效率更高,如果sql较复杂,需要自定义,则使用mybatis更加顺手。

入手使用

(一)引入依赖

<dependency>
    <groupId>org.Springframework.boot</groupId>
    <artifactId>Spring-boot-starter-data-jpa</artifactId>
</dependency>
 <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

(二)添加配置文件:

spring:
  profiles:
    active: dev
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/soil
    username: lxtest
    password: admin

jpa:
    hibernate:
      ddl-auto: update
    show-sql: true

注意: 我是用的是yml的语法,注意空格的长度,show-sql是在jpa下面的,不是hibernate.show-sql>
重点关注下ddl-auto这个配置项:

create:每次加载 hibernate 时都会删除上一次的生成的表,然后根据 model 类再重新来生成新表,哪怕两次没有任何改变也要这样执行,这就是导致数据库表数据丢失的一个重要原因。
create-drop:每次加载 hibernate 时根据 model 类生成表,但是 sessionFactory 一关闭,表就自动删除。
update:最常用的属性,第一次加载 hibernate 时根据 model 类会自动建立起表的结构(前提是先建立好数据库),以后加载 hibernate 时根据 model 类自动更新表结构,即使表结构改变了,但表中的行仍然存在,不会删除以前的行。要注意的是当部署到服务器后,表结构是不会被马上建立起来的,是要等应用第一次运行起来后才会。
validate:每次加载 hibernate 时,验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,但是会插入新值。

  • show-sql:是否打印出自动生产的 SQL,方便调试的时候查看。

(四)实体类

@Entity
@Data
public class User {
    @Id
    @GeneratedValue
    private Integer id;

    private String name;
    private String pwd;
    private Integer age;

    public User(){}

}

(五)Repository:

public interface UserRepository extends JpaRepository<User,Integer>{

}

(六)使用:

 @GetMapping(value = "/users",  produces = { "application/json;charset=UTF-8" })
    public List<User> userList(){
       return  userRepository.findAll();
    }

自定义简单查询

Spring Data Jpa有个很赞的功能就是可以自动根据方法名去生成相应的简单sql,具体的方法名和sql如下:
例如:

User findByUserNameOrEmail(String username, String email);

Long countByUserName(String userName);

Long deleteById(Long id);

//获得符合查询条件的前10条数据  
List<Person> findFirst10ByName(String name);  
//获取符合查询条件的前30条数据  
List<Person> findTop30ByName(String name); 

具体的方法名和语句如下:

关键字 方法命名 sql where字句
And findByNameAndPwd where name= ? and pwd =?
Or findByNameOrSex where name= ? or sex=?
Is,Equals findById,findByIdEquals where id= ?
Between findByIdBetween where id between ? and ?
LessThan findByIdLessThan where id < ?
LessThanEquals findByIdLessThanEquals where id <= ?
GreaterThan findByIdGreaterThan where id > ?
GreaterThanEquals findByIdGreaterThanEquals where id > = ?
After findByIdAfter where id > ?
Before findByIdBefore where id < ?
IsNull findByNameIsNull where name is null
isNotNull,NotNull findByNameNotNull where id= ?
Like findByNameLike where name like ?
NotLike findByNameNotLike where name not like ?
StartingWith findByNameStartingWith where name like ‘?%’
EndingWith findByNameEndingWith where name like ‘%?’
Containing findByNameContaining where name like ‘%?%’
OrderBy findByIdOrderByXDesc where id=? order by x desc
Not findByNameNot where name <> ?
In findByIdIn(Collection c) where id in (?)
NotIn findByIdNotIn(Collection c) where id not in (?)
True findByAaaTue where aaa = true
False findByAaaFalse where aaa = false
IgnoreCase findByNameIgnoreCase where id= ?

复杂查询

(一)分页

@Query("select u from User u")
Page<User> findALL(Pageable pageable);
Page<User> findByNickName(String nickName, Pageable pageable);

Pageable 是 Spring 封装的分页实现类,使用的时候需要传入页数、每页条数和排序规则。

@Test
public void testPageQuery(){
    int page=1,size=10;
    Sort sort = new Sort(Direction.DESC, "id");
    Pageable pageable = new PageRequest(page, size, sort);
    userRepository.findALL(pageable);
    userRepository.findByNickName("testName", pageable);
}

(二)限制查询

User findFirstByOrderByLastnameAsc();
User findTopByOrderByAgeDesc();
Page<User> queryFirst10ByLastname(String lastname, Pageable pageable);
List<User> findFirst10ByLastname(String lastname, Sort sort);
List<User> findTop10ByLastname(String lastname, Pageable pageable);

(三)自定义SQL

在 SQL 的查询方法上面使用 @Query 注解,如涉及到删除和修改需要加上 @Modifying,也可以根据需要添加 @Transactional 对事物的支持,查询超时的设置等。

@Transactional(timeout = 15)
@Modifying
@Query("update User set name= ?1 where id = ?2")
int modifyById(String  name, Long id);

@Transactional
@Modifying
@Query("delete from User where id = ?1")
void deleteById(Long id);

@Query("select u from User u where u.pwd= ?1")
User findByPwd(String pwd);

(四)多表查询

再新建一个用户详情的实体类:

@Data
@Entity
public class UserInfo {
    @Id
    @GeneratedValue
    private Integer id;
    private Integer userId;
    private String address;
    private String tel;


}

再新建一个接口,用于接受连表查询结果。

/**
 * @author : Aslan
 * @version : v1.0
 * @time : 2018-06-26 14:11
 * @desc : 定义一个结果集的接口类,接口类的内容来自于用户表和用户详情表,用于接收连表查询后的结果
 */
public interface UserDetail {


    String getTel();
    String getAddress();
    String getName();
}

新建一个Repository,也就是类似于DAO。

public interface UserInfoRepository extends JpaRepository<UserInfo,Integer> {
    /**
     * 特别注意这里的 SQL 是 HQL,需要写类的名和属性,不是数据库里面的字段名,若写错则会报错:
     *
     * 传入电话,查找用户信息
     * @param tel
     * @return
     */
    @Query("select u.name,d.address,d.tel  from User u , UserInfo d " +
            "where u.id = d.userId  and  d.tel = ?1 ")
    List<UserDetail> findUserInfo(String tel);
}

使用:

  @GetMapping(value = "/testUserInfo")
    public void testUserInfo(){
        List<UserDetail> userDetails = userInfoRepository.findUserInfo("111");
        for(UserDetail detail:  userDetails){
            System.out.println("name = "+detail.getName());
        }
    }

猜你喜欢

转载自blog.csdn.net/qq_29534483/article/details/80812974