百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分析 > 正文

SpringBoot专栏:整合JPA并开启声明式事务(第10讲)

liebian365 2024-10-23 13:51 15 浏览 0 评论

前言

今天给大家介绍的是操作数据库的另一个模块 JPA,即 Java 持久层的 API,极大的简化了我们操作数据库的步骤,使我们的代码具有很强的可维护性。

JPA全称Java Persistence API.JPA通过JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。

JPA 的目标之一是制定一个可以由很多供应商实现的API,并且开发人员可以编码来实现该API,而不是使用私有供应商特有的API。

JPA是需要Provider来实现其功能的,Hibernate就是JPA Provider中很强的一个,应该说无人能出其右。从功能上来说,JPA就是Hibernate功能的一个子集。

快速构建步骤

添加相关依赖

添加spring-boot-starter-jdbc依赖:

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

添加mysql连接类和连接池类:

 <dependency>
 <groupId>mysql</groupId>
 <artifactId>mysql-connector-java</artifactId>
 <scope>runtime</scope>
 </dependency> 

配置数据源,在application.properties文件配置:

spring:
 datasource:
 driver-class-name: com.mysql.jdbc.Driver
 url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8
 username: root
 password: 123456
 jpa:
 hibernate:
 ddl-auto: update # 第一次简表create 后面用update
 show-sql: true

特别注意,如果通过jpa在数据库中建表,将jpa.hibernate,ddl-auto改为create,建完表之后,要改为update,要不然每次重启工程会删除表并新建。

创建实体类

通过@Entity 表明是一个映射的实体类, @Id表明id, @GeneratedValue 字段自动生成

@Entity//告诉JPA这是一个实体类(和数据表映射的类)
@Table(name = "lp_users") //@Table来指定和哪个数据表对应;如果省略默认表名就是user;
public class UserInfo {
 @Id// @GeneratedValue(strategy = GenerationType.IDENTITY)//自增主键
 @Column(name = "ID")
 private String id;
 @Column(name = "ACCOUNT",length = 60) //这是和数据表对应的一个列
 private String account;
 @Column(name = "NAME")//省略默认列名就是属性名
 private String name;
 @Column(name = "REMARKS")
 private String remarks;
 @Column(name = "PASSWORD")
 private String password;
 @Column(name = "IP")
 private String ip;
 @Column(name = "MAC")
 private String mac;
 private Short isautoexpire;
 @Column(name = "ISBINDIP")
 private Short isbindip;
 @Column(name = "ISBINDMAC")
 private Short isbindmac;
*****
}

Dao层

数据访问层,通过编写一个继承自 JpaRepository 的接口就能完成数据访问,其中包含了几本的单表查询的方法,非常的方便。值得注意的是,这个Account 对象名,而不是具体的表名,另外Interger是主键的类型,一般为Integer或者Long

@Transactional//执行修改方法时一定要添加这个注解和@Modifying注解
public interface UserInfoRepository extends JpaRepository<UserInfo,String> {
 @Modifying
 @Query(value = "update lp_users set password = :password where id = :id",nativeQuery = true)
 void resetPasswordById(@Param("id") String id, @Param("password") String password);
 /**报错:
 * java.sql.SQLException: Can not issue data manipulation statements with executeQuery().
 * 解决方式:
 * 在修改方法上面添加@Modifying 注解
 * 报错:
 * javax.persistence.TransactionRequiredException: Executing an update/delete query
 * 解决方式:
 * 在UserRepository.java类上添加@Transactional注解
 */
}

Web层(包含增删改查以及自定义sql等基础方法)

controller层,为了简化测试流程,暂时定义为get方法请求,实际开发中,一定严格规范请求类型已经restful风格

@RestController
@Transactional
public class UserController {
 @Autowired
 UserInfoRepository userInfoRepository;
 /**
 * 新增用户信息
 * IP:端口/user?id=201&account=201&isbindip=1&isbindmac=1
 * @param user
 * @return
 * 注:线上环境应该为post提交
 */
 @GetMapping("/user")
 public UserInfo insertUser(UserInfo user){
 UserInfo save = userInfoRepository.save(user);
 Integer.parseInt("error");
 return save;
 }
 /**
 * 删除用户
 * @param id
 * @return
 */
 @GetMapping("/userdel/{id}")
 public String delUser(@PathVariable("id") String id){
 userInfoRepository.deleteById(id);
 return "success";
 }
 /**
 * 修改密码
 * @param id
 * @return
 */
 @GetMapping("/userupdate/{id}")
 public String updateUser(@PathVariable("id") String id){
 userInfoRepository.resetPasswordById(id,"123456");
 //saveAndFlush
 return "success";
 }
 @GetMapping("/user/{id}")
 public UserInfo getUser(@PathVariable("id") String id){
 //在测试方法上加入@Transactional注解可以解决报错的问题
// UserInfo userList1 = userInfoRepository.getOne(id); //使用getOne()返回的是代理对象,无法直接操作,会出现hibernate lazyxxx no session 的错误
 Optional<UserInfo> userList = userInfoRepository.findById(id);
 //需要结果过做判断,查询结果为null时会报NoSuchElementException
 if(userList.isPresent()){
 return userList.get();
 }
 return null;
 }
 /**
 * 多条件查询用户
 * http://localhost:8080/users?password=fcfc92fc7492b5fc7b74cf92b8b537fc
 * @param userInfo
 * @return
 */
 @GetMapping("/users")
 public List<UserInfo> getUsers(UserInfo userInfo){
 Example<UserInfo> example=Example.of(userInfo);
 List<UserInfo> exampleResult = userInfoRepository.findAll(example);
 return exampleResult;
 }
}

测试添加方法:

IP:端口/user?id=201&account=201&isbindip=1&isbindmac=1

?数据库存在

?其他测试结果..

可以直接下载源码参考:

https://github.com/shinians/springboot-demos

End:

本章内容主要了解基本的增删改查,至于复杂的更加深入的技能点,用户可根据公司需求进行更深层探索,如果本项目对您有帮助也希望您有好的文章、好的心得也及时@我 ,谢谢。

更多问题可以关注@架构师速成记

JPA 概述

1. Java Persistence API(Java 持久层 API):用于对象持久化的 API

2. 作用:使得应用程序以统一的方式访问持久层

3. 前言中提到了 Hibernate,那么JPA 与 Hibernate究竟是什么关系呢:

1)JPA 是 Hibernate 的一个抽象,就像 JDBC 和 JDBC 驱动的关系

2)JPA 是一种 ORM 规范,是 Hibernate 功能的一个子集 (既然 JPA 是规范,Hibernate 对 JPA 进行了扩展,那么说 JPA 是 Hibernate 的一个子集不为过)

3)Hibernate 是 JPA 的一个实现

4. JPA 包括三个方面的技术:

1)ORM 映射元数据,支持 XML 和 JDK 注解两种元数据的形式

2)JPA 的 API

3)查询语言:JPQL

JPA 的基本注解

1. @Entity :修饰实体类,指明该类将映射到指定的数据表

2. @Table :当实体类与映射的数据库表名不同名时需要使用 @Table 注解,该注解与 @Entity 注解并列使用,使用其 name 属性指明数据库的表名

3. @Id :标识该属性为主键一般标注在该属性的 getter 方法上

4. @GeneratedValue :标注主键的生成策略,通过其 strategy 属性。通常与 @Id 注解一起使用。默认情况下 JPA 会自动选择一个最适合底层数据库的主键生成策略,MySQL 默认为 AUTO,常用策略有:

–IDENTITY:采用数据库 ID自增长的方式来自增主键字段,Oracle 不支持这种方式;

AUTOJPA自动选择合适的策略,是默认选项;

–SEQUENCE:通过序列产生主键,通过 @SequenceGenerator 注解指定序列名,MySql 不支持这种方式

–TABLE:通过表产生主键,框架借由表模拟序列产生主键,使用该策略可以使应用更易于数据库移植

5. @Basic :用于没有任何标注的 getXxx() 方法,默认即为 @Basic,所以若一个 getter 方法无任何注解,可以使用 @Basic 注解,也可以不使用

6. @Column :当实体的属性与其映射的数据表的列不同名时使用,一般用于 getter 方法上。其 name 属性用来指明此属性在数据表中对应的列名unique 属性指明是否为唯一约束nullable 属性用来指明是否可以为空,false 为不能为空length 属性指明此列的长度

7. @Transient标注此注解后在创建数据表的时候将会忽略该属性 Customer 类并没有 info 这个属性,所以数据库中也不应该有 info 这个字段

8. @Temporal :向数据库映射日期(Date)属性时用来调整映射的精度。Date 类型的数据有 DATE, TIME, 和 TIMESTAMP 三种精度(即单纯的日期,时间,或者两者兼备).Birth 属性应该使用 DATE 类型(生日只具体到日即可,如:2015-10-22),而 CreateTime 应该使用 TIMESTAMP 类型(创建时间应该具体到秒,如:2017-10-11 22:39:13)

 问题探索:

1.什么是 JPQL?

2.如何开启JPA的二级缓存?

3.如何配置多对一、多对多的关系?

相关推荐

4万多吨豪华游轮遇险 竟是因为这个原因……

(观察者网讯)4.7万吨豪华游轮搁浅,竟是因为油量太低?据观察者网此前报道,挪威游轮“维京天空”号上周六(23日)在挪威近海发生引擎故障搁浅。船上载有1300多人,其中28人受伤住院。经过数天的调...

“菜鸟黑客”必用兵器之“渗透测试篇二”

"菜鸟黑客"必用兵器之"渗透测试篇二"上篇文章主要针对伙伴们对"渗透测试"应该如何学习?"渗透测试"的基本流程?本篇文章继续上次的分享,接着介绍一下黑客们常用的渗透测试工具有哪些?以及用实验环境让大家...

科幻春晚丨《震动羽翼说“Hello”》两万年星间飞行,探测器对地球的最终告白

作者|藤井太洋译者|祝力新【编者按】2021年科幻春晚的最后一篇小说,来自大家喜爱的日本科幻作家藤井太洋。小说将视角放在一颗太空探测器上,延续了他一贯的浪漫风格。...

麦子陪你做作业(二):KEGG通路数据库的正确打开姿势

作者:麦子KEGG是通路数据库中最庞大的,涵盖基因组网络信息,主要注释基因的功能和调控关系。当我们选到了合适的候选分子,单变量研究也已做完,接着研究机制的时便可使用到它。你需要了解你的分子目前已有哪些...

知存科技王绍迪:突破存储墙瓶颈,详解存算一体架构优势

智东西(公众号:zhidxcom)编辑|韦世玮智东西6月5日消息,近日,在落幕不久的GTIC2021嵌入式AI创新峰会上,知存科技CEO王绍迪博士以《存算一体AI芯片:AIoT设备的算力新选择》...

每日新闻播报(September 14)_每日新闻播报英文

AnOscarstatuestandscoveredwithplasticduringpreparationsleadinguptothe87thAcademyAward...

香港新巴城巴开放实时到站数据 供科技界研发使用

中新网3月22日电据香港《明报》报道,香港特区政府致力推动智慧城市,鼓励公私营机构开放数据,以便科技界研发使用。香港运输署21日与新巴及城巴(两巴)公司签署谅解备忘录,两巴将于2019年第3季度,开...

5款不容错过的APP: Red Bull Alert,Flipagram,WifiMapper

本周有不少非常出色的app推出,鸵鸟电台做了一个小合集。亮相本周榜单的有WifiMapper's安卓版的app,其中包含了RedBull的一款新型闹钟,还有一款可爱的怪物主题益智游戏。一起来看看我...

Qt动画效果展示_qt显示图片

今天在这篇博文中,主要实践Qt动画,做一个实例来讲解Qt动画使用,其界面如下图所示(由于没有录制为gif动画图片,所以请各位下载查看效果):该程序使用应用程序单窗口,主窗口继承于QMainWindow...

如何从0到1设计实现一门自己的脚本语言

作者:dong...

三年级语文上册 仿写句子 需要的直接下载打印吧

描写秋天的好句好段1.秋天来了,山野变成了美丽的图画。苹果露出红红的脸庞,梨树挂起金黄的灯笼,高粱举起了燃烧的火把。大雁在天空一会儿写“人”字,一会儿写“一”字。2.花园里,菊花争奇斗艳,红的似火,粉...

C++|那些一看就很简洁、优雅、经典的小代码段

目录0等概率随机洗牌:1大小写转换2字符串复制...

二年级上册语文必考句子仿写,家长打印,孩子照着练

二年级上册语文必考句子仿写,家长打印,孩子照着练。具体如下:...

一年级语文上 句子专项练习(可打印)

...

亲自上阵!C++ 大佬深度“剧透”:C++26 将如何在代码生成上对抗 Rust?

...

取消回复欢迎 发表评论: