今天早上看到一篇微信文章,说的是国内普遍用的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.yml
server: port: 8081
spring: profiles: active: test
|
application-test.yml
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 show-sql: true hibernate: ddl-auto: update
|
application-test.yml
需要了解的是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;
private String userId;
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;
@RequestMapping(value = "/init", method = RequestMethod.GET) public String initData() { for (int i = 1; i < 6; i++) { String userId = String.valueOf(System.currentTimeMillis()); 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);
if (i < 3) { sysUserRole.setId(i); sysUserRole.setUserId(userId); sysUserRole.setRoleId(1); sysUserRoleDao.save(sysUserRole); } else { sysUserRole.setId(i); sysUserRole.setUserId(userId); sysUserRole.setRoleId(2); sysUserRoleDao.save(sysUserRole); } } return "init data success"; }
@RequestMapping(value = "/delete/{userId}", method = RequestMethod.GET) public String deleteUser(@PathVariable("userId") String userId) { sysUserDao.deleteByUserId(userId); return "delete success"; }
@RequestMapping(value = "/list", method = RequestMethod.GET) public List<SysUser> getUsers() { return sysUserDao.findAll(); }
@RequestMapping(value = "/info/{userId}", method = RequestMethod.GET) public Optional<SysUser> getUserById(@PathVariable("userId") String userId) { return sysUserDao.findByUserId(userId); }
@RequestMapping(value = "/update", method = RequestMethod.POST) public String updateAccount(@RequestBody HashMap<String, String> map) { sysUserDao.updateOne( map.get("email"), map.get("userName"), map.get("passWord"), map.get("userId")); return "update success"; }
@RequestMapping(value = "/getUserRole", method = RequestMethod.POST) public List<SysUserInfo> getUserRole(@RequestBody HashMap<String, String> map) { return sysUserDao.findUserRole(map.get("userId")); }
@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> {
@Transactional @Query(value = "delete u from sys_user u where u.user_id = ?1", nativeQuery = true) @Modifying void deleteByUserId(String userId);
@Query(value = "select u.* from sys_user u where u.user_id = ?1", nativeQuery = true) Optional<SysUser> findByUserId(String userId);
@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);
@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);
@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…