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 不支持这种方式;
–AUTO: JPA自动选择合适的策略,是默认选项;
–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字符串复制...
- 二年级上册语文必考句子仿写,家长打印,孩子照着练
-
二年级上册语文必考句子仿写,家长打印,孩子照着练。具体如下:...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- wireshark怎么抓包 (75)
- qt sleep (64)
- cs1.6指令代码大全 (55)
- factory-method (60)
- sqlite3_bind_blob (52)
- hibernate update (63)
- c++ base64 (70)
- nc 命令 (52)
- wm_close (51)
- epollin (51)
- sqlca.sqlcode (57)
- lua ipairs (60)
- tv_usec (64)
- 命令行进入文件夹 (53)
- postgresql array (57)
- statfs函数 (57)
- .project文件 (54)
- lua require (56)
- for_each (67)
- c#工厂模式 (57)
- wxsqlite3 (66)
- dmesg -c (58)
- fopen参数 (53)
- tar -zxvf -c (55)
- 速递查询 (52)