mybatis
-
入门
-
XML配置
-
properties(属性)
-
settings(设置)
-
mapUnderscoreToCamelCase 驼峰命名
-
-
typeAliases(类型别名)
-
typeHandlers(类型处理器)
-
objectFactory(对象工厂)
-
plugins(插件)
-
environments(环境配置)
-
databaseIdProvider(数据库厂商标识)
-
mappers(映射器)
-
入门
1 引入配置文件创建SqlSessionFactory
mybatis-config1.xml是mybatis的核心配置文件,用来配置mybatis系统参数,数据库参数,缓存,另外还需要引入具体的mapper文件。mapper1.xml是mybatis写sql的文件,mapper文件必须有唯一的namespace
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?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> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/petstore?serverTimezone=GMT%2B8&characterEncoding=utf8&useUnicode=true&useSSL=false"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> <mappers> <mapper resource="primerConfig/mapper1.xml"/> </mappers> </configuration>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?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="config1"> <select id="selectManageUserName" resultType="string"> select username from manage_user where id = #{id} </select> </mapper>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
@Test//引入配置文件 public void t1() throws Exception { String resource = "primerConfig/mybatis-config1.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession sqlSession = sqlSessionFactory.openSession(); String name = (String) sqlSession.selectOne("config1.selectManageUserName", "1"); sqlSession.close(); }
2 不引入配置文件创建SqlSessionFactory
不引入mybatis配置文件,需要Configuration类,相当于mybatisconfig中的<configuation>标签。另外mapper文件也不存在了,则由注解代替
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package primer;/* * @auther 顶风少年 * @mail dfsn19970313@foxmail.com * @date 2019-12-26 10:39 * @notify * @version 1.0 */ import org.apache.ibatis.annotations.Select; public interface PrimerMapper { @Select("select username from manage_user where id = #{id}") String selectManageUserName(int id); }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package primer;/* * @auther 顶风少年 * @mail dfsn19970313@foxmail.com * @date 2019-12-26 10:39 * @notify * @version 1.0 */ import org.apache.ibatis.annotations.Select; public interface PrimerMapper2 { @Select("select username from manage_user where id = #{id}") String selectManageUserName2(int id); }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
@Test//不引入配置文件创建SqlSessionFactory public void t2() { //连接池对象 PooledDataSourceFactory pooledDataSourceFactory = new PooledDataSourceFactory(); //数据源参数 Properties properties = new Properties(); properties.put("driver", "com.mysql.jdbc.Driver"); properties.put("url", "jdbc:mysql://localhost:3306/petstore?serverTimezone=GMT%2B8&characterEncoding=utf8&useUnicode=true&useSSL=false"); properties.put("username", "root"); properties.put("password", "root"); pooledDataSourceFactory.setProperties(properties); //获取数据源 DataSource dataSource = pooledDataSourceFactory.getDataSource(); //设置事务管理器 TransactionFactory transactionFactory = new JdbcTransactionFactory(); //创建上下文环境 Environment environment = new Environment("development", transactionFactory, dataSource); //组装配置 Configuration configuration = new Configuration(environment); //添加mapper configuration.addMapper(PrimerMapper.class); configuration.addMapper(PrimerMapper2.class); //获取sqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration); //打开链接 SqlSession sqlSession = sqlSessionFactory.openSession(); //方式1 String selectManageUserName = (String) sqlSession.selectOne("selectManageUserName", 1); String selectManageUserName2 = (String) sqlSession.selectOne("selectManageUserName2", 1); //方式2 PrimerMapper mapper = sqlSession.getMapper(PrimerMapper.class); String s = mapper.selectManageUserName(1); sqlSession.close(); }
XML配置
1 properties(属性)
标签properties用于设置mybatis全局配置参数。内部定义property属性,或者引入外部文件,给mybatis注入属性,mybatis其他配置地方可使用${}引用参数。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?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> <property name="jdbc.driver" value="com.mysql.jdbc.Driver"/> <property name="jdbc.url" value="jdbc:mysql://localhost:3306/petstore?serverTimezone=GMT%2B8&characterEncoding=utf8&useUnicode=true&useSSL=false"/> <property name="jdbc.username" value="root"/> <property name="jdbc.password" value="root"/> </properties> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username-root}"/> <property name="password" value="${jdbc.password}"/> </dataSource> </environment> </environments> <mappers> <mapper resource="configuration-properties/mapper1.xml"/> </mappers> </configuration>
以上配置为内部配置property属性,我们也可以引入外部的配置文件。properties使用resource属性或者url属性。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/petstore?serverTimezone=GMT%2B8&characterEncoding=utf8&useUnicode=true&useSSL=false jdbc.username=root jdbc.password=root test.a=123 test.b=456
属性注入的顺序是,先使用<property>属性值,在使用resource覆盖,最终直接写入属性值覆盖。最终生效的则是相反。
不管是<property>注入的属性还是外部文件,最终mybatis都将其封装到sqlSessionFactory->configuration->variables中。另外当我们使用${}时,如果没有映射到对应的key,也可以设置默认值。但我们需要先开启默认值。
删除<property>和外部配置文件的jdbc.password使其不存在。发现现在注入的值为${jdbc.password}字面量字符串。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?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 resource="configuration-properties/db.properties"> <!-- 启用默认值特性 --> <property name="org.apache.ibatis.parsing.PropertyParser.enable-default-value" value="true"/> <property name="test.c" value="678"/> <property name="jdbc.driver" value="com.mysql.jdbc.Driver"/> <property name="jdbc.url" value="jdbc:mysql://localhost:3306/petstore?serverTimezone=GMT%2B8&characterEncoding=utf8&useUnicode=true&useSSL=false"/> <property name="jdbc.username" value="root"/> </properties> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password:root}"/> </dataSource> </environment> </environments> <mappers> <mapper resource="configuration-properties/mapper1.xml"/> </mappers> </configuration>
开启默认值,并设置默认值。默认值的使用方式是使用 value="${jdbc.password:root}"如果变量不存在,则使用:后的字符串默认值。
如果:符号已经被占用,我们还可以自定义分割符号。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?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 resource="configuration-properties/db.properties"> <!-- 启用默认值特性 --> <property name="org.apache.ibatis.parsing.PropertyParser.enable-default-value" value="true"/> <!-- 修改默认值的分隔符 默认的 : 和 ?: --> <property name="org.apache.ibatis.parsing.PropertyParser.default-value-separator" value="-"/> <property name="test.c" value="678"/> <property name="jdbc.driver" value="com.mysql.jdbc.Driver"/> <property name="jdbc.url" value="jdbc:mysql://localhost:3306/petstore?serverTimezone=GMT%2B8&characterEncoding=utf8&useUnicode=true&useSSL=false"/> <property name="jdbc.username" value="root"/> </properties> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password-root}"/> </dataSource> </environment> </environments> <mappers> <mapper resource="configuration-properties/mapper1.xml"/> </mappers> </configuration>
2 settings(设置)
2.1 mapUnderscoreToCamelCase 驼峰命名
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?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> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/petstore?serverTimezone=GMT%2B8&characterEncoding=utf8&useUnicode=true&useSSL=false"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> <mappers> <mapper resource="configuration-sittings-mapUnderscoreToCamelCase/mapper1.xml"/> </mappers> </configuration>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?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="config1"> <select id="selectManageUserName" resultType="configurationSittingsMapUnderscoreToCamelCase.ManageUser"> select * from manage_user where id = #{id} </select> </mapper>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package configurationSittingsMapUnderscoreToCamelCase;/* * @auther 顶风少年 * @mail dfsn19970313@foxmail.com * @date 2019-12-27 07:35 * @notify * @version 1.0 */ import org.apache.ibatis.type.Alias; import java.util.Date; public class ManageUser { private String id; private String username; private String password; private Date createDate; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Date getCreateDate() { return createDate; } public void setCreateDate(Date createDate) { this.createDate = createDate; } }
在数据库中字段create_date映射pojo属性createDate是不行的。此时我们开启自动驼峰命名规则映射可以解决这个问题。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?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> <!-- 开启驼峰命名映射--> <settings> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/petstore?serverTimezone=GMT%2B8&characterEncoding=utf8&useUnicode=true&useSSL=false"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> <mappers> <mapper resource="configuration-sittings-mapUnderscoreToCamelCase/mapper1.xml"/> </mappers> </configuration>
3 类型别名(typeAliases)
在写mapper文件时,必不可少的,我们要给PreparedStatement和Statement指定入参。或者结果集映射返回值。必然的我们需要指定类型。mybatis预选帮我们设置好了常用类型的别名。https://mybatis.org/mybatis-3/zh/configuration.html#typeAliases
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package configurationTypeAliases;/* * @auther 顶风少年 * @mail dfsn19970313@foxmail.com * @date 2019-12-27 07:35 * @notify * @version 1.0 */ import java.util.Date; public class ManageUser { private String id; private String username; private String password; private Date createDate; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Date getCreateDate() { return createDate; } public void setCreateDate(Date createDate) { this.createDate = createDate; } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?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> <!-- 设置别名 --> <typeAliases> <typeAlias type="configurationTypeAliases.ManageUser" alias="abc"/> <!-- <package name="configurationTypeAliases"/>--> </typeAliases> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/petstore?serverTimezone=GMT%2B8&characterEncoding=utf8&useUnicode=true&useSSL=false"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> <mappers> <mapper resource="configuration-typeAliases/mapper1.xml"/> </mappers> </configuration>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?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="config1"> <!-- 入参使用别名 --> <select id="selectManageUserName" resultType="string" parameterType="abc"> select username from manage_user where id = #{id} </select> </mapper>
扫描包别名,通常的单个指定别名会比较麻烦,所以我们可以扫描包路径,生成别名。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?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> <!-- 设置别名 --> <typeAliases> <!-- <typeAlias type="configurationTypeAliases.ManageUser" alias="abc"/>--> <package name="configurationTypeAliases"/> </typeAliases> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/petstore?serverTimezone=GMT%2B8&characterEncoding=utf8&useUnicode=true&useSSL=false"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> <mappers> <mapper resource="configuration-typeAliases/mapper1.xml"/> </mappers> </configuration>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?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="config1"> <!-- 入参使用别名 --> <select id="selectManageUserName" resultType="string" parameterType="manaGeuser"> select username from manage_user where id = #{id} </select> </mapper>
使用包扫描不限制类名大小写。同样我们可以强制要求pojo类的别名。使用@Alias注解
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package configurationTypeAliases;/* * @auther 顶风少年 * @mail dfsn19970313@foxmail.com * @date 2019-12-27 07:35 * @notify * @version 1.0 */ import org.apache.ibatis.type.Alias; import java.util.Date; @Alias(value = "def") public class ManageUser { private String id; private String username; private String password; private Date createDate; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Date getCreateDate() { return createDate; } public void setCreateDate(Date createDate) { this.createDate = createDate; } }
一个类可以有多个别名,我们可以在sqlSessionFactory->configuration->typeAliasRegistry->TYPE_ALIASES下寻找定义的别名。其中已经有mybatis预定义的别名。
4 类型转换器(typeHandlers)
无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时, 都会用类型处理器将获取的值以合适的方式转换成 Java 类型。就是说,在mapper中,我们的Statement入参和返回值都需要经过类型转换器,入参从java类型转成jdbc类型,返回值从jdbc类型转换成java类型。mybatis已经定义了大部分常用的类型转换器。https://mybatis.org/mybatis-3/zh/configuration.html#typeHandlers 下边我们自定义一个String类型转换器,覆盖mybatis定义的转换器。给入参字符串自动拼接,和返回值自动拼接。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package configurationTypeHandlers;/* * @auther 顶风少年 * @mail dfsn19970313@foxmail.com * @date 2019-12-30 08:17 * @notify * @version 1.0 */ import org.apache.ibatis.type.BaseTypeHandler; import org.apache.ibatis.type.JdbcType; import org.apache.ibatis.type.MappedJdbcTypes; import org.apache.ibatis.type.MappedTypes; import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @MappedJdbcTypes(value = {JdbcType.VARCHAR,JdbcType.CHAR},includeNullJdbcType = true) @MappedTypes(value = String.class) public class ExampleTypeHandler extends BaseTypeHandler<String> { public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException { System.out.println(parameter); ps.setString(i, parameter+"d"); } public String getNullableResult(ResultSet rs, String columnName) throws SQLException { System.out.println("columnName"); return rs.getString(columnName)+"---"; } public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException { System.out.println("columnIndex"); return rs.getString(columnIndex)+"|||"; } public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { System.out.println("CallableStatement"); return cs.getString(columnIndex)+"%%%"; } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?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="config1"> <select id="selectManageUserName" resultType="string"> select username from manage_user where username = #{username} </select> </mapper>
继承BaseTypeHandler类,set()方法是入参,get()是返回值。上边代码片段,我们试图将String和varchar char 互相转换。在ExampleTypeHandler上使用@MappedJdbcTypes和@MappedTypes指定要转换的类型。注意如果需要set()生效则需要在@MappedTypes使用includeNullJdbcType=true。然后在mybatis全局配置文件使用这个自定义类型转换器。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?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> <typeHandlers> <typeHandler handler="configurationTypeHandlers.ExampleTypeHandler"/> </typeHandlers> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/petstore?serverTimezone=GMT%2B8&characterEncoding=utf8&useUnicode=true&useSSL=false"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> <mappers> <mapper resource="configuration-typeHandlers/mapper1.xml"/> </mappers> </configuration>
<typeHandler/>有属性jdbcType和javaType会覆盖ExampleTypeHandler类上的@MappedJdbcTypes和@MappedTypes
5 对象工厂(ObjectFactory)
Statement返回结果集为pojo时,mybatis会帮我们实例化pojo对象。默认的会调用DefaultObjectFactory,我们可以继承此类,然后对返回pojo进行改造。setProperties()方法将<objectFactory/>中的<property/>属性映射到参数中,我们可将其设置为成员变量,在create()方法中使用。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package configurationObjectFactory;/* * @auther 顶风少年 * @mail dfsn19970313@foxmail.com * @date 2019-12-27 07:35 * @notify * @version 1.0 */ import java.util.Date; public class ObjectFactoryManageUser { private String id; private String username; private String password; private Date createDate; private String prp; public ObjectFactoryManageUser() { } public void setPrp(String prp) { this.prp = prp; } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?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> <objectFactory type="configurationObjectFactory.ExampleObjectFactory"> <property name="prp" value="AAA"/> </objectFactory> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/petstore?serverTimezone=GMT%2B8&characterEncoding=utf8&useUnicode=true&useSSL=false"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> <mappers> <mapper resource="configuration-ObjectFactory/mapper1.xml"/> </mappers> </configuration>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package configurationObjectFactory;/* * @auther 顶风少年 * @mail dfsn19970313@foxmail.com * @date 2019-12-30 10:47 * @notify * @version 1.0 */ import org.apache.ibatis.reflection.factory.DefaultObjectFactory; import java.util.List; import java.util.Properties; public class ExampleObjectFactory extends DefaultObjectFactory { Properties properties = new Properties(); @Override public <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs){ T ret = super.create(type,constructorArgTypes,constructorArgs); if(ObjectFactoryManageUser.class.isAssignableFrom(type)){ ObjectFactoryManageUser objectFactoryManageUser =(ObjectFactoryManageUser) ret; objectFactoryManageUser.setPrp((String) properties.get("prp")); } return ret; } @Override public void setProperties(Properties properties) { this.properties = properties; } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?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="config1"> <select id="selectManageUserName" resultType="configurationObjectFactory.ObjectFactoryManageUser"> select * from manage_user where id = #{id} </select> </mapper>
6 插件(plugins)
MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用。如果你想做的不仅仅是监控方法的调用,那么你最好相当了解要重写的方法的行为。 因为如果在试图修改或重写已有方法的行为的时候,你很可能在破坏 MyBatis 的核心模块。 这些都是更低层的类和方法,所以使用插件的时候要特别当心。以下代码片段是对返回值拦截。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package configurationPlugins;/* * @auther 顶风少年 * @mail dfsn19970313@foxmail.com * @date 2019-12-30 16:28 * @notify * @version 1.0 */ import org.apache.ibatis.executor.Executor; import org.apache.ibatis.executor.resultset.ResultSetHandler; import org.apache.ibatis.executor.statement.StatementHandler; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.plugin.*; import org.apache.ibatis.session.ResultHandler; import org.apache.ibatis.session.RowBounds; import java.sql.Statement; import java.util.Properties; /* 注解接收数组,类型为@Signature 而@Signature三个参数分别是,要拦截的类,要拦截的方法,方法参数。 注意可拦截的类和方法为 //执行sql Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed) //获取、设置参数 ParameterHandler (getParameterObject, setParameters) //处理结果集 ResultSetHandler (handleResultSets, handleOutputParameters) //记录sql StatementHandler (prepare, parameterize, batch, update, query) */ @Intercepts(value = {@Signature( type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})}) public class ExamplePlugin implements Interceptor { private Properties properties = new Properties(); //拦截类 public Object intercept(Invocation invocation) throws Throwable { System.out.println(properties.getProperty("timeout")); return invocation.proceed(); } //返回当前插件 public Object plugin(Object target) { return Plugin.wrap(target, this); } //将xml配置的property绑定到成员变量上 public void setProperties(Properties properties) { this.properties = properties; } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?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> <!-- 配置插件 --> <plugins> <plugin interceptor="configurationPlugins.ExamplePlugin"> <property name="timeout" value="100"/> </plugin> </plugins> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/petstore?serverTimezone=GMT%2B8&characterEncoding=utf8&useUnicode=true&useSSL=false"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> <mappers> <mapper resource="configuration-plugins/mapper1.xml"/> </mappers> </configuration>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?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="config1"> <select id="selectManageUserName" resultType="string"> select username from manage_user where id = #{id} </select> </mapper>
7 环境配置(environments)
使用mybatis,在可能的情况下我们会有多种环境,例如测试环境,生产环境等。我们可以通过配置environment来确定使用的环境。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?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> <environments default="development2"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/petstore?serverTimezone=GMT%2B8&characterEncoding=utf8&useUnicode=true&useSSL=false"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> <environment id="development2"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/petstore?serverTimezone=GMT%2B8&characterEncoding=utf8&useUnicode=true&useSSL=false"/> <property name="username" value="root"/> <property name="password" value="root2"/> </dataSource> </environment> </environments> <mappers> <mapper resource="configuration-environments/mapper1.xml"/> </mappers> </configuration>
每个environment有唯一的id,在environment标签上使用default属性,表示要使用的是哪个environment。以上我们使用environment2,但是他的密码是错误的,所以连接失败。
另外我们还可以在创建sqlSessionFactory时,指定要使用的环境,但是这样会使default失效。
关于环境的事务管理器,数据源配置可查看 https://mybatis.org/mybatis-3/zh/configuration.html#environments
8 数据库厂商标识(databaseIdProvider)
在正式开发中,我们可能会需要配置多种数据库。不同的数据库会有不同的方言,下面我们模拟这种情况。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?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> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/petstore?serverTimezone=GMT%2B8&characterEncoding=utf8&useUnicode=true&useSSL=false"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> <databaseIdProvider type="DB_VENDOR"> <property name="SQL Server" value="sqlserver"/> <property name="DB2" value="db2"/> <property name="Oracle" value="oracle" /> <property name="MySQL" value="mysql" /> </databaseIdProvider> <mappers> <mapper resource="configuration-databaseIdProvider/mapper1.xml"/> </mappers> </configuration>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?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="config1"> <select id="selectManageUserName" resultType="string" databaseId="mysql"> select username from manage_user where id = 2 </select> <select id="selectManageUserName" resultType="string"> select username from manage_user where id = 1 </select> </mapper>
在mybatis配置文件中使用<databaseIdProvider/>标签,<property/>声明数据库名称和别名。在mapper中,可以给Statement指定数据库。可以看到,上边的代码片段,我们有两个id相同的查询语句。其中一个指定的有databaseId,mybatis会优先使用带有数据库标识的,如果发现标识不存在,或者数据库类型不匹配,才会转向使用不带标识的Statement。
9 映射器(mappers)
最终我们的目的是执行sql语句,我们在mybatis配置文件中引入mapper文件,或者mapper类。
1 使用相对于类路径的资源引用
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?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="config1"> <select id="selectManageUserName" resultType="string"> select username from manage_user where id = #{id} </select> </mapper>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?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> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/petstore?serverTimezone=GMT%2B8&characterEncoding=utf8&useUnicode=true&useSSL=false"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> <mappers> <!-- 使用相对于类路径的资源引用 --> <mapper resource="configuration-mappers/mapper1.xml"/> </mappers> </configuration>
2 使用完全限定资源定位符(URL)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?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> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/petstore?serverTimezone=GMT%2B8&characterEncoding=utf8&useUnicode=true&useSSL=false"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> <mappers> <!-- 使用相对于类路径的资源引用 --> <!-- <mapper resource="configuration-mappers/mapper1.xml"/>--> <!-- 使用完全限定资源定位符(URL)--> <mapper url="file:\\\c:\workspace\mybatis\src\main\resources\configuration-mappers\mapper1.xml"/> </mappers> </configuration>
3 使用映射器接口实现类的完全限定类名,引入mapper接口
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package configurationMappers;/* * @auther 顶风少年 * @mail dfsn19970313@foxmail.com * @date 2019-12-26 10:39 * @notify * @version 1.0 */ import org.apache.ibatis.annotations.Select; public interface PrimerMapper { @Select("select username from manage_user where id = #{id}") String selectManageUserName(int id); }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?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> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/petstore?serverTimezone=GMT%2B8&characterEncoding=utf8&useUnicode=true&useSSL=false"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> <mappers> <!-- 使用相对于类路径的资源引用 --> <!-- <mapper resource="configuration-mappers/mapper1.xml"/>--> <!-- 使用完全限定资源定位符(URL)--> <!-- <mapper url="file:\\\c:\workspace\mybatis\src\main\resources\configuration-mappers\mapper1.xml"/>--> <!-- 使用映射器接口实现类的完全限定类名--> <mapper class="configurationMappers.PrimerMapper"/> </mappers> </configuration>
4 将包内的映射器接口实现全部注册为映射器
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?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> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/petstore?serverTimezone=GMT%2B8&characterEncoding=utf8&useUnicode=true&useSSL=false"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> <mappers> <!-- 使用相对于类路径的资源引用 --> <!-- <mapper resource="configuration-mappers/mapper1.xml"/>--> <!-- 使用完全限定资源定位符(URL)--> <!-- <mapper url="file:\\\c:\workspace\mybatis\src\main\resources\configuration-mappers\mapper1.xml"/>--> <!-- 使用映射器接口实现类的完全限定类名--> <!-- <mapper class="configurationMappers.PrimerMapper"/>--> <!-- 将包内的映射器接口实现全部注册为映射器 --> <package name="configurationMappers"/> </mappers> </configuration>