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