mybatisplus代碼生成器:
版本匹配是個比較麻煩的問題,這是我的配置:
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.2</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId><version>3.5.2</version></dependency><dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.31</version> <!-- 推薦版本 --></dependency>
CodeGenerator:
package com.neuedu.hisweb.utils;import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import com.baomidou.mybatisplus.generator.fill.Column;
import com.baomidou.mybatisplus.annotation.FieldFill; // 引入正確的枚舉類
import org.apache.commons.lang3.StringUtils;import java.util.Collections;
import java.util.Scanner;public class CodeGenerator {private static final String URL = "jdbc:mysql://localhost:3306/his02?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true";private static final String USERNAME = "root";private static final String PASSWORD = "1";private static final String AUTHOR = "xj";private static final String PARENT_PACKAGE = "com.neuedu.hisweb";private static final String OUTPUT_DIR = System.getProperty("user.dir") + "/src/main/java";public static String scanner(String tip) {Scanner scanner = new Scanner(System.in);System.out.println("請輸入" + tip + ":");if (scanner.hasNext()) {String ipt = scanner.next();if (StringUtils.isNotBlank(ipt)) {return ipt;}}throw new MybatisPlusException("請輸入正確的" + tip + "!");}public static void main(String[] args) {// 獲取需要生成的表名String tables = scanner("表名,多個英文逗號分割");FastAutoGenerator.create(URL, USERNAME, PASSWORD).globalConfig(builder -> {builder.author(AUTHOR).outputDir(OUTPUT_DIR).fileOverride().disableOpenDir().dateType(DateType.ONLY_DATE).commentDate("yyyy-MM-dd");}).packageConfig(builder -> {builder.parent(PARENT_PACKAGE).entity("entity").service("service").serviceImpl("service.impl").mapper("mapper").controller("controller").pathInfo(Collections.singletonMap(OutputFile.xml,System.getProperty("user.dir") + "/src/main/resources/mapper"));}).strategyConfig(builder -> {builder.addInclude(tables.split(",")).entityBuilder().enableLombok().naming(NamingStrategy.underline_to_camel).columnNaming(NamingStrategy.underline_to_camel).logicDeleteColumnName("deleted").versionColumnName("version").addTableFills(new Column("create_time", FieldFill.INSERT), // 修改為正確的枚舉值new Column("update_time", FieldFill.INSERT_UPDATE) // 修改為正確的枚舉值).controllerBuilder().enableRestStyle().formatFileName("%sController").serviceBuilder().formatServiceFileName("%sService").formatServiceImplFileName("%sServiceImpl").mapperBuilder().formatMapperFileName("%sMapper").formatXmlFileName("%sMapper");}).templateEngine(new FreemarkerTemplateEngine()).execute();}
}
MyBatis-Plus 混合使用 XML 和注解配置
一、配置原則
- 優先級:XML 配置會覆蓋注解配置。
- 最佳實踐:
- 簡單的 CRUD 操作可以使用注解(如?
@Select
、@Insert
?等)。 - 復雜的 SQL 查詢(如多表關聯、動態 SQL)建議使用 XML 配置。
- 簡單的 CRUD 操作可以使用注解(如?
- XML 文件位置:默認放在?
resources/mapper
?目錄下,文件名與 Mapper 接口名對應。
二、具體配置方法
1.?基礎配置
確保?application.yml
?或?application.properties
?中正確配置 MyBatis-Plus:
# application.yml
mybatis-plus:# Mapper XML 文件路徑mapper-locations: classpath:mapper/*.xml# 實體掃描,多個package用逗號或者分號分隔type-aliases-package: com.neuedu.hisweb.entityconfiguration:# 開啟駝峰命名map-underscore-to-camel-case: true
2.?混合使用示例
Mapper 接口:
package com.neuedu.hisweb.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.neuedu.hisweb.entity.User;
import org.apache.ibatis.annotations.*;import java.util.List;public interface UserMapper extends BaseMapper<User> {// 1. 使用注解實現簡單查詢@Select("SELECT * FROM user WHERE age > #{age}")List<User> selectByAge(int age);// 2. 使用注解實現帶參數的插入@Insert("INSERT INTO user(name, age) VALUES(#{name}, #{age})")@Options(useGeneratedKeys = true, keyProperty = "id")int insertUser(User user);// 3. 使用 XML 實現復雜查詢(XML 文件中定義該方法)List<User> selectUserWithDepartment();
}
對應的 XML 文件(resources/mapper/UserMapper.xml
):
<?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.neuedu.hisweb.mapper.UserMapper"><!-- 實現 UserMapper 接口中定義的 selectUserWithDepartment 方法 --><select id="selectUserWithDepartment" resultType="com.neuedu.hisweb.entity.User">SELECT u.*, d.name as dept_name FROM user uLEFT JOIN department d ON u.dept_id = d.idWHERE u.deleted = 0</select><!-- 可以添加更多復雜 SQL -->
</mapper>
三、注意事項
- 方法名匹配:XML 文件中的?
id
?必須與 Mapper 接口中的方法名一致。 - 參數處理:
- 注解方式:使用?
@Param
?注解為參數命名。 - XML 方式:可以直接使用參數名或索引。
- 注解方式:使用?
- 沖突處理:
- 如果同一方法在 XML 和注解中都有定義,XML 配置會覆蓋注解配置。
- XML 文件路徑:
- 確保?
mapper-locations
?配置正確指向 XML 文件。 - 推薦使用?
classpath:mapper/*.xml
?或?classpath*:mapper/**/*.xml
。
- 確保?
四、動態 SQL 示例
對于復雜的動態 SQL,XML 方式更加靈活:
<select id="selectUserByCondition" resultType="com.neuedu.hisweb.entity.User">SELECT * FROM user<where><if test="name != null and name != ''">AND name LIKE CONCAT('%', #{name}, '%')</if><if test="age != null">AND age >= #{age}</if><if test="deptId != null">AND dept_id = #{deptId}</if></where>ORDER BY create_time DESC
</select>
五、常見問題
-
XML 文件未被加載:
- 檢查?
mapper-locations
?配置是否正確。 - 確保 XML 文件在?
resources
?目錄下的正確位置。
- 檢查?
-
方法找不到:
- 檢查 XML 中的?
namespace
?是否與 Mapper 接口的全限定名一致。 - 檢查方法名(
id
)是否匹配。
- 檢查 XML 中的?
-
依賴問題:
- 確保項目中包含 MyBatis-Plus 和 MyBatis 的依賴:
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.2</version> </dependency>
- 確保項目中包含 MyBatis-Plus 和 MyBatis 的依賴:
@MapperScan
?與?mapper-locations
?的功能的兼容性
@MapperScan
?負責讓 Spring 容器識別 Mapper 接口。mapper-locations
?負責讓 MyBatis-Plus 加載 XML 中的 SQL 定義。
只要兩者的路徑配置與實際文件位置一致,即可同時使用,不會產生沖突。
一、兩者的核心功能區別
-
@MapperScan("com.neuedu.hisweb.mapper")
?的作用- 掃描 Mapper 接口:告訴 Spring 容器去哪里查找 MyBatis-Plus 的 Mapper 接口(如?
PatientcostsMapper
),并將這些接口注冊為 Spring Bean。 - 必須配置:如果沒有該注解或未通過其他方式掃描 Mapper 接口,Spring 將無法識別這些接口,導致依賴注入失敗(如?
@Autowired UserMapper
?會報錯)。
- 掃描 Mapper 接口:告訴 Spring 容器去哪里查找 MyBatis-Plus 的 Mapper 接口(如?
-
mapper-locations: classpath:mapper/*.xml
?的作用- 指定 XML 映射文件路徑:告訴 MyBatis-Plus 去哪里查找 XML 格式的 SQL 映射文件(如?
PatientcostsMapper.xml
)。 - 可選配置:如果 Mapper 接口中所有方法都使用注解(如?
@Select
)定義 SQL,則無需配置;若存在 XML 定義的 SQL,則必須配置正確路徑。
- 指定 XML 映射文件路徑:告訴 MyBatis-Plus 去哪里查找 XML 格式的 SQL 映射文件(如?
二、為什么需要同時使用?
-
場景示例:
- Mapper 接口?
PatientcostsMapper
?繼承自?BaseMapper<Patientcosts>
,自動獲得 CRUD 方法(無需 XML)。 - 若該接口中定義了自定義方法(如?
selectByCondition
),且該方法的 SQL 在?PatientcostsMapper.xml
?中實現,則必須通過?mapper-locations
?配置 XML 路徑,否則 MyBatis-Plus 無法找到對應的 SQL 語句。
- Mapper 接口?
-
@MapperScan
?解決的是?Mapper 接口的注冊問題,mapper-locations
?解決的是?XML 映射文件的加載問題,兩者功能獨立,可同時使用。
三、目錄結構建議
為避免混淆,建議按以下規范組織文件:
-
Mapper 接口位置:
?src/main/java/com/neuedu/hisweb/mapper/PatientcostsMapper.java
(與?
@MapperScan("com.neuedu.hisweb.mapper")
?掃描路徑一致) -
XML 映射文件位置:
?src/main/resources/mapper/PatientcostsMapper.xml
(與?
mapper-locations: classpath:mapper/*.xml
?配置路徑一致)
四、可能的沖突場景與解決方案
1.?XML 與注解的 SQL 定義沖突
- 問題:若 Mapper 接口的某個方法同時通過注解(如?
@Select
)和 XML 定義 SQL,則?XML 配置優先級更高,會覆蓋注解中的 SQL。 - 解決方案:同一方法的 SQL 定義只能選擇一種方式(注解或 XML),避免重復定義。
2.?Mapper 接口未被掃描
- 問題:若?
@MapperScan
?掃描路徑錯誤(如寫成?@MapperScan("com.neuedu.hisweb.dao")
),則 Spring 無法找到?PatientcostsMapper
,導致啟動時報錯。 - 解決方案:確保?
@MapperScan
?的包路徑與 Mapper 接口實際路徑一致。
五、驗證配置是否生效
- 啟動應用:若控制臺無?
NoSuchBeanDefinitionException
?或?Invalid bound statement
?錯誤,說明配置正確。 - 查看日志:
- 若配置了?
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
,執行 SQL 時會打印 XML 或注解中的 SQL 語句,可驗證是否正確加載。
- 若配置了?