基本
第一步:創建一個Maven項目:
- 添加依賴:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.11</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.7</version>
</dependency>
- 在build標籤下添加
<plugins>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.4.0</version>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.11</version>
</dependency>
</dependencies>
<configuration>
<configurationFile>
${basedir}/src/main/resources/genCfg.xml
<!--這裏是配置generatorConfig.xml的路徑 該文件默認在resources目錄下找generatorConfig.xml文件 -->
</configurationFile>
<!--允許移動生成的文件 -->
<verbose>true</verbose>
<!--允許覆蓋生成的文件 -->
<overwrite>true</overwrite>
</configuration>
</plugin>
</plugins>
<!-- 指定Mapper XML文件在mybatis-config.xml中的配置有效-->
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
第二步:在resources目錄中創建屬性文件mysql.properties:
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://127.0.0.1/test?useSSL=false&serverTimezone=CST
username=root
password=root
第三步:在resources目錄下建立 genCfg.xml,作爲mybatis-generator-maven-plugin 插件執行的配置文件:
<?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 url="file:///E:\Workspaces\MyBatis\MybatisGeneratorDemo\src\main\resources\mysql.properties"/>
<context id="default" targetRuntime="MyBatis3">
<!-- 自動識別數據庫關鍵字,默認false。如果設置爲true,根據SqlReservedWords中定義的關鍵字列表;一般保留默認值,遇到數據庫關鍵字(Java關鍵字),使用columnOverride覆蓋 -->
<property name="autoDelimitKeywords" value="false"/>
<!-- 生成的Java文件的編碼-->
<property name="javaFileEncoding" value="UTF-8"/>
<!-- 格式化java代碼-->
<property name="javaFormatter" value="org.mybatis.generator.api.dom.DefaultJavaFormatter"/>
<!-- 格式化XML代碼-->
<property name="xmlFormatter" value="org.mybatis.generator.api.dom.DefaultXmlFormatter"/>
<!--beginningDelimiter和endingDelimiter:指明數據庫的用於標記數據庫對象名的符號,比如ORACLE就是雙引號,MYSQL默認是`反引號; -->
<property name="beginningDelimiter" value="`"/>
<property name="endingDelimiter" value="`"/>
<plugin type="org.mybatis.generator.plugins.SerializablePlugin"/>
<plugin type="org.mybatis.generator.plugins.EqualsHashCodePlugin"/>
<plugin type="org.mybatis.generator.plugins.ToStringPlugin"/>
<!-- ② -->
<commentGenerator > <!-- ③ -->
<property name="suppressDate" value="true"/>
<!-- 是否去除自動生成的註釋 true:是 : false:否 -->
<property name="suppressAllComments" value="false"/>
<property name="addRemarkComments" value="true"/>
</commentGenerator>
<!--數據庫鏈接URL,用戶名、密碼 -->
<jdbcConnection driverClass="${driver}" connectionURL="${url}"
userId="${username}" password="${password}">
<!-- property屬性會設置到配置的Driver上-->
<property name="useInformationSchema" value="true"/><!-- 針對mysql數據庫 -->
</jdbcConnection>
<!-- 非必需,類型處理器,在數據庫類型和java類型之間的轉換控制-->
<javaTypeResolver>
<property name="forceBigDecimals" value="false"/>
</javaTypeResolver>
<!-- 生成實體類-->
<javaModelGenerator targetPackage="com.hc.bean" targetProject="src/main/java">
<!-- 是否生成構造方法 -->
<property name="constructorBased" value="false"/>
<!-- 是否允許子包 -->
<property name="enableSubPackages" value="false"/>
<!-- 如果爲true,則創建一個沒有setter只有構造方法的類 -->
<property name="immutable" value="false"/>
<!-- 設置是否在getter方法中,對String類型字段調用trim()方法 -->
<property name="trimStrings" value="true"/>
</javaModelGenerator>
<!-- 生成映射文件-->
<sqlMapGenerator targetPackage="com.hc.dao.mapping" targetProject="src/main/java">
<!-- 允許子包 -->
<property name="enableSubPackages" value="true"/>
</sqlMapGenerator>
<!-- 生成DAO類-->
<javaClientGenerator type="XMLMAPPER" targetPackage="com.hc.dao" targetProject="src/main/java">
<!-- 允許子包 -->
<property name="enableSubPackages" value="true"/>
</javaClientGenerator>
<!-- 要生成的表 tableName是數據庫中的表名或視圖名 domainObjectName是實體類名-->
<table tableName="tb_emp" domainObjectName="Emp" mapperName="EmpDao"
enableCountByExample="false" enableUpdateByExample="false"
enableDeleteByExample="false" enableSelectByExample="false"
selectByExampleQueryId="false" enableSelectByPrimaryKey="true"
enableUpdateByPrimaryKey="true" enableDeleteByPrimaryKey="true">
</table>
<table tableName="tb_dept" domainObjectName="Dept" mapperName="DeptDao"
enableCountByExample="false" enableUpdateByExample="false"
enableDeleteByExample="false" enableSelectByExample="false"
selectByExampleQueryId="false" enableSelectByPrimaryKey="true"
enableUpdateByPrimaryKey="true" enableDeleteByPrimaryKey="true">
</table>
</context>
</generatorConfiguration>
說明: 如果想要生成數據庫下面所有的表:
<table tableName="%" enableCountByExample="false"
enableUpdateByExample="false" enableDeleteByExample="false"
enableSelectByExample="false" selectByExampleQueryId="false"/>
第四步:採用圖形化的方式利用MBG產生代碼
依次點擊Maven Project—項目——Plugins——mybatis generator——Run Maven build,如下圖所示:
改進
自定義代碼生成器程序執行入口
MBG採用圖形化生成時會出現莫名其妙的問題,比如如果數據庫中的表的名字爲tb_admin時會會生成一堆莫名其妙的代碼,所以建議通過程序生成代碼而不是通過採用圖形化的方式。在項目中按如下所示的代碼創建程序執行入口類:
public class MBGGenerator {
public static void main( String[] args ) throws Exception {
List<String> warnings = new ArrayList<>();
String path = Generator.class.getResource("/").getPath();
File configFile = new File(path+"genCfg.xml");
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration cfg = cp.parseConfiguration(configFile);
DefaultShellCallback callback = new DefaultShellCallback(true);
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(cfg, callback, warnings);
myBatisGenerator.generate(null);
}
}
生成正確的代碼註釋
查看生成代碼中的實體類,發現儘管數據庫中表及字段都有註釋,但生成的實體類中出現了一大堆莫名其妙的英文信息。要想生成正確的代碼註釋:
第一步:按如下所示在com.hc.gen包下提供註釋工具類
public class BeanCommentsGen implements CommentGenerator {
private Properties properties;
private Properties systemPro;
private boolean suppressDate;
private boolean suppressAllComments;
private String currentDateStr;
public BeanCommentsGen() {
properties = new Properties();
}
@Override
public void addConfigurationProperties(Properties properties) {
// 獲取自定義的 properties
this.properties.putAll(properties);
}
@Override
public void addModelClassComment(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
String author = properties.getProperty("author");
String dateFormat = properties.getProperty("dateFormat", "yyyy-MM-dd");
SimpleDateFormat dateFormatter = new SimpleDateFormat(dateFormat);
// 獲取表註釋
String remarks = introspectedTable.getRemarks();
topLevelClass.addJavaDocLine("/**");
topLevelClass.addJavaDocLine(" * " + remarks);
topLevelClass.addJavaDocLine(" *");
topLevelClass.addJavaDocLine(" * @author " + author);
topLevelClass.addJavaDocLine(" * @date " + dateFormatter.format(new Date()));
topLevelClass.addJavaDocLine(" */");
}
@Override
public void addFieldComment(Field field, IntrospectedTable introspectedTable, IntrospectedColumn introspectedColumn) {
// 獲取列註釋
String remarks = introspectedColumn.getRemarks();
field.addJavaDocLine("/**");
field.addJavaDocLine(" * " + remarks);
field.addJavaDocLine(" */");
}
@Override
public void addFieldComment(Field field, IntrospectedTable introspectedTable) {
if (suppressAllComments) {
return;
}
StringBuilder sb = new StringBuilder();
field.addJavaDocLine("/**");
sb.append(" * ");
sb.append(introspectedTable.getFullyQualifiedTable());
field.addJavaDocLine(sb.toString().replace("\n", " "));
field.addJavaDocLine(" */");
}
@Override
public void addClassComment(InnerClass innerClass, IntrospectedTable introspectedTable) {
if (suppressAllComments) {
return;
}
StringBuilder sb = new StringBuilder();
innerClass.addJavaDocLine("/**");
sb.append(" * ");
sb.append(introspectedTable.getFullyQualifiedTable());
innerClass.addJavaDocLine(sb.toString());
sb.setLength(0);
sb.append(" * @author ");
sb.append(systemPro.getProperty("user.name"));
sb.append(" ");
sb.append(currentDateStr);
// addJavadocTag(innerClass, markAsDoNotDelete);
innerClass.addJavaDocLine(" */");
}
@Override
public void addClassComment(InnerClass innerClass, IntrospectedTable introspectedTable, boolean markAsDoNotDelete) {
}
@Override
public void addEnumComment(InnerEnum innerEnum, IntrospectedTable introspectedTable) {
}
@Override
public void addGetterComment(Method method, IntrospectedTable introspectedTable,
IntrospectedColumn introspectedColumn) {
if (suppressAllComments) {
return;
}
method.addJavaDocLine("/**");
StringBuilder sb = new StringBuilder();
sb.append(" * 獲取");
sb.append(introspectedColumn.getRemarks());
method.addJavaDocLine(sb.toString());
sb.setLength(0);
sb.append(" * @return ");
sb.append(introspectedColumn.getRemarks());
method.addJavaDocLine(sb.toString());
// addJavadocTag(method, false);
method.addJavaDocLine(" */");
}
@Override
public void addSetterComment(Method method, IntrospectedTable introspectedTable,
IntrospectedColumn introspectedColumn) {
if (suppressAllComments) {
return;
}
method.addJavaDocLine("/**");
StringBuilder sb = new StringBuilder();
sb.append(" * 設置");
sb.append(introspectedColumn.getRemarks());
method.addJavaDocLine(sb.toString());
Parameter parm = method.getParameters().get(0);
sb.setLength(0);
sb.append(" * @param ");
sb.append(parm.getName());
sb.append(" ");
sb.append(introspectedColumn.getRemarks());
method.addJavaDocLine(sb.toString());
// addJavadocTag(method, false);
method.addJavaDocLine(" */");
}
@Override
public void addGeneralMethodComment(Method method, IntrospectedTable introspectedTable) {
}
@Override
public void addJavaFileComment(CompilationUnit compilationUnit) {
}
@Override
public void addComment(XmlElement xmlElement) {
}
@Override
public void addRootComment(XmlElement rootElement) {
}
@Override
public void addGeneralMethodAnnotation(Method method, IntrospectedTable introspectedTable,
Set<FullyQualifiedJavaType> imports) {
}
@Override
public void addGeneralMethodAnnotation(Method method, IntrospectedTable introspectedTable,
IntrospectedColumn introspectedColumn, Set<FullyQualifiedJavaType> imports) {
}
@Override
public void addFieldAnnotation(Field field, IntrospectedTable introspectedTable,
Set<FullyQualifiedJavaType> imports) {
}
@Override
public void addFieldAnnotation(Field field, IntrospectedTable introspectedTable,
IntrospectedColumn introspectedColumn, Set<FullyQualifiedJavaType> imports) {
}
@Override
public void addClassAnnotation(InnerClass innerClass, IntrospectedTable introspectedTable,
Set<FullyQualifiedJavaType> imports) {
}
}
第二步:將genCfg文件中編號③處的代碼替換成如下所示的內容:
<commentGenerator type="com.tiku.utils.BeanCommentsGen">
<property name="author" value="HC"/>
<property name="dateFormat" value="yyyy-MM-dd"/>
</commentGenerator>
第三步:運行MBGGenerator 程序,發現在項目中生成了實體類、DAO接口以及映射文件的代碼,如下圖所示:
查看發現生成的DAO接口以及映射文件中沒有註釋了,最重要的是實體類的註釋符合也我們要求了
生成正確的Mapper文件
自定義生成正確的代碼註釋後,又發現Mapper文件中的代碼出錯了,生成了兩次。我們採用如下步驟解決這個問題:
第一步:按如下所示在com.hc.gen包下編寫代碼:
public class OverIsMergeablePlugin extends PluginAdapter {
@Override
public boolean validate(List<String> warnings) {
return true;
}
@Override
public boolean sqlMapGenerated(GeneratedXmlFile sqlMap, IntrospectedTable it) {
try {
Field field = sqlMap.getClass().getDeclaredField("isMergeable");
field.setAccessible(true);
field.setBoolean(sqlMap, false);
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
}
第二步:在genCfg.xml文件中代碼②處添加如下代碼:
<plugin type="com.hc.gen.OverIsMergeablePlugin"/>
再次運行MBGGenerator類的main方法發現生成的DAO接口以及映射文件中和實體類都符合也我們要求了。
測試
第一步:創建MyBatis配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--引入外部properties文件 -->
<properties resource="mysql.properties"></properties>
<settings>
<!-- 打印查詢語句 -->
<setting name="logImpl" value="STDOUT_LOGGING" />
</settings>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED"> <!-- 數據源的配置,連接到數據庫 -->
<property name="driver" value="${driver}" />
<property name="url" value="${url}"/>
<property name="username" value="${username}" />
<property name="password" value="${password}" />
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/hc/dao/mapping/DeptDao.xml"/>
</mappers>
</configuration>
第二步:創建MyBatis工具類
public class MyBatisUtil {
private static String CONFIG_FILE_LOCATION = "mybatis-cfg.xml";
private static final ThreadLocal<SqlSession> threadLocal = new
ThreadLocal<SqlSession>();
private static SqlSessionFactory sessionFactory;
static {
try {
Reader reader=Resources.getResourceAsReader(CONFIG_FILE_LOCATION);
SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
sessionFactory=builder.build(reader);
} catch (Exception e) {
e.printStackTrace();
}
}
public static SqlSession getSession() {
SqlSession session = threadLocal.get();
if (session == null) {
session = (sessionFactory!=null) ? sessionFactory.openSession() : null;
threadLocal.set(session);
}
return session;
}
public static void closeSession() {
SqlSession session = threadLocal.get();
if (session != null) {
session.close();
threadLocal.set(null);
}
}
}
第三步:測試代碼
public class DeptMapperTest {
private SqlSession session;
private DeptDao mapper;
@Before
public void before(){
session = MyBatisUtil.getSession();
mapper = session.getMapper(DeptDao.class);
}
@After
public void after(){
session.commit();
}
@Test
public void deleteByPrimaryKey() {
int res = mapper.deleteByPrimaryKey((byte) 46);
System.out.println(res);
}
@Test
public void insert() {
Dept dept = new Dept((byte)1,"aa","aaaaaaaaaaa");
int res = mapper.insert(dept);
System.out.println(res);
}
@Test
public void insertSelective() {
Dept dept = new Dept();
dept.setDname("abcd");
int res = mapper.insertSelective(dept);
System.out.println(res);
}
@Test
public void selectByPrimaryKey() {
Dept dept = mapper.selectByPrimaryKey((byte) 10);
System.out.println(dept);
}
@Test
public void updateByPrimaryKeySelective() {
Dept dept = new Dept();
dept.setDeptno((byte)40);
dept.setDname("abc");
int res = mapper.updateByPrimaryKeySelective(dept);
System.out.println(res);
}
@Test
public void updateByPrimaryKey() {
// Dept dept = new Dept();
// dept.setDeptno((byte)47);
// dept.setDname("asdf");
// int res = mapper.updateByPrimaryKey(dept);
System.out.println(3/0);
}
}