說明:基於 MyBatis 有很多第三方功能外掛,這些外掛可以完成資料操作方法的封裝、資料庫逆向工程的生成等。
tkMapper
和MyBatis-plus
都是基於 MyBatis 提供的第三方外掛,功能類似,下面介紹 tkMapper 的使用。
tkMapper 就是一個 MyBatis 外掛,基於 MyBatis 提供很多工具,提高開發效率,主要有以下兩個功能。
tkMapper 的使用需要基於 MyBatis。
建立 Spring Boot 專案,選中 Lombok、Spring Web、MyBatis Framework、MySQL Driver 依賴
application.yml 組態檔中設定相關資訊
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/springdb?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8
username: root
password: luis
mybatis:
type-aliases-package: com.luis.beans
mapper-locations: classpath:mappers/*Mapper.xml
注意:設定後,手動建立 beans 和 mappers 資料夾
建立 dao 資料夾,在啟動類上新增 dao 的包掃描器 @MapperScan(basePackages = {"com.luis.dao"})
新增依賴
<!-- tkMapper -->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>2.1.5</version>
</dependency>
如果自己在 maven 倉庫中搜尋,注意搜尋關鍵詞:mapper starter
PS:新增後,注意手動重新整理 pom
更換啟動類上 dao 包的包掃描器來源,不使用原先的 @MapperScan
,要使用新新增的 tkMapper 的 @MapperScan
import tk.mybatis.spring.annotation.MapperScan;
@SpringBootApplication
@MapperScan(basePackages = {"com.luis.dao"}) //使用tkMapper的包掃描器註解
public class SpringbootTkMapperDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootTkMapperDemoApplication.class, args);
}
}
PS:注意註解的包來源 import tk.mybatis.spring.annotation.MapperScan
以上,tkMapper 環境已經搭建完成
tkMapper 提供針對單表通用的資料庫操作方法。
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`user_id` int(11) NOT NULL AUTO_INCREMENT,
`user_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`user_pwd` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`user_realname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`user_img` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`user_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Compact;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "users") //資料庫表名和實體類類名不一致需要指定對映關係!
public class User {
@Id //指定主鍵
private Integer userId;
private String userName;
private String userPwd;
private String userRealname;
private String userImg;
}
注意:建立的 Dao 介面需要繼承 tkMapper 中提供的 Mapper
和 MySqlMapper
兩個介面,這兩個介面提供了對單表的通用操作。
public interface UserDao extends Mapper<User>, MySqlMapper<User> {
}
可選優化策略【建議使用】:
如果不想每次建立 dao 介面時都繼承 tkMapper 中的兩個介面,可以自己寫一個通用的介面模板,只需要讓這個通用的介面模板繼承 tkMapper 中的兩個介面,然後自己建立的 dao 介面只需要繼承這個通用的介面模板即可!
但是,需要注意的是,這個通用的介面模板千萬不能寫在 dao 目錄下!因為 dao 目錄下的介面會被掃描到,有固定的功能用處;而我們自定義的通用介面模板只是為了繼承,沒有其他特殊功能!
使用範例:
1、可在 dao 目錄同級建立 general 目錄,在 general 目錄下建立 GeneralDao 介面,並繼承 tkMapper 中的兩個介面。
package com.luis.general; import tk.mybatis.mapper.common.Mapper; import tk.mybatis.mapper.common.MySqlMapper; /** * @Author: Luis * @date: 2022/11/9 14:39 * @description: 自定義的通用介面模板 */ public interface GeneralDao<T> extends Mapper<T>, MySqlMapper<T> { }
2、建立 dao 介面,繼承 GeneralDao 即可!
public interface UserDao extends GeneralDao<User> { }
新增 Junit 和 springboot test 兩個測試依賴:
<!-- junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<!-- springboot test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
寫測試類進行測試:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringbootTkMapperDemoApplication.class) //啟動類.class
public class UserDaoTest {
@Autowired
private UserDao userDao; //如果爆紅線不用管(或Dao介面上新增@Repository註解)
@Test
public void test() {
User user = new User();
user.setUserName("mike");
user.setUserPwd("123");
user.setUserRealname("zhangsan");
user.setUserImg("user/default.jpg");
int i = userDao.insert(user);
System.out.println("========> i = " + i);
}
}
insert
:普通新增insertUseGeneratedKeys
:可返回自增 id 的新增updateByPrimaryKey
:根據主鍵修改deleteByPrimaryKey
:根據主鍵刪除@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringbootTkMapperDemoApplication.class) //啟動類.class
public class UserDaoTest {
@Autowired
private UserDao userDao; //如果爆紅線不用管(或Dao介面上新增@Repository註解)
@Test
public void testInsert() {
User user = new User();
user.setUserName("juno4");
user.setUserPwd("321");
user.setUserRealname("lin");
user.setUserImg("user/default.jpg");
/**
* insert: 新增(自增的id不會返回)
*/
int i = userDao.insert(user);
System.out.println("========> i = " + i);
System.out.println(user.getUserId()); //null
}
@Test
public void testInsertUseGeneratedKeys() {
User user = new User();
user.setUserName("juno3");
user.setUserPwd("321");
user.setUserRealname("lin");
user.setUserImg("user/default.jpg");
/**
* insertUseGeneratedKeys: 新增(自增的id可以返回)
* 注意:
* 1. 資料庫中主鍵欄位需要設定為自增
* 2. 實體類中主鍵屬性需要使用@Id註解指定;並且需要使用包裝型別Integer,不要使用int
*/
int i = userDao.insertUseGeneratedKeys(user);
System.out.println("========> i = " + i);
System.out.println(user.getUserId()); //10
}
@Test
public void testUpdateByPrimaryKey() {
User user = new User();
user.setUserId(10); //必須指定要修改的id
user.setUserName("juno new");
user.setUserPwd("000");
user.setUserRealname("lin new");
user.setUserImg("new.jpg");
/**
* updateByPrimaryKey:根據主鍵修改
*/
int i = userDao.updateByPrimaryKey(user);
System.out.println("========> i = " + i);
System.out.println(user);
}
@Test
public void testDeleteByPrimaryKey() {
/**
* deleteByPrimaryKey:根據主鍵刪除
*/
int i = userDao.deleteByPrimaryKey(9);
System.out.println("========> i = " + i);
}
}
PS:其實還有根據自定義條件修改或刪除的方法(使用方法參考帶條件的查詢範例)
selectAll
:查所有selectByPrimaryKey
:根據主鍵查所有selectByExample
:根據條件查所有selectByRowBounds
:分頁查詢selectByExampleAndRowBounds
:帶條件的分頁查詢selectCount
:查總記錄數selectCountByExample
:根據條件查總記錄數@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringbootTkMapperDemoApplication.class) //啟動類.class
public class UserDaoTest {
@Autowired
private UserDao userDao; //如果爆紅線不用管(或Dao介面上新增@Repository註解)
@Test
public void testSelectAll() {
/**
* selectAll:查詢所有
*/
List<User> users = userDao.selectAll();
for (User user : users) {
System.out.println(user);
}
}
@Test
public void testSelectByPrimaryKey() {
/**
* selectByPrimaryKey:根據主鍵查詢
*/
User user = userDao.selectByPrimaryKey(10);
System.out.println(user);
}
@Test
public void testSelectByExample() {
//封裝查詢條件
Example example = new Example(User.class);
Example.Criteria criteria = example.createCriteria();
//條件資訊(根據Criteria物件的各種方法進行設定)
criteria.andEqualTo("userRealname", "lin");
// criteria.orEqualTo("userPwd", "123");
// criteria.andLike("userName", "%i%");
/**
* selectByPrimaryKey:根據條件查詢(PS:根據條件修改或刪除與此類似)
* 注意:需要設定查詢條件資訊,並傳入條件物件
*/
List<User> users = userDao.selectByExample(example);
for (User user : users) {
System.out.println("========> " + user);
}
}
@Test
public void testSelectByRowBounds() {
//分頁查詢資訊
int pageNum = 2; //第幾頁
int pageSize = 3; //每頁顯示多少行
int start = (pageNum - 1) * pageSize; //起始顯示的下標
RowBounds rowBounds = new RowBounds(start, pageSize);
/**
* selectByRowBounds:查所有的分頁查詢
*/
List<User> users = userDao.selectByRowBounds(new User(), rowBounds);
for (User user : users) {
System.out.println("========> " + user);
}
/**
* selectCount:查詢總記錄數
*/
int count = userDao.selectCount(new User());
System.out.println("========> count = " + count);
}
@Test
public void testSelectByExampleAndRowBounds() {
//封裝查詢條件
Example example = new Example(User.class);
Example.Criteria criteria = example.createCriteria();
criteria.andEqualTo("userRealname", "lin");
//分頁查詢資訊
int pageNum = 2; //第幾頁
int pageSize = 2; //每頁顯示多少行
int start = (pageNum - 1) * pageSize; //起始顯示的下標
RowBounds rowBounds = new RowBounds(start, pageSize);
/**
* selectByExampleAndRowBounds:帶條件的分頁查詢
*/
List<User> users = userDao.selectByExampleAndRowBounds(example, rowBounds);
for (User user : users) {
System.out.println("========> " + user);
}
/**
* selectCountByExample:根據條件查詢總記錄數
*/
int count = userDao.selectCountByExample(example);
System.out.println("========> count = " + count);
}
}
說明:所有的關聯/多表查詢都可以由多個單表查詢組成
關聯/多表查詢實現方式:
方式一:多次使用單表查詢,然後封裝資料
方式二:自定義查詢方法和 SQL
情景:基於以上的使用者表,新新增一個訂單表 orders,訂單表中有訂單資訊,但是也有使用者 id;
要求:在查詢使用者表的同時還要查詢出使用者的訂單資訊,這就涉及到了兩張表的查詢。
具體業務要求:根據使用者名稱查詢使用者的所有資訊,包括訂單資訊。
新建訂單表 orders:
DROP TABLE IF EXISTS `orders`;
CREATE TABLE `orders` (
`order_id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`receiver_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`receiver_mobile` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`receiver_address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
PRIMARY KEY (`order_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Compact;
INSERT INTO `orders` VALUES (1, 1, 'luis', '13344445555', '湖北武漢');
新建實體類 Order:
@Data
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "orders")
public class Order {
@Id
private Integer orderId;
private Integer userId;
private String receiverName;
private String receiverMobile;
private String receiverAddress;
}
新建 dao 介面:
注意,此處 dao 介面繼承的是自定義的通用介面模板,相關說明參見之前建立範例 UserDao 的步驟。
也可以直接繼承 tkMapper 的兩個介面。(注意靈活運用!)
public interface OrderDao extends GeneralDao<Order> {
}
說明:進行關聯/多表查詢前,需要修改下之前的 User 實體類,在實體類中需要新增一個訂單的欄位,以便查詢出使用者所關聯的訂單資訊。
@Data
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "users") //資料庫表名和實體類類名不一致需要指定對映關係!
public class User {
@Id //指定主鍵
private Integer userId;
private String userName;
private String userPwd;
private String userRealname;
private String userImg;
//訂單
private List<Order> orderList;
}
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringbootTkMapperDemoApplication.class) //啟動類.class
public class UserDaoTest {
@Autowired
private UserDao userDao; //如果爆紅線不用管(或Dao介面上新增@Repository註解)
@Autowired
private OrderDao orderDao;
@Test
public void test() {
//根據使用者名稱查詢使用者資訊
Example example = new Example(User.class);
Example.Criteria criteria = example.createCriteria();
criteria.andEqualTo("userName", "luis");
//條件查詢
List<User> users = userDao.selectByExample(example);
User user = users.get(0);
//根據使用者id查詢訂單資訊
Example example1 = new Example(Order.class);
Example.Criteria criteria1 = example.createCriteria();
criteria.andEqualTo("userId", user.getUserId());
//條件查詢
List<Order> orders = orderDao.selectByExample(example1);
//將查詢到的訂單資訊設定到user中
user.setOrderList(orders);
System.out.println("========> " + user);
}
}
UserDao 介面中新建查詢方法
public interface UserDao extends GeneralDao<User> {
public User selectByUserName(String userName);
}
mappers 目錄下建立對應的 UserMapper.xml 檔案,自定義查詢 SQL
<?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.luis.dao.UserDao">
<resultMap id="userMap" type="com.luis.beans.User">
<id column="user_id" property="userId"/>
<result column="user_name" property="userName"/>
<result column="user_pwd" property="userPwd"/>
<result column="user_realname" property="userRealname"/>
<result column="user_img" property="userImg"/>
<collection property="orderList" ofType="com.luis.beans.Order">
<id column="order_id" property="orderId"/>
<result column="user_id" property="userId"/>
<result column="receiver_name" property="receiverName"/>
<result column="receiver_mobile" property="receiverMobile"/>
<result column="receiver_address" property="receiverAddress"/>
</collection>
</resultMap>
<select id="selectByUserName" resultMap="userMap">
select u.user_id,u.user_name,u.user_pwd,u.user_realname,u.user_img,
o.order_id,o.user_id,o.receiver_name,o.receiver_mobile,o.receiver_address
from users u inner join orders o
on u.user_id = o.user_id;
</select>
</mapper>
測試
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringbootTkMapperDemoApplication.class) //啟動類.class
public class UserDaoTest {
@Autowired
private UserDao userDao; //如果爆紅線不用管(或Dao介面上新增@Repository註解)
@Autowired
private OrderDao orderDao;
@Test
public void test02() {
//使用自定義的查詢方法
User user = userDao.selectByUserName("luis");
System.out.println("========> " + user);
}
}
所謂逆向工程,就是通過資料庫表,來自動生成實體類、dao 介面和 mapper 檔案。
需要注意的是,本逆向工程是最好配合 tkMapper 環境使用,因為,有一些設定和 tkMapper 相關,如生成的 dao 介面會繼承自定義的通用介面模板,而該通用的介面模板就是繼承了 tkMapper 中的兩個介面,從而才能使用 tkMapper 提供的通用資料操作方法;還有,生成的實體類上的註解需要依賴 tkMapper 環境。
重要說明:本逆向工程使用的 mysql 版本是低版本 5.1.36!經測試,如果使用高版本如 8.xxx,很大概率會生成有問題!所以建議專案中統一使用低版本的 MySQL。
在 pom.xml 中 build 的 plugins 下新增下列生成器外掛
<!-- mybatis-generator-maven-plugin -->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.6</version>
<!-- 生成器組態檔位置;如果還沒有新增,可以先註釋,新增後再放開 -->
<configuration>
<configurationFile>
${basedir}/src/main/resources/generator/GeneratorConfig.xml
</configurationFile>
</configuration>
<!-- 外掛所需的兩個依賴 -->
<dependencies>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.36</version>
</dependency>
<!-- mapper -->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper</artifactId>
<version>4.1.5</version>
</dependency>
</dependencies>
</plugin>
注意:推薦直接複製,但如果想自己在 maven 倉庫中搜尋,注意關鍵詞:mybatis-generator-maven-plugin
,並且,千萬注意,你搜尋到的肯定是依賴,而並非外掛!此時,你只需要複製依賴的 gav 座標,自己在 pom 中建立空 plugin 標籤,將 gav 座標複製進去即可!(如果相關依賴重新整理新增失敗,可以複製到 dependences 下,重新重新整理新增試試,新增成功後複製回來即可)
注意檢視專案中是否自定義有通用介面模板 GeneralDao,使其繼承 tkMapper 的兩個介面;如果沒有,則在 dao 同級目錄,建立 general 目錄,在 general 目錄下建立自定義通用介面模板 GeneralDao,繼承 tkMapper 的兩個介面;
public interface GeneralDao<T> extends Mapper<T>, MySqlMapper<T> {
}
在 resources/generator
下新增 GeneratorConfig.xml
生成器設定(建立並複製後改主要設定即可)
主要需要設定:設定資料庫連線、設定實體類存放路徑、設定 XML 存放路徑、設定 DAO 存放路徑、設定 GeneralDao
注意:預設設定是生成指定資料庫中所有表,也可以自定義的指定只生成哪些表
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!-- 引入資料庫連線設定 -->
<!-- <properties resource="jdbc.properties"/>-->
<context id="Mysql" targetRuntime="MyBatis3Simple" defaultModelType="flat">
<property name="beginningDelimiter" value="`"/>
<property name="endingDelimiter" value="`"/>
<!-- 設定 GeneralDao -->
<plugin type="tk.mybatis.mapper.generator.MapperPlugin">
<property name="mappers" value="com.luis.general.GeneralDao"/>
</plugin>
<!-- 設定資料庫連線(注意資料庫版本問題,需要使用低版本的,高版本可能出現問題!) -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/springdb?serverTimezone=UTC"
userId="root" password="luis">
</jdbcConnection>
<!-- 設定實體類存放路徑 -->
<javaModelGenerator targetPackage="com.luis.beans" targetProject="src/main/java"/>
<!-- 設定 XML 存放路徑 -->
<sqlMapGenerator targetPackage="/" targetProject="src/main/resources/mappers"/>
<!-- 設定 Dao 存放路徑 -->
<javaClientGenerator targetPackage="com.luis.dao" targetProject="src/main/java" type="XMLMAPPER"/>
<!-- 設定需要指定生成的資料庫和表,% 代表所有表 -->
<table tableName="%">
<!-- mysql 設定 -->
<!-- <generatedKey column="id" sqlStatement="Mysql" identity="true"/>-->
</table>
<!-- <table tableName="tb_roles">-->
<!-- <!– mysql 設定 –>-->
<!-- <generatedKey column="roleid" sqlStatement="Mysql" identity="true"/>-->
<!-- </table>-->
<!-- <table tableName="tb_permissions">-->
<!-- <!– mysql 設定 –>-->
<!-- <generatedKey column="perid" sqlStatement="Mysql" identity="true"/>-->
<!-- </table>-->
</context>
</generatorConfiguration>
開啟 IDEA 右側 Maven 視窗,找到專案--》Plugins--》mybatis-generator--》mybatis-generator:generate,雙擊執行逆向生成即可!
範例圖:
檢視 beans、dao、mappers 目錄下的生成情況,看生成的相關介面是否符合開發要求,根據情況可做相關修改,然後進行相關測試。
都看到最後了,右下角來個贊鴨!-.- 歡迎評論留言~