一, 前言
今天早上看到一篇微信文章, 说的是国内普遍用的 Mybatis, 而国外确普遍用的是 Jpa. 我之前也看了 jpa, 发现入门相当容易. jpa 对于简单的 CRUD 支持非常好, 开发效率也会比 Mybatis 高出不少, 因为 JpaRepository 会根据你定制的实体类, 继承了 JpaRepository 会有一套完整的封装好了的基本条件方法. 减少了很多开发量. 你只需要写 SQL 就行了. 可能我才刚入门 Jpa, 对一些认识还是很浅显. 我觉得 Jpa 对于多表查询, 开发起来有点吃力..
这是我开始玩 Jpa 的最初的感受, 但是 Jpa 却受到了极大的支持和赞扬, 在国外 Jpa 远比 Mybatis 流行得多得多. 国内却还是在流程用 Mybatis, 估计也是收到很多培训机构或者大 V 的带领下, 很多国内优秀的开源项目也是用的 Mybatis, 因为已经用得非常熟练了.
话不多说, 先看看 SpringBoot 如何整合使用 Jpa 吧!
这里具体讲一讲 Jpa 的搭建, 几种常见的场景的使用: 增删改查, 多表查询, 非主键查询这几种情况的一个学习总结.
二, 代码部署
1, 添加 Maven 依赖
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-devtools</artifactId>
- <scope>runtime</scope>
- <optional>true</optional>
- </dependency>
- <dependency>
- <groupId>org.projectlombok</groupId>
- <artifactId>lombok</artifactId>
- <optional>true</optional>
- </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>
- <dependency>
- <groupId>MySQL</groupId>
- <artifactId>MySQL-connector-java</artifactId>
- <scope>runtime</scope>
- </dependency>
其实 Jpa 关键用到的是最下面两块
2, 配置 application
application.YAML
- server:
- port: 8081
- # 指定配置文件为 test
- spring:
- profiles:
- active: test
- application-test.YAML
- spring:
- datasource:
- driver-class-name: com.MySQL.cj.jdbc.Driver
- url: jdbc:MySQL://127.0.0.1:3306/jpatest?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
- username: root
- password: root
- jpa:
- # 数据库类型
- database: MySQL
- #打印 SQL
- show-sql: true
- hibernate:
- ddl-auto: update #第一次启动创建表, 之后修改为 update
application-test.YAML 需要了解的是 jpa 分支, 如果需要通过 jpa 在数据库中建表, 就将 spring.jpa.hibernate.ddl-auto 改为 create, 建完表之后, 建议改为 update, 否则你再次重启, 表会回炉重造, 数据相应的会丢失. 可得注意啦.
3, 创建实体类
用户表 sys_user 的实体类
- @Data
- @Entity
- @Table(name = "sys_user")
- public class SysUser implements Serializable {
- @Id
- private String userId;
- @Column(nullable = false)
- private String userName;
- @Column(nullable = false)
- private String passWord;
- @Column(nullable = false, unique = true)
- private String email;
- @Column(nullable = false, unique = true)
- private String salt;
- @Column(nullable = false)
- private Date regTime;
- }
用户角色对照表 sys_user_role 的实体类
- @Entity
- @Data
- @Table(name = "sys_user_role")
- public class SysUserRole implements Serializable {
- @Id
- @GeneratedValue
- private int id;
- // 用户 ID
- private String userId;
- // 角色 ID
- private int roleId;
- }
4,Dao 层
用户表 SysUserDao
- public interface SysUserDao extends JpaRepository<SysUser, Integer> {
- }
用户角色对照表 SysUserRoleDao
- public interface SysUserRoleDao extends JpaRepository<SysUserRole, Integer> {
- }
5,Controller 层
- @RestController
- @RequestMapping("/user")
- public class UserController {
- @Autowired
- private SysUserDao sysUserDao;
- @Autowired
- private SysUserRoleDao sysUserRoleDao;
- /**
- * 用户表 sys_user, 用户角色对照表 sys_user_role. 数据初始化
- */
- // 发送 get 请求进行数据添加: 127.0.0.1:8081/user/init
- @RequestMapping(value = "/init", method = RequestMethod.GET)
- public String initData() {
- for (int i = 1; i <6; i++) {
- // 根据时间戳生成 userId
- String userId = String.valueOf(System.currentTimeMillis());
- // new 出用户表和用户角色表的对象
- SysUser sysUser = new SysUser();
- SysUserRole sysUserRole = new SysUserRole();
- // 新增用户表
- sysUser.setUserId(userId);
- sysUser.setUserName("username_num" + i);
- sysUser.setPassWord("password_num" + i);
- sysUser.setEmail("email_num" + i + "@qq.com");
- sysUser.setSalt(i + "");
- sysUser.setRegTime(new Date());
- sysUserDao.save(sysUser);
- // 暂时规定小于 3 的, 角色为 1, 新建用户角色表
- if (i < 3) {
- sysUserRole.setId(i);
- sysUserRole.setUserId(userId);
- sysUserRole.setRoleId(1);
- sysUserRoleDao.save(sysUserRole);
- } else {
- // 大于 3 的, 角色为 2
- sysUserRole.setId(i);
- sysUserRole.setUserId(userId);
- sysUserRole.setRoleId(2);
- sysUserRoleDao.save(sysUserRole);
- }
- }
- return "init data success";
- }
- /**
- * 删除
- */
- // 发送 get 请求: 127.0.0.1:8081/user/delete/1562486017644
- @RequestMapping(value = "/delete/{userId}", method = RequestMethod.GET)
- public String deleteUser(@PathVariable("userId") String userId) {
- sysUserDao.deleteByUserId(userId);
- return "delete success";
- }
- /**
- * 查询全部
- * @return
- */
- // 发送 get 请求: 127.0.0.1:8081/user/list
- @RequestMapping(value = "/list", method = RequestMethod.GET)
- public List<SysUser> getUsers() {
- return sysUserDao.findAll();
- }
- /**
- * 根据 id 查询
- */
- // 发送 get 请求: 127.0.0.1:8081/user/info/1562486017644
- @RequestMapping(value = "/info/{userId}", method = RequestMethod.GET)
- public Optional<SysUser> getUserById(@PathVariable("userId") String userId) {
- return sysUserDao.findByUserId(userId);
- }
- /**
- * 更新
- */
- // 发送 post 请求: 127.0.0.1:8081/user/update
- // 发送报文体如下
- /*
- {
- "userId":"1562486017551",
- "passWord": "231231231212312",
- "userName":"Tom",
- "email": "1111111@qq.com"
- }
- */
- @RequestMapping(value = "/update", method = RequestMethod.POST)
- public String updateAccount(@RequestBody HashMap<String, String> map) {
- // 根据 Id 更新用户信息
- sysUserDao.updateOne(
- map.get("email"),
- map.get("userName"),
- map.get("passWord"),
- map.get("userId"));
- return "update success";
- }
- /**
- * 关联查询用户的角色信息
- */
- // 发送 post 请求: 127.0.0.1:8081/user/getUserRole
- // 发送报文体如下
- /*
- {
- "userId":"1562486017629"
- }
- */
- @RequestMapping(value = "/getUserRole", method = RequestMethod.POST)
- public List<SysUserInfo> getUserRole(@RequestBody HashMap<String, String> map) {
- return sysUserDao.findUserRole(map.get("userId"));
- }
- /**
- * 根据非主键 username 模糊查询
- */
- // 发送 post 请求: 127.0.0.1:8081/user/getUserByUserName
- // 发送报文体如下
- /*
- {
- "userName":"username"
- }
- */
- @RequestMapping(value = "/getUserByUserName", method = RequestMethod.POST)
- public List<SysUser> getUserByUserName(@RequestBody HashMap<String, String> map) {
- return sysUserDao.findUserName(map.get("userName"));
- }
- }
代码有点多, 只是我写的例子多了点
6, 补充 Dao
- public interface SysUserDao extends JpaRepository<SysUser, Integer> {
- /**
- * 根据 userId 删除数据
- */
- @Transactional
- @Query(value = "delete u from sys_user u where u.user_id = ?1", nativeQuery = true)
- @Modifying
- void deleteByUserId(String userId);
- /**
- * 根据 UserId 查询
- * @param userId
- * @return
- */
- @Query(value = "select u.* from sys_user u where u.user_id = ?1", nativeQuery = true)
- Optional<SysUser> findByUserId(String userId);
- /**
- * 根据 Id 更新用户相关信息
- * nativeQuery = true 添加该属性等于 true 则是原生 SQL 语句查询, 不添加则是 HQL 语句
- */
- @Transactional
- @Query(value = "update sys_user set email=?1, user_name=?2, pass_word=?3 where user_id=?4", nativeQuery = true)
- @Modifying
- public void updateOne(String email, String userName, String passWord, String userId);
- /**
- * 查询用户角色
- * @param userId
- * @return
- */
- @Query(value = "SELECT" +
- "t.user_id AS userId," +
- "t.user_name AS userName," +
- "t.email AS email," +
- "t.pass_word AS passWord," +
- "r.role_id AS roleId" +
- "FROM sys_user t LEFT JOIN sys_user_role r" +
- "ON r.user_id = t.user_id" +
- "WHERE t.user_id = ?1", nativeQuery = true)
- List<SysUserInfo> findUserRole(String userId);
- /**
- * 根据 username 查询用户信息
- * @return
- */
- @Query(value = "select u.* from sys_user u where u.user_name like CONCAT('%',?1,'%')", nativeQuery = true)
- List<SysUser> findUserName(String nickName);
- }
这里需要注意的在 findUserRole 方法, 是联表查询, 其结果集在 SysUserInfo 中
- public interface SysUserInfo {
- String getUserId();
- String getUserName();
- String getEmail();
- String getPassWord();
- int getRoleId();
- }
三, 测试
启动项目之前, 将 spring.jpa.hibernate.ddl-auto 改为 create. 启动完成之后改为 update 或者 none.
会生成两张表 sys_user 用户表, sys_user_role 用户角色对应表
然后通过 controller 里的一个接口 init, 发送 get 请求
生成一些数据.
之后可以进行具体的数据库接口操作啦.
四, 总结
在学习过程中, 敲代码也遇到不少坑, 感觉 Jpa 还行, 确实比 Mybatis 快了不少, 不需要建立 mapper.xml 文件.
可是在项目中不可能都是一些简单的查询 SQL 呀, 肯定会遇到许多复杂的 SQL, 如果用 Jpa 的话, 感觉并不是那么好用. 当然我还没有深入去学习它. 肯定有许多我不太明白的技术. 肯定可以解决不复杂 SQL.
我在网上也搜索了, 有些人会建议将 Jpa 和 Mybatis 结合使用. 我也感觉这点子不错. 后续会继续研究
GitHub 源码地址: Spring Boot2(九): 整合 Jpa 的基本使用
To be continued...
来源: https://www.cnblogs.com/niaobulashi/p/springboot-jpa.html