Spring同時整合JPA與Mybatis

智慧zhuhuix發表於2020-08-11

@

ORM

  • ORM的出現,使得關係型資料庫對映成了物件;簡單來說,有了ORM之後,JAVA程式設計師從面向JDBC程式設計轉化成面向JAVA物件程式設計。

在這裡插入圖片描述

Spring ORM

  • Spring對ORM的解決方案主要體現在以下方面:

    1. 統一的資源管理方式與異常管理:Spring使用各種ORM框架,資源管理及使用方式都是統一的;同時Spring會將各個ORM框架的異常轉譯到Spring異常體系下。
    2. 統一的事務管理:Spring通過IoC和AOP技術,形成了事務管理抽象層,接管了各種ORM框架下的資料訪問的事務管理。
  • 隨著版本的升級,Spring核心包中對ORM的各種解決方案也越來越精煉。本文我們重點將介紹同時整合Spring Data JPAMybatis兩個ORM框架。

Spring ORM 同時整合JPA與Mybatis

  • 在同一個專案中一般只會單獨整合Spring Data JPA,或者單獨整合Mybatis。但兩者也可以混合使用(一般沒這個必要),本文為了更加深入探索Spring ,將通過一個DEMO應用兩者的並展示相似點與不同之處。
一、建立一個SpringBoot專案
  1. IntelliJ IDEA中建立新專案
    在這裡插入圖片描述
  2. 通過地址https://start.spring.io/初始化專案;
    在這裡插入圖片描述
  3. 指定專案通用資訊:
    在這裡插入圖片描述
  4. 選擇專案依賴Starter
    在這裡插入圖片描述
  5. 生成的專案結構:
    在這裡插入圖片描述
二、建立使用者資訊登記表
  • 根據使用者資訊模型類,設計使用者資訊登入表
DROP DATABASE IF EXISTS user_info;

CREATE DATABASE user_info
	DEFAULT CHARACTER SET utf8
	DEFAULT COLLATE utf8_general_ci;

use user_info;

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `email` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;

在這裡插入圖片描述

三、Web應用專案整合mysql
  • 增加依賴
 <!--Mysql依賴包-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
            <scope>runtime</scope>
        </dependency>
 <!-- 資料庫連線池:druid資料來源驅動 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>
  • Spring資料來源配置
###資料來源配置
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    username: root
    password: root
    driver-class-name: net.sf.log4jdbc.sql.jdbcapi.DriverSpy
    url: jdbc:log4jdbc:mysql://localhost:3306/user_info?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true
四、新增Spring Data JPA和Mybatis依賴
<!--pom.xml-->
		<!--Spring Data JPA-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
         <!-- mybatis -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>
五、新增資料表對映實體類
/**
 * 使用者類--對映表user
 *
 * @author zhuhuix
 */
@Entity
@Table(name="user_info")
public class User implements Serializable {
    // 使用者id
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    // 使用者名稱
    @NotBlank(message = "使用者名稱稱不能為空")
    @Column(name="name")
    private String name;
    // 郵箱
    @Column(name="email")
    @Pattern(message ="郵箱格式不符", regexp = "^[A-Za-z0-9\\u4e00-\\u9fa5]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$")
    private String email;

    public User(Long id, String name, String email) {
        this.id = id;
        this.name = name;
        this.email = email;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}
六、建立資料介面層
6.1 宣告JPA介面
  • 藉助Spring Data JPA,我們可以通過繼承CrudRepository介面,快速定義應用的資料層。CrudRepository定義並實現了很多用於crud(建立、讀取、更新、刪除)操作的方法,我們根本就不用編寫實現類!當應用啟動的時候,Spring Data JPA會在執行期自動生成實現類。
/**
 * 基於SpringMVC框架開發web應用--資料操作層
 */
public interface UserRepository extends CrudRepository<User,Long> {

}
  • CrudRepository的一些預設實現
public interface CrudRepository<T, ID> extends Repository<T, ID> {
    <S extends T> S save(S var1);

    <S extends T> Iterable<S> saveAll(Iterable<S> var1);

    Optional<T> findById(ID var1);

    boolean existsById(ID var1);

    Iterable<T> findAll();

    Iterable<T> findAllById(Iterable<ID> var1);

    long count();

    void deleteById(ID var1);

    void delete(T var1);

    void deleteAll(Iterable<? extends T> var1);

    void deleteAll();
}
6.2 宣告MyBatis介面
  • 雖然強大的Spring Data JPA已經幫我們封裝了多種資料操作,但由於業務邏輯的複雜度及自定義 SQL的需求,我們仍然可以運用MyBatis框架完成ORM的處理。
/**
 * mybatis資料層介面
 *
 */
@Repository
public interface UserMapper {

    // 自定義新增通過使用者名稱稱模糊查詢使用者資訊
    List<User> findByName(String name);
    
}
  • Mybatis Mapper對映
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mybatis.UserMapper">
	<!-- 自定義模糊查詢 SQL -->
    <select id="findByName" resultType="com.example.demo.register.User">
        select * from user where name like concat('%',#{name},'%')
    </select>

</mapper>
  • Spring新增MyBatis配置
    修改application.yml配置檔案:定位mapper檔案掃描路徑
#MyBatis掃描mapper檔案配置
mybatis:
  mapper-locations: classpath:mapper/*Mapper.xml

在這裡插入圖片描述

  • 在啟動類里加上註解用於給出需要掃描的mapper檔案路徑
@SpringBootApplication
@MapperScan(basePackages = "com.example.demo.register")
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}
七、建立業務服務層
  • 建立UserService服務層直接呼叫由Spring Data JPAMybatis介面各自提供的資料操作方法,以實現使用者資訊的增刪改查。
/**
 * 呼叫Spring Data JPA和Mybatis介面進行業務處理
 */
@Service
public class UserService {

    // Spring Data JPA
    @Autowired
    private UserRepository userRepository;
    // Mybatis
    @Autowired
    private UserMapper userMapper;

    // 返回所有的使用者
    public List<User> listUsers() {
        return (List<User>) userRepository.findAll();
    }

    // 儲存使用者
    public User saveUser(User user) {
        return userRepository.save(user);
    }

    // 刪除使用者
    public void deleteUser(Long id) {
        userRepository.deleteById(id);
    }

    // 查詢使用者
    public User findUser(Long id) {
        return userRepository.findById(id).get();
    }

    // 根據名稱查詢使用者--Mybatis
    public List<User> searchUser(String name) {
        return userMapper.findByName(name);
    }

}

八、建立控制器
  • 控制器的主要職責是處理HTTP請求傳遞給檢視以便於渲染瀏覽器展現。

  • SpirngMVC的請求註解

註解 描述
@RequestMapping 通用的請求
@GetMapping 處理HTTP GET請示
@PostMapping 處理HTTP POST請示
@PutMapping 處理HTTP PUT請示
@DeleteMapping 處理HTTP DELETE請示
/**
 * 使用者控制器
 */
@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;

    // 儲存使用者並返回到使用者列表頁面
    @PostMapping
    public ModelAndView saveUser(@Valid User user, Errors errors, Model model) {
        if (errors.hasErrors()) {
            model.addAttribute("user", user);
            if (errors.getFieldError("name") != null) {
                model.addAttribute("nameError", errors.getFieldError("name").getDefaultMessage());
            }
            if (errors.getFieldError("email") != null) {
                model.addAttribute("emailError", errors.getFieldError("email").getDefaultMessage());
            }
            return new ModelAndView("register", "userModel", model);
        }
        userService.saveUser(user);
        //重定向到list頁面
        return new ModelAndView("redirect:/user");
    }

    // 獲取使用者操作表單頁面
    @GetMapping("/form")
    public ModelAndView createForm(Model model, @RequestParam(defaultValue = "0") Long id) {
        if (id > 0) {
            model.addAttribute("user", userService.findUser(id));
        } else {
            model.addAttribute("user", new User());
        }
        return new ModelAndView("register", "userModel", model);
    }

    // 獲取使用者列表顯示頁面
    @GetMapping
    public ModelAndView list(Model model) {
        model.addAttribute("userList", userService.listUsers());
        return new ModelAndView("userlist", "userModel", model);
    }

    // 模糊查詢輸入頁面
    @GetMapping("/index")
    public ModelAndView index(Model model) {
        model.addAttribute("user", new User());
        return new ModelAndView("index", "userModel", model);
    }

    // 查詢提交併跳轉使用者列表
    @PostMapping("/search")
    public ModelAndView search(@ModelAttribute User user, Model model) {
        model.addAttribute("userList", userService.searchUser(user.getName()));
        return new ModelAndView("userlist", "userModel", model);
    }

    // 刪除使用者
    @RequestMapping(path = "/del")
    public ModelAndView del(@RequestParam(name = "id") Long id) {
        userService.deleteUser(id);
        return new ModelAndView("redirect:/user");
    }
}

九、設計檢視模板
9.1 設計一個使用者列表的檢視模板
  • Thymeleaf提供了一個屬性th:each,它會迭代一個元素集合,為集合中的每個條目渲染HTML,我們可以利用這個屬性,設計出使用者的列表檢視。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultrag.net.nz/thymeleaf/layout"
>
<head>
    <meta charset="UTF-8">
</head>
<body>
<h3>使用者列表</h3>
<div>
    <a th:href="@{/user/form}">建立使用者</a>
    <a th:href="@{/user/index}">查詢使用者</a>
</div>
<table border="1">
    <thead>
    <tr>
        <td>ID</td>
        <td>郵箱</td>
        <td>名稱</td>
        <td>操作</td>
    </tr>
    </thead>
    <tbody>
    <tr th:if="${userModel.userList.size()} eq 0">
        <td colspan="3">沒有使用者資訊!</td>
    </tr>
    <tr th:each="user:${userModel.userList}">
        <td th:text="${user.id}"></td>
        <td th:text="${user.email}"></td>
        <td th:text="${user.name}"></td>
        <td><a th:href="@{/user/form(id=${user.id})}"> 修改 </a> <a th:href="@{/user/del(id=${user.id})}"> 刪除 </a></td>
    </tr>
    </tbody>
</table>
</body>
</html>
9.2 設計一個提交使用者資訊的表單模板
  • 使用者通過這個檢視,錄入名稱與郵箱地址,提交儲存新使用者的資訊。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultrag.net.nz/thymeleaf/layout"
>
<head>
    <meta charset="UTF-8">
</head>
<body>
<h3>登記使用者</h3>
<form action="/users" th:action="@{/user}" method="POST" th:object="${userModel.user}">
    <input type="hidden" name="id" th:value="*{id}">
    名稱:<br>
    <input type="text" name="name" th:value="*{name}">
    <br>
    郵箱:<br>
    <input type="text" name="email" th:value="*{email}">
    <input type="submit" value="提交" >
</form>
</body>
</html>
9.3 設計一個使用者模糊查詢頁面模板
<!-- index.html-->
<!DOCTYPE html>
<html  xmlns:th="http://www.thymeleaf.org" >
<head>
     <meta charset="UTF-8"/>
     <title>Title</title>
</head>
 <body>

     <h3>查詢使用者</h3>
     <form action="/users" th:action="@{/user/search}" method="POST" th:object="${userModel.user}">
         名稱:<br>
         <input type="text" name="name" th:value="*{name}" >
         <br>
         <input type="submit" value="查詢" >
     </form>

 </body>
 </html>
十、執行應用
  • 到目前為止,我們已經開發了User使用者類、JPA資料介面、Mybatis資料介面、UserService使用者服務類、UserController控制器、使用者列表檢視模板、使用者登記檢視模板、使用者模糊查詢頁面模板,接下來我們嘗試啟動程式,並進行操作測試。
    在這裡插入圖片描述
10.1使用者列表

在這裡插入圖片描述

10.2增加使用者
  • 點選頁面上的建立使用者,登記新使用者,並提交
    在這裡插入圖片描述
    在這裡插入圖片描述
10.3查詢使用者

在這裡插入圖片描述
在這裡插入圖片描述

在這裡插入圖片描述

該web應用一切執行正常。

相關文章