myBatis-03 主配置文件
myBatis主配置文件相关配置参考文档:https://mybatis.org/mybatis-3/zh/configuration.html
0、项目文件结构
1、主配置文件相关配置项目
2、相关属性介绍
2.1、属性(properties)
用来定义一些常用的属性,可以放到外部文件定义,也可以放在标记内不定义,定义的属性可以在配置文件中使用${属性名}
<!-- 引入外部属性配置文件 --> <properties resource="jdbc.Properties"> <!-- 内部额外定义的属性,这些属性都可以在配置文件中通过${属性名}使用 --> <property name="jdbc.other" value="other"/> </properties>
jdbc.Properties文件创建在src/main/resources根目录中,具体内容如下:
jdbc.driver=com.mysql.cj.jdbc.Driver jdbc.url=jdbc:mysql://47.100.229.xxx:3306/springStudy?useSSL=false&serverTimezone=UTC jdbc.username=root jdbc.password=xxx
定义的属性可以在配置文件中使用
2.2、设置(settings)
这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。
配置例子:
<!-- 全局配置参数,相关的参数参照myBatis文档 --> <settings> <!-- 是否开启缓存 --> <setting name="cacheEnabled" value="true"/> <!-- 是否开启懒加载 --> <setting name="lazyLoadingEnabled" value="true"/> </settings>
myBatis提供的相关配置项目及含义
设置名 | 描述 | 有效值 | 默认值 |
---|---|---|---|
cacheEnabled | 全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。 | true | false | true |
lazyLoadingEnabled | 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。 |
true | false | false |
aggressiveLazyLoading | 开启时,任一方法的调用都会加载该对象的所有延迟加载属性。 否则,每个延迟加载属性会按需加载(参考 lazyLoadTriggerMethods )。 |
true | false | false (在 3.4.1 及之前的版本中默认为 true) |
multipleResultSetsEnabled | 是否允许单个语句返回多结果集(需要数据库驱动支持)。 | true | false | true |
useColumnLabel | 使用列标签代替列名。实际表现依赖于数据库驱动,具体可参考数据库驱动的相关文档,或通过对比测试来观察。 | true | false | true |
useGeneratedKeys | 允许 JDBC 支持自动生成主键,需要数据库驱动支持。如果设置为 true,将强制使用自动生成主键。尽管一些数据库驱动不支持此特性,但仍可正常工作(如 Derby)。 | true | false | False |
autoMappingBehavior | 指定 MyBatis 应如何自动映射列到字段或属性。 NONE 表示关闭自动映射;PARTIAL 只会自动映射没有定义嵌套结果映射的字段。 FULL 会自动映射任何复杂的结果集(无论是否嵌套)。 | NONE, PARTIAL, FULL | PARTIAL |
autoMappingUnknownColumnBehavior | 指定发现自动映射目标未知列(或未知属性类型)的行为。
|
NONE, WARNING, FAILING | NONE |
defaultExecutorType | 配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(PreparedStatement); BATCH 执行器不仅重用语句还会执行批量更新。 | SIMPLE REUSE BATCH | SIMPLE |
defaultStatementTimeout | 设置超时时间,它决定数据库驱动等待数据库响应的秒数。 | 任意正整数 | 未设置 (null) |
defaultFetchSize | 为驱动的结果集获取数量(fetchSize)设置一个建议值。此参数只可以在查询设置中被覆盖。 | 任意正整数 | 未设置 (null) |
defaultResultSetType | 指定语句默认的滚动策略。(新增于 3.5.2) | FORWARD_ONLY | SCROLL_SENSITIVE | SCROLL_INSENSITIVE | DEFAULT(等同于未设置) | 未设置 (null) |
safeRowBoundsEnabled | 是否允许在嵌套语句中使用分页(RowBounds)。如果允许使用则设置为 false。 | true | false | False |
safeResultHandlerEnabled | 是否允许在嵌套语句中使用结果处理器(ResultHandler)。如果允许使用则设置为 false。 | true | false | True |
mapUnderscoreToCamelCase | 是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。 | true | false | False |
localCacheScope | MyBatis 利用本地缓存机制(Local Cache)防止循环引用和加速重复的嵌套查询。 默认值为 SESSION,会缓存一个会话中执行的所有查询。 若设置值为 STATEMENT,本地缓存将仅用于执行语句,对相同 SqlSession 的不同查询将不会进行缓存。 | SESSION | STATEMENT | SESSION |
jdbcTypeForNull | 当没有为参数指定特定的 JDBC 类型时,空值的默认 JDBC 类型。 某些数据库驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。 | JdbcType 常量,常用值:NULL、VARCHAR 或 OTHER。 | OTHER |
lazyLoadTriggerMethods | 指定对象的哪些方法触发一次延迟加载。 | 用逗号分隔的方法列表。 | equals,clone,hashCode,toString |
defaultScriptingLanguage | 指定动态 SQL 生成使用的默认脚本语言。 | 一个类型别名或全限定类名。 | org.apache.ibatis.scripting.xmltags.XMLLanguageDriver |
defaultEnumTypeHandler | 指定 Enum 使用的默认 TypeHandler 。(新增于 3.4.5) |
一个类型别名或全限定类名。 | org.apache.ibatis.type.EnumTypeHandler |
callSettersOnNulls | 指定当结果集中值为 null 的时候是否调用映射对象的 setter(map 对象时为 put)方法,这在依赖于 Map.keySet() 或 null 值进行初始化时比较有用。注意基本类型(int、boolean 等)是不能设置成 null 的。 | true | false | false |
returnInstanceForEmptyRow | 当返回行的所有列都是空时,MyBatis默认返回 null 。 当开启这个设置时,MyBatis会返回一个空实例。 请注意,它也适用于嵌套的结果集(如集合或关联)。(新增于 3.4.2) |
true | false | false |
logPrefix | 指定 MyBatis 增加到日志名称的前缀。 | 任何字符串 | 未设置 |
logImpl | 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。 | SLF4J | LOG4J(deprecated since 3.5.9) | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING | 未设置 |
proxyFactory | 指定 Mybatis 创建可延迟加载对象所用到的代理工具。 | CGLIB | JAVASSIST | JAVASSIST (MyBatis 3.3 以上) |
vfsImpl | 指定 VFS 的实现 | 自定义 VFS 的实现的类全限定名,以逗号分隔。 | 未设置 |
useActualParamName | 允许使用方法签名中的名称作为语句参数名称。 为了使用该特性,你的项目必须采用 Java 8 编译,并且加上 -parameters 选项。(新增于 3.4.1) |
true | false | true |
configurationFactory | 指定一个提供 Configuration 实例的类。 这个被返回的 Configuration 实例用来加载被反序列化对象的延迟加载属性值。 这个类必须包含一个签名为static Configuration getConfiguration() 的方法。(新增于 3.2.3) |
一个类型别名或完全限定类名。 | 未设置 |
shrinkWhitespacesInSql | 从SQL中删除多余的空格字符。请注意,这也会影响SQL中的文字字符串。 (新增于 3.5.5) | true | false | false |
defaultSqlProviderType | Specifies an sql provider class that holds provider method (Since 3.5.6). This class apply to the type (or value ) attribute on sql provider annotation(e.g. @SelectProvider ), when these attribute was omitted. |
A type alias or fully qualified class name | Not set |
nullableOnForEach | Specifies the default value of 'nullable' attribute on 'foreach' tag. (Since 3.5.9) | true | false | false |
2.3、类型别名(typeAliases)
类型别名可为 Java 类型设置一个缩写名字。可以在Mapper文件中使用。
配置例子:
<!-- 类型别名,声明的短名称可以在Mapper文件中替代使用 --> <typeAliases> <typeAlias alias="employee" type="db.Domain.Employee"></typeAlias> <!-- 自动为包内所有类创建类型别名,默认是首字母小写的类名称 也可以在类上方通过@Alias("别名")类设置所需要的别名 --> <package name="db.Domain"/> </typeAliases>
下面是一些为常见的 Java 类型内建的类型别名。它们都是不区分大小写的,注意,为了应对原始类型的命名重复,采取了特殊的命名风格。
别名 | 映射的类型 |
---|---|
_byte | byte |
_long | long |
_short | short |
_int | int |
_integer | int |
_double | double |
_float | float |
_boolean | boolean |
string | String |
byte | Byte |
long | Long |
short | Short |
int | Integer |
integer | Integer |
double | Double |
float | Float |
boolean | Boolean |
date | Date |
decimal | BigDecimal |
bigdecimal | BigDecimal |
object | Object |
map | Map |
hashmap | HashMap |
list | List |
arraylist | ArrayList |
collection | Collection |
iterator | Iterator |
2.4、类型处理器(typeHandlers)
在设置预处理语句(PreparedStatement)中的参数或从结果集中取出一个值时, 都会用类型处理器将获取到的值以合适的方式转换成 Java 类型。
为了演示改效果:在数据库中增加isDelete字段,数据库类型用的Bit,程序里边用是/否
数据库表结构:
模型类新代码:
package db.Domain; import org.springframework.stereotype.Component; import java.sql.Date; @Component(value = "employee") public class Employee { private String emplId; private String name; private String gender; private Date hireDate; private int salary; //程序中用String,数据库用布尔类型 private String isDelete; public Employee(String emplId, String name, String gender, Date hireDate, int salary,String isDelete) { this.emplId = emplId; this.name = name; this.gender = gender; this.hireDate = hireDate; this.salary = salary; this.isDelete = isDelete; } public String getEmplId() { return emplId; } public void setEmplId(String emplId) { this.emplId = emplId; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public Date getHireDate() { return hireDate; } public void setHireDate(Date hireDate) { this.hireDate = hireDate; } public int getSalary() { return salary; } public void setSalary(int salary) { this.salary = salary; } public String getDelete() {return isDelete;} public void setDelete(String delete) {isDelete = delete;} @Override public String toString() { return "Employee{" + "emplId='" + emplId + '\'' + ", name='" + name + '\'' + ", gender='" + gender + '\'' + ", hireDate=" + hireDate + ", salary=" + salary + ", isDelete=" + isDelete + '}'; } //实例化后执行的方法 public void init() { //完成对其它的业务处理 System.out.println("init执行"); } }
参考配置:
<!-- 从数据库的类型转为Java的类型,将Java类型的参数转换为数据库对应类型 MyBatis默认提供了一些类型处理器,基本不需要自己定义 jdbcType必须是枚举值 JDBCType.XXX 了解即可,使用少 --> <typeHandlers> <typeHandler handler="db.TypeHandles.isDeleteTypeHandle" javaType="java.lang.String" jdbcType="BIT"></typeHandler> </typeHandlers>
定义类型转换类:
package db.TypeHandles; import org.apache.ibatis.type.JdbcType; import org.apache.ibatis.type.TypeHandler; import java.sql.*; //是否删除字段,数据库BIT类型,程序操作:是否 public class isDeleteTypeHandle implements TypeHandler<String> { //是设置为true,否设置为false @Override public void setParameter(PreparedStatement ps, int i, String b, JdbcType jdbcType) throws SQLException { System.out.println("参数值="+b); if(b.equals("是")) ps.setBoolean(i,true); if(b.equals("否")) ps.setBoolean(i,false); } @Override public String getResult(ResultSet rs, String s) throws SQLException { boolean r = rs.getBoolean(s); if(r==true) return "是"; if(r==false) return "否"; return null; } @Override public String getResult(ResultSet rs, int i) throws SQLException { boolean r = rs.getBoolean(i); if(r==true) return "是"; if(r==false) return "否"; return null; } @Override public String getResult(CallableStatement cs, int i) throws SQLException { boolean r = cs.getBoolean(i); if(r==true) return "是"; if(r==false) return "否"; return null; } }
在Mapper文件中使用类型转换器:jdbcType的取值必须是枚举JDBCType.xxx内部包含的某一个类型。
<?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="db.Dao.EmployeeDao"> <!--主键查询--> <select id="queryByEmplId" resultType="db.Domain.Employee"> select * from Employee where emplId=#{emplId} </select> <!--条件查询--> <select id="queryListBySalary" resultType="employee" > select * from Employee where salary BETWEEN #{start} and #{end} </select> <!--新增--> <insert id="insert" parameterType="db.Domain.Employee"> insert into employee(emplId,`name`,gender,hireDate,salary,isDelete) values(#{emplId},#{name},#{gender}, #{hireDate},#{salary}, #{isDelete,javaType=java.lang.String,jdbcType=BIT,typeHandler=db.TypeHandles.isDeleteTypeHandle}) </insert> <!--修改--> <update id="update" parameterType="db.Domain.Employee"> update employee set `name`=#{name},gender=#{gender},salary=#{salary}, isDelete=#{isDelete,javaType=java.lang.String,jdbcType=BIT,typeHandler=db.TypeHandles.isDeleteTypeHandle} where emplId=#{emplId} </update> <delete id="delete"> delete from employee where emplId=#{emplId} </delete> </mapper>
测试输出结果,自动显示为是和否。
2.5、对象工厂(objectFactory)
每次 MyBatis 创建结果对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成实例化工作。 默认的对象工厂需要做的仅仅是实例化目标类,要么通过默认无参构造方法,要么通过存在的参数映射来调用带有参数的构造方法。 如果想覆盖对象工厂的默认行为,可以通过创建自己的对象工厂来实现。
配置例子:
<!-- 对象工厂,用来完成查询结果映射对ResultType时进行的的业务处理 每次 MyBatis 创建结果对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成实例化工作。 默认的对象工厂需要做的仅仅是实例化目标类,要么通过默认无参构造方法,要么通过存在的参数映射来调用带有参数的构造方法。 如果想覆盖对象工厂的默认行为,可以通过创建自己的对象工厂来实现 了解即可,使用少 --> <objectFactory type="db.ObjectFactory.ExampleObjectFactory"> </objectFactory>
定义工厂类:
工厂类内部调用的模型类,必须提供带参数的构造方法,否则无法给参数复制。
package db.ObjectFactory; import db.Domain.Employee; import org.apache.ibatis.reflection.factory.DefaultObjectFactory; import java.util.List; //自定义对象生成工程 public class ExampleObjectFactory extends DefaultObjectFactory { @Override public <T> T create(Class<T> type) { return super.create(type); } @Override public <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) { T ret = super.create(type, constructorArgTypes, constructorArgs); //如果是Employee类型,Employee需要提供带参数的构造函数,否则获取的对象属性没有数据值 if(Employee.class.isAssignableFrom(type)) { Employee emp = (Employee)ret; System.out.println("工厂对象输出:"+emp.toString()); } return ret; } }
运行结果:
2.6、插件(plugins)
有点复杂,文档没有详细说明每个拦截位置的要求。
MyBatis 允许你在映射语句执行过程中的某一点进行拦截调用。默认情况下,MyBatis 允许使用插件来拦截的方法调用包括:
- Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
- ParameterHandler (getParameterObject, setParameters)
- ResultSetHandler (handleResultSets, handleOutputParameters)
- StatementHandler (prepare, parameterize, batch, update, query)
配置例子:
<!-- MyBatis 允许你在映射语句执行过程中的某一点进行拦截调用 了解即可,使用少 --> <plugins> <plugin interceptor="db.Plugin.ExamplePlugin"> </plugin> </plugins>
插件类定义:
package db.Plugin; import org.apache.ibatis.executor.Executor; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.plugin.Interceptor; import org.apache.ibatis.plugin.Intercepts; import org.apache.ibatis.plugin.Invocation; import org.apache.ibatis.plugin.Signature; import java.util.Properties; //拦截器注解,拦截范围定义 @Intercepts({@Signature( type= Executor.class, method = "update", args = {MappedStatement.class,Object.class})}) public class ExamplePlugin implements Interceptor { private Properties properties = new Properties(); public Object intercept(Invocation invocation) throws Throwable { System.out.println("拦截器前执行"); Object returnObject = invocation.proceed(); System.out.println("拦截器后执行"); return returnObject; } public void setProperties(Properties properties) { this.properties = properties; } }
运行结果:删除,新增,修改都会有输出。
2.7、环境配置(environments)
MyBatis 可以配置成适应多种环境,方便开发、测试,上线不同的环境参数。
配置例子:
<!-- 在主配置文件中允许同时配置多个环境 通过default切换所用的配置 --> <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}"/> </dataSource> </environment> <!-- 上线环境 --> <environment id="oneline"> <!-- 事务类型 --> <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}"/> </dataSource> </environment> </environments>
2.8、映射器(mappers)
用来引入表的配置,可以引入Mapper文件,也可以引入类定义
引入Mapper文件:
<!-- 映射器配置 --> <!-- 引入表的接口类 --> <mappers> <mapper resource="db/mapper/EmployeeMapper.xml"/> </mappers>
引入类文件:采用注解的方式时用。
<mappers> <mapper class="org.mybatis.builder.AuthorMapper"/> <mapper class="org.mybatis.builder.BlogMapper"/> <mapper class="org.mybatis.builder.PostMapper"/> </mappers>
批量引入:
<!-- 将包内的映射器接口实现全部注册为映射器 --> <mappers> <package name="org.mybatis.builder"/> </mappers>
3、相关代码
3.1 模型类
package db.Domain; import org.springframework.stereotype.Component; import java.sql.Date; @Component(value = "employee") public class Employee { private String emplId; private String name; private String gender; private Date hireDate; private int salary; //程序中用String,数据库用布尔类型 private String isDelete; public Employee(String emplId, String name, String gender, Date hireDate, int salary,String isDelete) { this.emplId = emplId; this.name = name; this.gender = gender; this.hireDate = hireDate; this.salary = salary; this.isDelete = isDelete; } public String getEmplId() { return emplId; } public void setEmplId(String emplId) { this.emplId = emplId; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public Date getHireDate() { return hireDate; } public void setHireDate(Date hireDate) { this.hireDate = hireDate; } public int getSalary() { return salary; } public void setSalary(int salary) { this.salary = salary; } public String getDelete() {return isDelete;} public void setDelete(String delete) {isDelete = delete;} @Override public String toString() { return "Employee{" + "emplId='" + emplId + '\'' + ", name='" + name + '\'' + ", gender='" + gender + '\'' + ", hireDate=" + hireDate + ", salary=" + salary + ", isDelete=" + isDelete + '}'; } //实例化后执行的方法 public void init() { //完成对其它的业务处理 System.out.println("init执行"); } }
3.2 接口类
package db.Dao; import db.Domain.Employee; import org.apache.ibatis.annotations.Param; import java.util.List; //数据访问接口 - 注解方式 public interface EmployeeDao { //查询单个对象,单个参数时@Param可以省略 public Employee queryByEmplId(@Param("emplId") String empId); //查询多个对象,多个参数时需要通过@Param声明 public List<Employee> queryListBySalary(@Param("start") int start, @Param("end") int end); //新增数据 public int insert(Employee emp); //更新数据 public int update(Employee emp); //删除数据 public void delete(@Param("emplId") String empId); }
3.3 属性配置
jdbc.driver=com.mysql.cj.jdbc.Driver jdbc.url=jdbc:mysql://47.100.229.xxx:3306/springStudy?useSSL=false&serverTimezone=UTC jdbc.username=root jdbc.password=xxx
3.4 主配置文件
<?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="jdbc.Properties"> <!-- 内部额外定义的属性,这些属性都可以在配置文件中通过${属性名}使用 --> <property name="jdbc.other" value="other"/> </properties> <!-- 全局配置参数,相关的参数参照myBatis文档 --> <settings> <!-- 是否开启缓存 --> <setting name="cacheEnabled" value="true"/> <!-- 是否开启懒加载 --> <setting name="lazyLoadingEnabled" value="true"/> </settings> <!-- 类型别名,声明的短名称可以在Mapper文件中替代使用 --> <typeAliases> <typeAlias alias="employee" type="db.Domain.Employee"></typeAlias> <!-- 自动为包内所有类创建类型别名,默认是首字母小写的类名称 也可以在类上方通过@Alias("别名")类设置所需要的别名 --> <package name="db.Domain"/> </typeAliases> <!-- 从数据库的类型转为Java的类型,将Java类型的参数转换为数据库对应类型 MyBatis默认提供了一些类型处理器,基本不需要自己定义 jdbcType必须是枚举值 JDBCType.XXX 了解即可,使用少 --> <typeHandlers> <typeHandler handler="db.TypeHandles.isDeleteTypeHandle" javaType="java.lang.String" jdbcType="BIT"></typeHandler> </typeHandlers> <!-- 对象工厂,用来完成查询结果映射对ResultType时进行的的业务处理 每次 MyBatis 创建结果对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成实例化工作。 默认的对象工厂需要做的仅仅是实例化目标类,要么通过默认无参构造方法,要么通过存在的参数映射来调用带有参数的构造方法。 如果想覆盖对象工厂的默认行为,可以通过创建自己的对象工厂来实现 了解即可,使用少 --> <objectFactory type="db.ObjectFactory.ExampleObjectFactory"> </objectFactory> <!-- MyBatis 允许你在映射语句执行过程中的某一点进行拦截调用 了解即可,使用少 --> <plugins> <plugin interceptor="db.Plugin.ExamplePlugin"> </plugin> </plugins> <!-- 在主配置文件中允许同时配置多个环境 通过default切换所用的配置 --> <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}"/> </dataSource> </environment> <!-- 上线环境 --> <environment id="oneline"> <!-- 事务类型 --> <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}"/> </dataSource> </environment> </environments> <!-- 映射器配置 --> <!-- 引入表的接口类 --> <mappers> <mapper resource="db/mapper/EmployeeMapper.xml"/> </mappers> </configuration>
3.5 映射文件
<?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="db.Dao.EmployeeDao"> <!--主键查询--> <select id="queryByEmplId" resultType="db.Domain.Employee"> select * from Employee where emplId=#{emplId} </select> <!--条件查询--> <select id="queryListBySalary" resultType="employee" > select * from Employee where salary BETWEEN #{start} and #{end} </select> <!--新增--> <insert id="insert" parameterType="db.Domain.Employee"> insert into employee(emplId,`name`,gender,hireDate,salary,isDelete) values(#{emplId},#{name},#{gender}, #{hireDate},#{salary}, #{isDelete,javaType=java.lang.String,jdbcType=BIT,typeHandler=db.TypeHandles.isDeleteTypeHandle}) </insert> <!--修改--> <update id="update" parameterType="db.Domain.Employee"> update employee set `name`=#{name},gender=#{gender},salary=#{salary}, isDelete=#{isDelete,javaType=java.lang.String,jdbcType=BIT,typeHandler=db.TypeHandles.isDeleteTypeHandle} where emplId=#{emplId} </update> <delete id="delete"> delete from employee where emplId=#{emplId} </delete> </mapper>
3.6 类型转换类
package db.TypeHandles; import org.apache.ibatis.type.JdbcType; import org.apache.ibatis.type.TypeHandler; import java.sql.*; //是否删除字段,数据库BIT类型,程序操作:是否 public class isDeleteTypeHandle implements TypeHandler<String> { //是设置为true,否设置为false @Override public void setParameter(PreparedStatement ps, int i, String b, JdbcType jdbcType) throws SQLException { System.out.println("参数值="+b); if(b.equals("是")) ps.setBoolean(i,true); if(b.equals("否")) ps.setBoolean(i,false); } @Override public String getResult(ResultSet rs, String s) throws SQLException { boolean r = rs.getBoolean(s); if(r==true) return "是"; if(r==false) return "否"; return null; } @Override public String getResult(ResultSet rs, int i) throws SQLException { boolean r = rs.getBoolean(i); if(r==true) return "是"; if(r==false) return "否"; return null; } @Override public String getResult(CallableStatement cs, int i) throws SQLException { boolean r = cs.getBoolean(i); if(r==true) return "是"; if(r==false) return "否"; return null; } }
3.7 对象工厂类
package db.ObjectFactory; import db.Domain.Employee; import org.apache.ibatis.reflection.factory.DefaultObjectFactory; import java.util.List; //自定义对象生成工程 public class ExampleObjectFactory extends DefaultObjectFactory { @Override public <T> T create(Class<T> type) { return super.create(type); } @Override public <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) { T ret = super.create(type, constructorArgTypes, constructorArgs); //如果是Employee类型,Employee需要提供带参数的构造函数,否则获取的对象属性没有数据值 if(Employee.class.isAssignableFrom(type)) { Employee emp = (Employee)ret; //自动调用后续的处理方法 emp.init(); System.out.println("工厂对象输出:"+emp.toString()); } return ret; } }
3.8 插件类
package db.Plugin; import org.apache.ibatis.executor.Executor; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.plugin.Interceptor; import org.apache.ibatis.plugin.Intercepts; import org.apache.ibatis.plugin.Invocation; import org.apache.ibatis.plugin.Signature; import java.util.Properties; //拦截器注解,拦截范围定义 @Intercepts({@Signature( type= Executor.class, method = "update", args = {MappedStatement.class,Object.class})}) public class ExamplePlugin implements Interceptor { private Properties properties = new Properties(); public Object intercept(Invocation invocation) throws Throwable { System.out.println("拦截器前执行"); Object returnObject = invocation.proceed(); System.out.println("拦截器后执行"); return returnObject; } public void setProperties(Properties properties) { this.properties = properties; } }
3.9 测试代码
import db.Dao.EmployeeDao; import db.Domain.Employee; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Test; import java.io.IOException; import java.io.InputStream; import java.sql.Date; import java.util.List; public class myTest { @Test public void TestMyBaisc() throws IOException { //1 读取配置文件 String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); //2 构建SqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //3 构建SqlSession,并执行mapper内操作 try (SqlSession session = sqlSessionFactory.openSession()) { //获取接口代理实现 EmployeeDao dao = session.getMapper(EmployeeDao.class); //单数据查询 { System.out.println("==单数据查询"); Employee empl = dao.queryByEmplId("001"); System.out.println(empl.toString()); } //数据删除 { System.out.println("==数据删除"); dao.delete("005"); session.commit(); } //数据新增 { System.out.println("==数据新增"); Employee empl = new Employee("005","李晓明","男",new Date(2020,10,10),2000,"是"); int result = dao.insert(empl); session.commit(); System.out.println("行数:"+result); } //多数据查询 { System.out.println("==多数据查询 - 新增后"); List<Employee> list = dao.queryListBySalary(20,5000); for (Employee item : list) { System.out.println(item.toString()); } } //数据修改 { System.out.println("==数据修改"); Employee empl = new Employee("003","刘超","男",new Date(2020,10,10),2000,"是"); int result = dao.update(empl); session.commit(); System.out.println("行数:"+result); } //多数据查询 { System.out.println("==多数据查询 - 修改后"); List<Employee> list = dao.queryListBySalary(20,5000); for (Employee item : list) { System.out.println(item.toString()); } } } System.out.println("测试完成1"); } }