spring boot通过JPA访问Mysql
本文主要介绍spring boot如何使用JPA来访问Mysql,对单表做简单的增删改查操作。
环境说明:
- IntelliJ IDEA
- JDK 1.8
- spring boot 2.1.0
- Maven 3.5.0
- Mysql
一、初始化mysql
进入mysql,创建数据库,创建数据表,并生成一些测试数据。
CREATE DATABASE spring_boot_study;
USE spring_boot_study;
DROP TABLE IF EXISTS `novel_type`;
CREATE TABLE `novel_type` (`id` int(11) NOT NULL AUTO_INCREMENT,`novelname` varchar(20) NOT NULL,`novelauthor` varchar(20) NOT NULL,`type` varchar(20) NOT NULL,`introduce` text NOT NULL,`download` varchar(20) DEFAULT 'false',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;-- ----------------------------
-- Records of novel_type
-- ----------------------------
INSERT INTO `novel_type` VALUES ('1', '大主宰', '天蚕土豆', '连载中', '大千世界,位面交汇,万族林立,群雄荟萃,一位位来自下位面的天之至尊,在这无尽世界,演绎着令人向往的传奇,追求着那主宰之路。 无尽火域,炎帝执掌,万火焚苍穹。 武境之内,武祖之威,震慑乾坤。 西天之殿,百战之皇,战威无可敌。 北荒之丘,万墓之地,不死之主镇天地。 ...... 少年自北灵境而出,骑九幽冥雀,闯向了那精彩绝伦的纷纭', 'true');
INSERT INTO `novel_type` VALUES ('2', '斗破苍穹', '天蚕土豆', '已完结', '这里是属于斗气的世界,没有花俏艳丽的魔法,有的,仅仅是繁衍到巅峰的斗气! 新书等级制度:斗者,斗师,大斗师,斗灵,斗王,斗皇,斗宗,斗尊,斗圣,斗帝。', 'true');
INSERT INTO `novel_type` VALUES ('3', '都市无上仙医', '断桥残雪', '已完结', '他当过搬砖工,当过酒吧服务生,当过办公室文员,当过老师,当过医生……他是千千万万打工仔中的一名,为了生计而奔波劳碌,但同时他却又是一位得上古巫王夏禹血脉传承的巫师。 巫,上一横顶天,下一横立地,中间一竖直通天地,中统人与人,是真正通天达地,掌控天地万物生灵之大能者!', 'true');
INSERT INTO `novel_type` VALUES ('4', '遮天', '辰东', '已完结', '冰冷与黑暗并存的宇宙深处,九具庞大的龙尸拉着一口青铜古棺,亘古长存。 这是太空探测器在枯寂的宇宙中捕捉到的一幅极其震撼的画面。 九龙拉棺,究竟是回到了上古,还是来到了星空的彼岸? 一个浩大的仙侠世界,光怪陆离,神秘无尽。热血似火山沸腾,激情若瀚海汹涌,欲望如深渊无止境…… 登天路,踏歌行,弹指遮天。', 'true');
二、Spring boot配置
2.1 application.yml
根据个人喜好选择配置文件的类型,在这里我选择配置application.yml,主要对datasource与jpa进行一些配置说明。
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/spring_boot_study?allowMultiQueries=true&serverTimezone=GMT%2B8username: rootpassword: rootjpa:hibernate:ddl-auto: update # 第一次建表用create,之后用update,show-sql: true # 在控制台打印出sql语句
server:port: 8081servlet:context-path: /spring-boot-study
**注意:**如果通过jpa在数据库中建表,将spring.jpa.hibernate,ddl-auto
改为create
,建完表之后,再改为update
,要不然每次重启工程会删除表并新建。
2.2 pom.xml
至少引入下面四个依赖:
<!--引入JDBC的依赖-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!--引入mysql连接-->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope>
</dependency>
<!--引入web依赖,可以使用@RequestMapping,@RestController等注解-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--引入jpa依赖-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
三、具体编码
概括,本篇文章实现的功能有:
- 查询表中所有数据
- 查询表中所有数据的条数
- 通过小说作者来查询数据
- 向表中插入或更新一条数据
- 根据小说id来判断数据是否存在
- 根据小说id来删除数据
- 根据小说名称来删除数据
3.1 实体(Entity)层
package com.study.spring.entity;import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;@Entity
@Table(name="novel_type")
public class NovelEntity {@Id@Column(name = "id")private Long id;@Column(name = "novelname")private String novelName;@Column(name = "novelauthor")private String novelAuthor;@Column(name = "type")private String type;@Column(name = "introduce")private String introduce;@Column(name = "download")private String download;public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getNovelName() {return novelName;}public void setNovelName(String novelName) {this.novelName = novelName;}public String getNovelAuthor() {return novelAuthor;}public void setNovelAuthor(String novelAuthor) {this.novelAuthor = novelAuthor;}public String getType() {return type;}public void setType(String type) {this.type = type;}public String getIntroduce() {return introduce;}public void setIntroduce(String introduce) {this.introduce = introduce;}public String getDownload() {return download;}public void setDownload(String download) {this.download = download;}@Overridepublic String toString() {return "NovelEntity{" +"id=" + id +", novelName='" + novelName + '\'' +", novelAuthor='" + novelAuthor + '\'' +", type='" + type + '\'' +", introduce='" + introduce + '\'' +", download='" + download + '\'' +'}';}
}
3.2 DAO层
数据访问层,通过编写一个继承自JpaRepository
的接口就能完成数据访问,其中包含了基本的单表查询的方法,非常的方便。
package com.study.spring.jpa;import com.study.spring.entity.NovelEntity;
import org.apache.ibatis.annotations.Param;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;import javax.transaction.Transactional;
import java.io.Serializable;
import java.util.List;/*** @description: 创建Novel JPA接口,继承SpringDataJPA内的接口作为父类。* 继承JpaRepository接口(SpringDataJPA提供的简单数据操作接口)、* JpaSpecificationExecutor(SpringDataJPA提供的复杂查询接口)、* 其中本篇文章仅使用了JpaRepository接口。*/
public interface INovelDAO extends JpaRepository<NovelEntity, Long>,JpaSpecificationExecutor<NovelEntity>
{/*** @description: 通过小说作者来查询数据* @param: author(小说作者)* @param: type(小说类型)* @return: java.util.List<com.study.spring.entity.NovelEntity>*/@Query("select nt from NovelEntity nt where nt.novelAuthor = ?1 and nt.type = ?2")List<NovelEntity> findByAuthorAndType(String author, String type);/*** @description: 根据小说名称来删除数据* @param: novelName(小说名称)* @return: void*/@Transactional@Modifying@Query("delete from NovelEntity nt where nt.novelName = ?1")void deleteByNovelName(String novelName);}
说明:
- 接口类继承
JpaRepository
后,该接口类就可以直接使用自带的findAll(),count(),save(),deleteById()等方法。方法功能可以通过方法名称了解。 - 如果需要一些自定义操作或者复杂查询的话,需要在继承
JpaRepository
的接口里面编写JPQL
语句,查询语句需要在方法上加注解@Query
,增加/修改/删除语句需要在方法上加注解@Transactional
、@Modifying
、@Query
。 JPQL
语句与SQL
语句略有不同,JPQL
语句是对实体进行操作,属性也是实体类里面的属性,而非表字段。
3.3 Service层
由接口类与实现类组成:
接口类:
package com.study.spring.service;import com.study.spring.entity.NovelEntity;import java.util.List;public interface INovelService {/*** @description: 获取表中所有信息* @return: java.util.List<com.study.spring.entity.NovelEntity>*/List<NovelEntity> findAll();/*** @description: 通过小说作者和小说类型来查询数据* @param: author(小说作者)* @param: type(小说类型)* @return: java.util.List<com.study.spring.entity.NovelEntity>*/List<NovelEntity> findByAuthorAndType(String author, String type);/*** @description: 获取表中所有数据的个数* @return: long*/long count();/*** @description: 向表中插入或更新一条数据* @param: novelEntity* @return: void*/void saveNovel(NovelEntity novelEntity);/*** @description: 根据id判断数据是否存在* @param: id* @return: boolean*/boolean exists(Long id);/*** @description: 根据表的id来删除数据* @param: id* @return: void*/void deleteById(Long id);/*** @description: 根据小说名称来删除数据* @param: novelName(小说名称)* @return: void*/void deleteByNovelName(String novelName);}
实现类:
package com.study.spring.service;import com.study.spring.entity.NovelEntity;
import com.study.spring.jpa.INovelDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.List;@Service
public class NovelServiceImpl implements INovelService {@Autowiredprivate INovelDAO inovelDAO;@Overridepublic List<NovelEntity> findAll() {return inovelDAO.findAll();}@Overridepublic List<NovelEntity> findByAuthorAndType(String author, String type) {return inovelDAO.findByAuthorAndType(author, type);}@Overridepublic long count() {return inovelDAO.count();}@Overridepublic void saveNovel(NovelEntity novelEntity) {inovelDAO.save(novelEntity);}@Overridepublic boolean exists(Long id) {return inovelDAO.existsById(id);}@Overridepublic void deleteById(Long id) {inovelDAO.deleteById(id);}@Overridepublic void deleteByNovelName(String novelName) {inovelDAO.deleteByNovelName(novelName);}
}
说明:
- 需要在Serivice层的实现类里面加入注解@Service
- 通过注解@Autowired来引用DAO层的接口INovelDAO
3.4 Controller
package com.study.spring.controller;import com.study.spring.entity.NovelEntity;
import com.study.spring.service.INovelService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.HashMap;
import java.util.List;
import java.util.Map;@RestController
@RequestMapping("novel")
public class NovelController {@Autowiredprivate INovelService iNovelService;/*** @description: 获取表中所有信息* @return: java.util.List<com.study.spring.entity.NovelEntity>*/@RequestMapping("list")public List<NovelEntity> findAll() {return iNovelService.findAll();}/*** @description: 获取表中所有数据的个数* @return: long*/@RequestMapping("count")public long count() {return iNovelService.count();}/*** @description: 向表中插入或更新一条数据* @param: novelEntity* @return: java.util.Map<java.lang.String,java.lang.Boolean>*/@RequestMapping(value = "save", method = RequestMethod.POST)public Map<String, Boolean> saveNovel(NovelEntity novelEntity) {Map<String, Boolean> map = new HashMap<>();try {iNovelService.saveNovel(novelEntity);map.put("status", true);} catch (Exception e) {e.printStackTrace();map.put("status", false);}return map;}/*** @description: 通过小说作者和小说类型来查询数据* @param: author(小说作者),在url中可不指明author参数,默认值为“天蚕土豆”* @param: type(小说类型),在url中必须指明type参数* @return: java.util.List<com.study.spring.entity.NovelEntity>*/@RequestMapping(value = "findByAuthorAndType", method = RequestMethod.GET)public List<NovelEntity> findByAuthorAndType(@RequestParam(value = "author", required = false, defaultValue = "天蚕土豆") String author,@RequestParam(value = "type") String type) {List<NovelEntity> neList;neList = iNovelService.findByAuthorAndType(author, type);return neList;}/*** @description: 根据表的id来删除数据* @param: id* @return: java.util.Map<java.lang.String,java.lang.Boolean>*/@RequestMapping(value = "id/{id}", method = RequestMethod.DELETE)public Map<String, Boolean> deleteById(@PathVariable("id") Long id) {Map<String, Boolean> map = new HashMap<>();// 根据id判断数据是否存在boolean exists = iNovelService.exists(id);try {if (exists) {// 如果数据存在,则删除该数据。iNovelService.deleteById(id);map.put("status", true);} else {map.put("status", false);}} catch (Exception e) {e.printStackTrace();map.put("status", false);}return map;}/*** @description: 根据小说名称来删除数据* @param: novelName* @return: java.util.Map<java.lang.String,java.lang.Boolean>*/@RequestMapping(value = "deleteByNovelName", method = RequestMethod.DELETE)public Map<String, Boolean> deleteByNovelName(@RequestParam(value = "novelName", required = false) String novelName) {Map<String, Boolean> map = new HashMap<>();try {iNovelService.deleteByNovelName(novelName);map.put("status", true);} catch (Exception e) {e.printStackTrace();map.put("status", false);}return map;}
}
说明:
- 需要在Controller层的类上面加入注解@RestController与@RequestMapping(“xxx”)
- 通过注解@Autowired来引用Service层的接口INovelService
- 前后端参数交互使用@RequestParam,默认必须在url中指明参数,如果不需要指明该参数,可以使用
@required = false
,详情可参考上述代码中的findByAuthorAndType()
。 - url参数使用还可使用
@PathVariable
,该注解的参数仅限于url传参,具体使用可参考上述代码的deleteById()
。
四、功能测试
通过Jrebel v2018.2.2
来启动spring boot
程序,可以实现热部署(代码修改即时生效)。
查询所有数据
浏览器访问http://localhost:8081/spring-boot-study/novel/list查询所有数据,如下图所示:
获取表中所有数据的个数
浏览器访问http://localhost:8081/spring-boot-study/novel/count,获取表中数据个数,如下图所示:
插入或更新数据
通过小说作者和小说类型来查询数据
浏览器访问http://localhost:8081/spring-boot-study/novel/findByAuthorAndType?author=天蚕土豆&type=已完结,如下图所示:
根据表的id来删除数据
根据小说名称来删除数据
五、注解概述
1. @Entity:对实体注释
2. @Table:声明此对象映射到数据库的数据表
3. @Id:声明此属性为主键
4. @Column:声明该属性与数据库字段的映射关系。
5. @Service注解:用于标注Service层组件,标注在实现类上。
6. @Autowired
这是一个非常常见的注解。
比如在上述代码示例中所示:在Controller层,需要使用@Autowired
来调用Service层;在Service层,需要使用@Autowired
来调用DAO层;在DAO层实现类中,通过@Autowired
来调用JdbcTemplate。
7. @RestController
Spring4之后新加入的注解,原来返回json需要@ResponseBody
和@Controller
配合。即@RestController
是@ResponseBody
和@Controller
的组合注解。
8. @RequestMapping :配置url映射
9. @PathVariable:url参数化
当使用@RequestMapping URI template
样式映射时, 即someUrl/{paramId}
,这时的paramId
可通过 @Pathvariable
注解绑定它传过来的值到方法的参数上。具体可见上述实例的删除代码逻辑。
10. @RequestParam
@RequestParam
来映射请求参数,required
表示是否必须,默认为true,defaultValue
可设置请求参数的默认值,value
为接收前台参数的参数名。
11. @Query
可在该注解上编写JPQL
语句,例如:@Query("select nt from NovelEntity nt where nt.novelAuthor = ?1 and nt.type = ?2")
12. @Modifying
与注解@Query
一起使用,@Modifying
一般适用于增加/修改/删除的JPQL
语句,例如:@Query("delete from NovelEntity nt where nt.novelName = ?1")
13. @Transactional
事务注解。在本篇文章中,@Query("delete from NovelEntity nt where nt.novelName = ?1")
之上需要添加注解@Modifying
和@Transactional
,否则会报错。
六、总结
前面写了这么多,可算到总结了。现在用几句话来概括一下:
- 首先需要创建数据库,数据表
- 修改yml配置文件,配置datasource与jpa
- 在pom文件中引入相关依赖
- 具体编码。编写Entity类,然后通过继承
JpaRepository
接口来操作Mysql,也可以自定义编写JPQL
语句,最后在Service层实现业务逻辑,在Controller层制作api展示数据。 - 会使用基础注解
源码已上传至https://github.com/841809077/spring-boot-study,欢迎Star。
spring boot通过JPA访问Mysql相关推荐
- jpa mysql_Spring boot通过JPA访问MySQL数据库
本文展示如何通过JPA访问MySQL数据库. JPA全称Java Persistence API,即Java持久化API,它为Java开发人员提供了一种对象/关系映射工具来管理Java应用中的关系数据 ...
- SpringBoot 实战 (八) | 使用 Spring Data JPA 访问 Mysql 数据库
微信公众号:一个优秀的废人 如有问题或建议,请后台留言,我会尽力解决你的问题. 前言 如题,今天介绍 Spring Data JPA 的使用. 什么是 Spring Data JPA 在介绍 Spri ...
- 安卓后端mysql_后端Spring Boot+前端Android交互+MySQL增删查改(Java+Kotlin实现)
1 前言&概述 这篇文章是基于这篇文章的更新,主要是更新了一些技术栈以及开发工具的版本,还有修复了一些Bug. 本文是SpringBoot+Android+MySQL的增删查改的简单实现,用到 ...
- 使用PostgreSQL使用Spring Boot和JPA构建基本应用
"我喜欢编写身份验证和授权代码." 〜从来没有Java开发人员. 厌倦了一次又一次地建立相同的登录屏幕? 尝试使用Okta API进行托管身份验证,授权和多因素身份验证. 每个不平 ...
- Springboot学习1——通过JPA访问MySQL数据库
本文展示如何通过JPA访问MySQL数据库. JPA全称Java Persistence API,即Java持久化API,它为Java开发人员提供了一种对象/关系映射工具来管理Java应用中的关系数据 ...
- Spring Boot使用spring-data-jpa配置Mysql多数据源
转载请注明出处 :Spring Boot使用spring-data-jpa配置Mysql多数据源 我们在之前的文章中已经学习了Spring Boot中使用mysql数据库 在单数据源的情况下,Spri ...
- spring boot 系列之四:spring boot 整合JPA
上一篇我们讲了spring boot 整合JdbcTemplate来进行数据的持久化, 这篇我们来说下怎么通过spring boot 整合JPA来实现数据的持久化. 一.代码实现 修改pom,引入依赖 ...
- Spring Boot与数据访问
Spring Boot与数据访问 JBDC.MyBatis.Spring Data JPA 一.简介 对于数据访问层,无论是SQL还是NOSQL,Spring Boot默认采用整合 Spring Da ...
- Spring Boot Data JPA
Spring Data JPA简介 用来简化创建 JPA 数据访问层和跨存储的持久层功能. Spring Data JPA提供的接口 Repository:最顶层的接口,是一个空的接口,目的是为了统一 ...
- Spring boot(6) 数据访问
Spring boot(6) 数据访问 学习视频:https://www.bilibili.com/video/BV19K4y1L7MT?p=62&spm_id_from=pageDriver ...
最新文章
- Science:产前母体感染促进后代的组织特异性免疫和炎症
- 循环神经网络(RNN)原理通俗解释
- .htaccess文件玩转Rewrite
- 如何修复 Ubuntu 上“...script returned error exit status 1”的错误
- c语言嵌入式学习,学习嵌入式C语言的秘诀
- 计算机网页制作保存,不使用任何工具轻松保存网页资源的法子
- HTML5中weight属性的作用,css font-weight属性怎么用
- 创蓝253短信验证码接口接入常见问题
- 纯卡西欧计算器5800P坐标正反算
- 2020中科院分区表之自动化与控制系统学科和工程技术
- c语言从入门到脱发,知乎|脱发是一种怎样的体验?
- 程序员该造轮子吗,造轮子能升职加薪吗?
- python 电梯运行_面向对象电梯系列总结
- Json系列之二 json to bean(JSONObject类详解)
- 小米智能家居技术分析
- Ruby RestClient教程
- C#发起钉钉审批实例,表格明细 FormComponentValues_的格式该如何传递的问题
- [转]Amit's Astar Page中译文
- nginx+fastcgi+flask延时分段返回数据
- PageAdmin CMS 环境配置要求