【SpringBoot2.0系列04】SpringBoot之使用JPA完成简单的rest api

目录

【SpringBoot2.0文章汇总目录,java多线程教程文章汇总 长期更新系列

请多多支持

【SpringBoot2.0系列01】初识SpringBoot
【SpringBoot2.0系列02】SpringBoot之使用Thymeleaf视图模板
【SpringBoot2.0系列03】SpringBoot之使用freemark视图模板
【SpringBoot2.0系列04】SpringBoot之使用JPA完成简单的rest api
【SpringBoot2.0系列05】SpringBoot之整合Mybatis
【SpringBoot2.0系列06】SpringBoot之多数据源动态切换数据源
【SpringBoot2.0系列07】SpringBoot之redis使用(Lettuce版本)

一、 前言

在前面我们已经知道在springboot中如何使用freemarkthymeleaf之类的视图模板引擎去渲染我们的视图页面,但是没涉及跟数据库交互的东西,所以今天在这里我们将介绍了一下如何在springboot中通过spring data jpa操作mysql数据库,并且构建一套简单的rest api接口。

1.1、Spring Data Jpa 介绍

Spring Data JPA是Spring基于Hibernate开发的一个JPA框架。如果用过Hibernate或者MyBatis的话,就会知道对象关系映射(ORM)框架有多么方便。但是Spring Data JPA框架功能更进一步,为我们做了 一个数据持久层框架几乎能做的任何事情。并且提供了基础的增删改查方法,具体api请看官网

2.2

REST是所有Web应用都应该遵守的架构设计指导原则。
Representational State Transfer,翻译是”表现层状态转化”。
面向资源是REST最明显的特征,对于同一个资源的一组不同的操作。资源是服务器上一个可命名的抽象概念,资源是以名词为核心来组织的,首先关注的是名词。REST要求,必须通过统一的接口来对资源执行各种操作。对于每个资源只能执行一组有限的操作。(7个HTTP方法:GET/POST/PUT/DELETE/PATCH/HEAD/OPTIONS)
关于rest api如何涉及我也是从阮一峰老师那里学习的。

二、目标

首先我们有一个user表,我们希望能通过构建出对应的rest api对表中的数据完成增删改查操作。
jpa的依赖如下

        <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-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
    </dependencies>

接下来那么第一步就是创表了
1、创表
由于我们使用的spring data jpa 而jpa的底层实现是hibernate,用过hibernate的同学知道 hibernate可以通过实体类逆向创建表,只需要配置一下ddl-auto 就可以
所以我们需要在application.yml配置一下

server:
  port: 8989
spring:
  datasource:
    username: root
    password: root
    url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8
    driver-class-name: com.mysql.jdbc.Driver
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true

在上面的配置文件中 我们配置了一个数据源跟tomcat端口还有jpa的配置。其中 show-sql: true 代表会在日志中打印我们操作的sql、
而另外 ddl-auto有四个值可选,分别是

  • create 启动时删数据库中的表,然后创建,退出时不删除数据表
  • create-drop 启动时删数据库中的表,然后创建,退出时删除数据表 如果表不存在报错
  • update 最常用的属性,第一次加载hibernate时根据model类会自动建立起表的结构(前提是先建立好数据库),以后加载hibernate时根据 model类自动更新表结构,即使表结构改变了但表中的行仍然存在不会删除以前的行。要注意的是当部署到服务器后,表结构是不会被马上建立起来的,是要等 应用第一次运行起来后才会。
  • validate 项目启动表结构进行校验 如果不一致则报错

所以这里我们希望当表创建成功后 下次启动数据还在我们就选择了update模式,其次我们需要在本地的mysql数据库新建一个test数据库。
接下来我们需要编写的我们实体类User.javahibernate将会通过实体类的结构在test数据库中创建一个对应的user
新建包entity 创建User.java代码如下:

@JsonIgnoreProperties(value={"hibernateLazyInitializer","handler","fieldHandler"}) 
@Entity
public class User {

    @Id
    @GeneratedValue
    private Long id;

    /**
     * 用户名
     */
    @Column(name = "username", nullable = true, length = 32)
    private String username;

    /**
     * 密码
     */
    @Column(name = "password", nullable = true, length = 32)
    private String password;

    /**
     * 年龄
     */
    @Column(name = "age", nullable = true, length = 11)
    private Integer age;

    /**
     * 性别 1=男 2=女 其他=保密
     */
    @Column(name = "sex", nullable = true, length = 11)
    private Integer sex;


    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Integer getSex() {
        return sex;
    }

    public void setSex(Integer sex) {
        this.sex = sex;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }
}

至此,我们的user表也算是创建好了,当我们的程序第一个启动的时候jpa会自动在test数据库中创建与之对应的表。


2、构建rest api
这里我们需要构建如下的rest api

url method 介绍
/user/ get 获取所有的用户信息
/user/id/{id} get 根据id获取用户信息
/user/username/{username} get 根据username获取用户信息
/user post 新增用户信息
/user put 更新用户信息
/user/id/{id} delete 根据id删除用户信息

那么这就是我们需要构建的rest api,那么对应的由mvc模式可知我们的rest apicontroller层的,所以我们的servicerepository层(备注在使用 jpa的时候我们喜欢把dao层命名为repository)需要提供对应的接口。
首先我们首先需要编写UserRepository接口,并且让它基础JpaRepository接口

新建包repository 创建UserRepository.java代码如下:

public interface UserRepository extends JpaRepository<User, Long> {

    /**
     * 根据用户名查找用户信息
     * @param username
     * @return
     */
    User findUserByUsername(String username);

}

解释一下上面的代码,为什么只有一个方法,而前面我们是五个接口,因为是在JpaRepository中提供较为基础的增删改查方法,我们无需编写就看使用。如果大家不信按住ctrl点击JpaRepository看源码就知道了。

image.png

从上面就可以看出JpaRespository提供了哪些基础方法了。怎么样 是不是觉得很方便。那么接下来的第二点就Jpa可以根据你的命名规则来推断你这个方法作用,简单的来说findUserByUsername 根据这个方法名,jpa可以知道这个方法是通过用户名去查找用户。 具体的规则大家可以看文档
image.png

如果大家用的idea的话,那么它会用智能提示功能,如图
image.png

所以我们只需要编写方法名就可以轻轻松松的实现我们的查询方法,怎么样jpa是不是特别简单,但是需要注意的是方法名一定要命名规范,不要嫌太长了。
接下来就是编写我们的service层了,
新建service包创建UserService.java代码如下:

public interface UserService {

    /**
     * 添加用户信息
     * @param user
     * @return
     */
    User saveUser(User user);

    /**
     * 更新用户信息
     * @param user
     */
    User updateUser(User user);

    /**
     * 根据id获取用户
     * @param id
     * @return
     */
    User getById(Long id);

    /**
     * 根据名称获取用户
     * @param username
     * @return
     */
    User getByUserName(String username);

    /**
     * 查询所有用户
     * @return
     */
    List<User> queryAll();

    /**
     * 根据id删除用户信息
     * @param id
     */
    void deleteById(Long id);
}

接下里就下service的实现类,带service包下新建impl包并且创建实现类UserServiceImpl.java 代码如下

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository userRepository;

    @Override
    public User saveUser(User user) {
        return userRepository.save(user);
    }

    @Override
    public User updateUser(User user) {
        return userRepository.save(user);
    }

    @Override
    public User getById(Long id) {
        return userRepository.getOne(id);
    }

    @Override
    public User getByUserName(String username) {
        return userRepository.findUserByUsername(username);
    }

    @Override
    public List<User> queryAll() {
        return userRepository.findAll();
    }

    @Override
    public void deleteById(Long id) {
        userRepository.deleteById(id);
    }
}

那么紧接着就是控制层的代码了,新建controller包,并且创建UserController.java

@RestController
@RequestMapping(value = "/user")
public class UserController {

    @Autowired
    private UserService userService;

    @PostMapping
    public User save(@RequestBody User user) {
        return userService.saveUser(user);
    }

    @PutMapping
    public User update(@RequestBody User user) {
        return userService.saveUser(user);
    }

    @DeleteMapping(value = "/id/{id}")
    public String delete(@PathVariable  Long id) {
        userService.deleteById(id);
        return "删除成功";
    }

    @GetMapping(value = "/id/{id}")
    public User findById (@PathVariable Long id) {
        return userService.getById(id);
    }

    @GetMapping(value = "/username/{username}")
    public User findByUsername (@PathVariable String username) {
        return userService.getByUserName(username);
    }

    @GetMapping(value = "/")
    public List<User> findAll () {
        return userService.queryAll();
    }
}

这样我们就完成了一个简单的rest api了啊。
接下来我们来测试一下把。
3、测试
由于我们这里测试的是rest api普通的浏览器是没法支持 post delet put方式的访问的,所以这里我们就用postman来测试。
1、首先我们看到test数据库中现在是一张表都没有的

image.png

启动程序,注意观察日志。
image.png

我们看到了日志打印了创建表的ddl那么我们再看看数据库中有没有表

image.png

此时我们看到了有两张表,一张是我们user表,而另一张就是主键生成序列表。
接下来就开始我们的rest api测试了。
首先测试新增用户
打开postman

image.png

选择post模式,输入访问的url,然后选择body中的raw,因为我们使用的@RequestBody注解,所以我们选择raw中的Json,如图


image.png

因为我们的id是自增的,所以我们不要输入,直接点击send访问,如果返回的数据有id那么就是代表新增成功。如下图就是新增成功。


image.png

打开数据库中的user表,看看数据有没有保存成功。
image.png

由图可知,保存成功。

接下来我们就多添加几条数据。
那么我们测试一下查询所有数据的方法。操作如图


image.png

我们刚刚一共添加三条数据,全部都查询出来了。
我们继续测试一下修改方法把。我们把id为2的数据密码修改为跟用户名一样,具体操作如图,
image.png

点击send操作成功,我们用根据id查询的方法来查询一下刚刚id为2的数据有没有修改成功,那么我们查询一下id为2的数据,操作如图。
image.png

由图中可以看到我们的修改是成功的,用户名跟密码已经一样的,那么代表我们的根据id查询方法也是没问题的。那么另外几个方法我们不测试了,留给大家测试。

三、总结

这里我们通过这次选择对于jpa的使用有了一个初步的了解,并且对于rest api的规范也有了个了解。

最后配套教程的代码全部在这里
github https://github.com/YuKongEr/SpringBoot-Study。麻烦点个star或者fork吧。
最后大家关注一下我的个人公众号把。

公众号

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349

推荐阅读更多精彩内容