Spring Boot2(九):整合Jpa的基本使用

一、前言

今天早上看到一篇微信文章,說的是國內普遍用的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
#指定配置文件爲test
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
    #打印SQL
    show-sql: true
    hibernate:
      ddl-auto: update  #第一次啓動創建表,之後修改爲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;

    // 用戶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": "[email protected]"
     }
     */
    @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的基本使用

原文地址:https://niaobulashi.com/archives/springboot-jpa.html

To be continued...

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章