Spring-Data-JPA尝鲜:快速搭建CRUD+分页后台实例

https://mp.weixin.qq.com/s/D12izOGIjhY8I1ebgQyLMQ

Spring-Data-JPA尝鲜:快速搭建CRUD+分页后台实例


image.png

前言:因为以前没有接触过Hibernate框架,可是最近看一些博客深深被它的“效率”所吸引,因此这就来跟你们一块儿就着一个简单的例子来尝尝Spring全家桶里自带的JPA的鲜java

Spring-DATA-JPA 简介

JPA(Java Persistence API)是Sun官方提出的Java持久化规范。它为Java开发人员提供了一种对象/关联映射工具来管理Java应用中的关系数据。他的出现主要是为了简化现有的持久化开发工做和整合ORM技术,结束如今Hibernate,TopLink,JDO等ORM框架各自为营的局面。值得注意的是,JPA是在充分吸取了现有Hibernate,TopLink,JDO等ORM框架的基础上发展而来的,具备易于使用,伸缩性强等优势。从目前的开发社区的反应上看,JPA受到了极大的支持和赞赏,其中就包括了Spring与EJB3.0的开发团队。mysql

注意:JPA是一套规范,不是一套产品,那么像Hibernate,TopLink,JDO他们是一套产品,若是说这些产品实现了这个JPA规范,那么咱们就能够叫他们为JPA的实现产品。git

Spring Data JPA 是 Spring 基于 ORM 框架、JPA 规范的基础上封装的一套JPA应用框架,可以使开发者用极简的代码便可实现对数据的访问和操做。它提供了包括增删改查等在内的经常使用功能,且易于扩展!学习并使用 Spring Data JPA 能够极大提升开发效率!(spring data jpa让咱们解脱了DAO层的操做,基本上全部CRUD均可以依赖于它来实现github

摘自:springboot(五):spring data jpa的使用——纯洁的微笑web

Hibernate 和 MyBatis 简单对比

因为JPA底层干活的仍然是Hibernate框架,而咱们以前学习的只有MyBatis相关的东西,因此在尝鲜以前仍是有必要简单了解一下二者的区别:spring

Hibernate的优点:sql

  • Hibernate的DAO层开发比MyBatis简单,Mybatis须要维护SQL和结果映射。数据库

  • Hibernate对对象的维护和缓存要比MyBatis好,对增删改查的对象的维护要方便。缓存

  • Hibernate数据库移植性很好,MyBatis的数据库移植性很差,不一样的数据库须要写不一样SQL。springboot

  • Hibernate有更好的二级缓存机制,可使用第三方缓存。MyBatis自己提供的缓存机制不佳。

MyBatis的优点:

  • MyBatis能够进行更为细致的SQL优化,能够减小查询字段。

  • MyBatis容易掌握,而Hibernate门槛较高。

简单总结:

  • MyBatis:小巧、方便、高效、简单、直接、半自动化

  • Hibernate:强大、方便、高效、复杂、间接、全自动化

引用自:【持久化框架】Mybatis与Hibernate的详细对比——高亮

CRUD + 分页后台实例

下面咱们来快速搭建一个使用Spring-DATA-JPA的CRUD+分页后台实例,而且咱们会直接使用到RESTful API(不熟悉的同窗[戳这里]())

第一步:新建SpringBoot项目

打开IDEA新建一个SpringBoot项目,不熟悉SpringBoot的同窗请右转:【传送门】,而后在pom.xml中添加如下依赖:

<!-- mysql-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.21</version>
</dependency>

<!-- jpa-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

而后把application.properties弄成这个样子:

#数据库
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/testdb?useUnicode=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.properties.hibernate.hbm2ddl.auto=update
#显示SQL语句
spring.jpa.show-sql=true
#不加下面这句则默认建立MyISAM引擎的数据库
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
#本身重写的配置类,默认使用utf8编码
spring.jpa.properties.hibernate.dialect=com.wmyskxz.demo.config.MySQLConfig

spring.jpa.properties.hibernate.hbm2ddl.auto是hibernate的配置属性,其主要做用是:自动建立、更新、验证数据库表结构。该参数的几种配置以下:

  • create:每次加载hibernate时都会删除上一次的生成的表,而后根据你的model类再从新来生成新表,哪怕两次没有任何改变也要这样执行,这就是致使数据库表数据丢失的一个重要缘由。

  • create-drop:每次加载hibernate时根据model类生成表,可是sessionFactory一关闭,表就自动删除。

  • update:最经常使用的属性,第一次加载hibernate时根据model类会自动创建起表的结构(前提是先创建好数据库),之后加载hibernate时根据model类自动更新表结构,即便表结构改变了但表中的行仍然存在不会删除之前的行。要注意的是当部署到服务器后,表结构是不会被立刻创建起来的,是要等应用第一次运行起来后才会。

  • validate:每次加载hibernate时,验证建立数据库表结构,只会和数据库中的表进行比较,不会建立新表,可是会插入新值。

而后新建一个【config】包,建立一个【MySQLConfig】类(上面的spring.jpa.properties.hibernate.dialect属性就要配置这里的类全路径):

package com.wmyskxz.demo.config;

import org.hibernate.dialect.MySQL5InnoDBDialect;

public class MySQLConfig extends MySQL5InnoDBDialect {
    @Override
    public String getTableTypeString() {
        return "ENGINE=InnoDB DEFAULT CHARSET=utf8";
    }
}

第二步:建立好须要的数据库

打开SQL服务,建表语句也很简单啦:

create database testdb;

第三步:建立实体类

实体类映射的其实是数据库表的结构,在适当的包目录下(例如【entity】)下建立好实体类:

package com.wmyskxz.demo.entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity // 代表这是个实体类
public class User {

    @Id // 代表这个属性是主键
    @GeneratedValue // 自增加
    private long id;
    @Column(nullable = false, unique = true)    // 不容许为空,属性惟一
    private String username;
    @Column(nullable = false)   // 不容许为空
    private String password;

    // getter and setter
}

第四步:DAO层

新建一个【repository】包,而后新建一个【UserRepository】接口,并继承JpaRepository类:

package com.wmyskxz.demo.repository;

import com.wmyskxz.demo.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<UserLong{
}

继承JpaRepository须要传入两个参数,一个是实体类User一个是主键的类型Long,而凡是继承了JpaRepository类的就会自动实现不少内置的方法,包括增删改查,以及使用默认支持的Pageable对象来进行分页,默认的方法大体以下:

public interface JpaRepository<TIDextends PagingAndSortingRepository<TID>, QueryByExampleExecutor<T{
    List<T> findAll();
    List<T> findAll(Sort var1);
    List<T> findAllById(Iterable<ID> var1);
    <S extends T> List<S> saveAll(Iterable<S> var1);
    void flush();
    <S extends T> saveAndFlush(S var1);
    void deleteInBatch(Iterable<T> var1);
    void deleteAllInBatch();
    getOne(ID var1);
    <S extends T> List<S> findAll(Example<S> var1);
    <S extends T> List<S> findAll(Example<S> var1, Sort var2);
}

第五步:Controller层

新建【controller】包,新建一个【UserController】类,编写简单的增删改查代码:

package com.wmyskxz.demo.controoler;

import com.wmyskxz.demo.entity.User;
import com.wmyskxz.demo.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.web.bind.annotation.*;

import java.util.Optional;

@RestController // 代表这是一个Controller并返回JSON格式
public class UserController {
    @Autowired
    private UserRepository userRepository;

    @GetMapping("/getOne")
    public Optional<User> getOneUserById(@RequestParam long id) {
        return userRepository.findById(id);
    }

    @GetMapping("/all")
    public Iterable<User> getAllUsers(@RequestParam(value = "page", defaultValue = "0") int page,
                                      @RequestParam(value = "size", defaultValue = "5") int size) 
{
        page = page < 0 ? 0 : page;// 若是page为负数则修改成0,防止在首页点击上一页发生错误
        Sort sort = new Sort(Sort.Direction.DESC, "id");// 按id倒叙排列
        return userRepository.findAll(new PageRequest(page, size, sort));
    }

    @PostMapping("/add")
    public String addUser(@RequestParam String username,
                          @RequestParam String password)
 
{
        User user = new User();
        user.setUsername(username);
        user.setPassword(password);
        userRepository.save(user);// 注意这里是save
        return "Saved";
    }

    @DeleteMapping("/delete")
    public String deleteUserById(@RequestParam long id) {
        userRepository.deleteById(id);
        return "Deleted";
    }

    @PutMapping("/update")
    public String updateUser(User user) {
//        User user = new User();
//        user.setId(id);
//        user.setUsername(username);
//        user.setPassword(password);
        userRepository.save(user);
        return "Updated";
    }
}

上面就直接使用@Autowired自动引入了继承了JpaRepository的UserRepository接口,咱们使用它默认的方法已经足够完成咱们的基础功能了,值得一提的是咱们的getAllUsers(...)方法,它往findAll()方法里传入了一个Pageable对象,这是Spring Data库中定义的一个接口,是全部分页相关信息的一个抽象,经过该接口,咱们能够获得和分页相关的全部信息(例如pageNumberpageSize等),这样Jpa就可以经过Pageable参数来获得一个带分页信息的Sql语句。

固然上面咱们是经过本身建立了一个Pageable对象,Spring也支持直接获取Pageable对象,能够把上面的getAllUsers(...)方法改写成下面这样:

@GetMapping("/all")
public Iterable<User> getAllUsers(@PageableDefault(value = 5, sort = {"id"}, direction = Sort.Direction.DESC) 
                                              Pageable pageable) 
{
    return userRepository.findAll(pageable);
}

默认从第0页开始,也能够本身传入一个page参数,跟上面的是同样的。

第六步:运行项目

上面咱们就快速搭建起来了一个基于Spring Boot和JPA的REST风格的后台增删改查实例,咱们把项目跑起来,能够看到数据库自动建立了一些表:

image.png

JPA帮咱们建立的user表的建立SQL以下:

CREATE TABLE `user` (
  `id` bigint(20NOT NULL,
  `password` varchar(255NOT NULL,
  `username` varchar(255NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `UK_sb8bbouer5wak8vyiiy4pf2bx` (`username`)
ENGINE=InnoDB DEFAULT CHARSET=utf8;

使用REST测试工具测试

彻底符合咱们的要求,而后咱们使用一些REST的测试工具,来测试上面的功能是否都能正确运行,好比我这里使用的【Restlet Client】,在Chrome商店就能够下载到。

`/all`地址测试:

首先先来测试一下http://localhost:8080/all地址,因为如今数据库仍是空的,因此能够看到返回以下:

{
    "content": [
    ],
    "pageable": {
        "sort": {
            "sorted"true,
            "unsorted"false,
            "empty"false
        },
        "offset"0,
        "pageNumber"0,
        "pageSize"5,
        "unpaged"false,
        "paged"true
    },
    "totalElements"0,
    "last"true,
    "totalPages"0,
    "number"0,
    "size"5,
    "sort": {
        "sorted"true,
        "unsorted"false,
        "empty"false
    },
    "numberOfElements"0,
    "first"true,
    "empty"true
}

添加用户测试:

而后咱们使用

http://localhost:8080/add?username=wmyskxz&password=123地址,添加几个相似的用户信息: image.png

能够看到返回正确的Saved信息:

image.png

`/getOne`地址测试:

咱们就直接使用http://localhost:8080/getOne?id=1来获取刚才添加的用户,能够看到返回正确的数据:

{
    "id"1,
    "username""wmyskxz",
    "password""123"
}

修改用户测试:

而后咱们使用http://localhost:8080/update?id=1&username=wmyskxz&password=123456来模拟进行用户密码的修改:

image.png

能够看到正确的更新信息Updated,再次查询用户,也能看到正确的数据:

{
    "id"1,
    "username""wmyskxz",
    "password""123456"
}

分页测试:

咱们使用添加功能为数据库添加5条以上的数据,而后进行一次查询/all,能够看到可以按照id倒叙排列后返回5条数据:

image.png

数据库的状况

返回的JSON数据以下:

{
    "content": [
        {
            "id"10,
            "username""wmyskxz8",
            "password""123"
        },
        {
            "id"9,
            "username""wmyskxz7",
            "password""123"
        },
        {
            "id"8,
            "username""wmyskxz6",
            "password""123"
        },
        {
            "id"7,
            "username""wmyskxz5",
            "password""123"
        },
        {
            "id"6,
            "username""wmyskxz4",
            "password""123"
        }
    ],
    "pageable": {
        "sort": {
            "sorted"true,
            "unsorted"false,
            "empty"false
        },
        "offset"0,
        "pageNumber"0,
        "pageSize"5,
        "unpaged"false,
        "paged"true
    },
    "totalElements"9,
    "last"false,
    "totalPages"2,
    "number"0,
    "size"5,
    "sort": {
        "sorted"true,
        "unsorted"false,
        "empty"false
    },
    "numberOfElements"5,
    "first"true,
    "empty"false
}

删除用户测试:

使用地址http://localhost:8080/delete?id=1来删除ID为1的用户:

image.png

能正确看到Deleted信息,并查看数据可以看到数据已经被删除了。


以上,咱们就快速搭建好了一个CRUD+分页的后台实例,还用了比较流行的RESTful风格,粗略的感觉了一下JPA的方便,仍是挺爽的..没有复杂的Mapper文件,不用自动生成实体,甚至不用管SQL,只须要专一在逻辑上就好了,其实简单使用的话以上的东西也能应付一些常见的场景了,后期再深刻了解了解吧!

参考资料:
springboot(五):spring data jpa的使用——纯洁的微笑
springboot(十五):springboot+jpa+thymeleaf增删改查示例——纯洁的微笑
Spring Boot中使用Spring-data-jpa让数据访问更简单、更优雅——程序猿DD

欢迎转载,转载请注明出处!   
简书ID:@我没有三颗心脏  
github:wmyskxz  
欢迎关注公众微信号:wmyskxz
分享本身的学习 & 学习资料 & 生活
想要交流的朋友也能够加qq群:3382693


我没有三颗心脏

赞扬二维码喜欢做者

相关文章
相关标签/搜索