mybatis是一款优秀的持久层框架,支持定制SQL语句,避免了几乎全部JDBC代码和手动设置参数,结果集获取php
SqlSessionFactory build(InputStream inputStream) SqlSessionFactory build(InputStream inputStream, String environment) SqlSessionFactory build(InputStream inputStream, Properties properties) SqlSessionFactory build(InputStream inputStream, String env, Properties props) SqlSessionFactory build(Configuration config) 复制代码
//默认获取的方式,不自动提交(开启事务)
SqlSession openSession() //是否自动提交 SqlSession openSession(boolean autoCommit) SqlSession openSession(Connection connection) //事务的隔离级别:None,RU,RC,RR,Serial SqlSession openSession(TransactionIsolationLevel level) //查询类型:simple,batch,reuse SqlSession openSession(ExecutorType execType,TransactionIsolationLevel level) SqlSession openSession(ExecutorType execType) SqlSession openSession(ExecutorType execType, boolean autoCommit) SqlSession openSession(ExecutorType execType, Connection connection) //获取mybatis配置信息 Configuration getConfiguration();
复制代码
//带参数的增删改查方法
<T> T selectOne(String statement, Object parameter) <E> List<E> selectList(String statement, Object parameter) <K,V> Map<K,V> selectMap(String statement, Object parameter, String mapKey) int insert(String statement, Object parameter) int update(String statement, Object parameter) int delete(String statement, Object parameter) //不带参数的增删改查方法 <T> T selectOne(String statement) <E> List<E> selectList(String statement) <K,V> Map<K,V> selectMap(String statement, String mapKey) int insert(String statement) int update(String statement) int delete(String statement) //高级版本的增删该查方法,支持自定义返回行数和结果控制 <E> List<E> selectList (String statement, Object parameter, RowBounds rowBounds) <K,V> Map<K,V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowbounds) void select (String statement, Object parameter, ResultHandler<T> handler) void select (String statement, Object parameter, RowBounds rowBounds, ResultHandler<T> handler) //事务控制相关方法 void commit() void commit(boolean force) void rollback() void rollback(boolean force) //清除缓存。mybatis提供了本地缓存和二级缓存 void clearCache() //关闭session void close() //得到configuration实例 Configuration getConfiguration() //得到映射器 <T> T getMapper(Class<T> type) 复制代码
全部支持的配置项介绍文档:mybatis配置文件说明,最外层标签为configuration,子标签有:html
propertiess, 能够外部配置且动态替换java
typeAliases,定义别名。用于减小冗长的类限定名,只和xml配置有关mysql
<typeAlias>
<typeAlia alias="role" type="XXX"/>
<package name="xxx"/>
</typeAlias>
复制代码
mappers,定义映射器,告诉mybatis去哪里找映射器git
<mappers>
<mapper resource="xxx"/>
<mapper url="file:://xxx"/>
<mapper class="xxx"/>
<!--包内的全部接口都注册为映射器-->
<package name="xxx" />
</mappers>
复制代码
typeHandlers,用于将获取的值转化为合适的java类型github
<typeHandlers>
<typeHandler handler="xxx">
</typeHandlers>
复制代码
environments,定义了如何配置数据库环境信息spring
<environments>
<environment>
<transactionManager type="JDBC">
</transactionManager>
<dataSource type="POOLED">
<property name="url" value="xxx">
...
</dataSource>
</environment>
</environments>
复制代码
settings,很重要的参数sql
<settings>
<!--全局开启映射器已经配置的任何缓存-->
<setting name="cacheEnabled" value="true"/>
<!--延迟加载的全局开关-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--是否运行单一语句返回多条结果集-->
<setting name="multipleResultSetsEnabled" value="true"/>
<!--列标签代替列名-->
<setting name="useColumnLabel" value="true"/>
<!--运行jdbc支持自增加主键-->
<setting name="useGeneratedKeys" value="false"/>
<!--如何自动映射列到字段属性-->
<setting name="autoMappingBehavior" value="PARTIAL"/>
<!---->
<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
<!--默认的执行器-->
<setting name="defaultExecutorType" value="SIMPLE"/>
<!--超时时间-->
<setting name="defaultStatementTimeout" value="25"/>
<!--日志框架,可选值有:SLF4J,LOG4J,JDK_LOGGING,COMMONS_LOGGING,STDOUT_LOGGING,NO_LOGGING-->
<setting name="logImpl" value="LOG4J"/>
<!---->
<setting name="defaultFetchSize" value="100"/>
<!---->
<setting name="safeRowBoundsEnabled" value="false"/>
<!--是否开启自动驼峰命名规则:下划线列名转驼峰变量名-->
<setting name="mapUnderscoreToCamelCase" value="false"/>
<!---->
<setting name="localCacheScope" value="SESSION"/>
<!---->
<setting name="jdbcTypeForNull" value="OTHER"/>
<!---->
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>
复制代码
objectFactory:建立结果对象的工厂类,可自定义覆盖默认的数据库
<objectFactory type="XXX">
<property name="xx", value="xx"/>
</objectFactory>
复制代码
plugins:插件运行定义拦截器,拦截mybatis执行过程当中的某些调用apache
映射文件定义了接口要执行的sql语句,全部支持的映射文件介绍文档:mybatis映射文件说明
<select id="调用接口的函数名称,惟一标识" parameterType="参数类型,可省略,会根据typehandler自动推断" parameterMap="被废弃的选项" resultType="返回结果的类型,不能与resultMap同时存在" resultMap="返回结果的外部集合映射,不能与resultType同时存在。resultType为bean时,底层使用了resultMap" flushCache="设置为true表示任什么时候候调用都会清除本地和二级缓存,默认false" useCache="是否开启本地和二级缓存,默认为true" timeout="驱动等待数据库响应时间,默认为unset,依赖驱动" fetchSize="驱动每次批量返回结果数" statementType="默认preparedStatement" resultSetType="结果集类型,逗号分开">
select id, name from table_name where id = #{id}
</select>
复制代码
<insert ... useGeneratedKeys="是否取出数据库自增加获得的id,默认false" keyProperty=“generatedKey的目标属性字段” keyColumn=“generatedKey的目标列名,主键列不是第一列须要设置” >
</insert>
复制代码
<sql id="xxx">
</sql>
<!--调用的地方-->
<include refid="xxx"/>
复制代码
<resultMap>
<!--注入结果到构造方法中-->
<constructor>
<idArg column="" javatype="">
<arg>
</constructor>
<!--复杂类型的关联-->
<association>
</association>
<!--复杂类型的集合-->
<collection>
</collection>
</resultMap>
复制代码
<!--开启可读可写缓存,全部select都被缓存,insert,delete和update刷新缓存,-->
<cache
<!--回收策略:包括LRU(默认),FIFO,SOFT,WEAK-->
eviction="LRU"
<!--刷新时间,单位毫秒-->
flushInternval="60000"
readOnly="true"
<!--缓存存储的引用数量,默认1024-->
size="512"
/>
<cache type="自定义缓存,必须实现org.mybatis.cache.Cache接口"/>
复制代码
动态SQL:用于根据条件包含where字句的一部分。动态SQL包括if,choose,trim,foreach
<select/insert id="xx">
select id, name, status
from table_name
where status = #{status}
<!--普通的条件判断语句-->
<if test="name != null">
and name like #{name}
</if>
<!--条件分支语句,相似与switch-->
<choose>
<when test="name != null">
</when>
<otherwise>
</otherwise>
</choose>
<!--会自动去除条件不知足时多余的where,and,or等关键字-->
<where>
</where>
<!--自定义去除某些符号的功能-->
<trim prefix="WHERE" prefixOverrides="AND|OR">
</trim>
<set>
<if>
</set>
<foreach item="" index="" collection="">
</foreach>
</select>
复制代码
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--必须的属性,配置数据源-->
<property name="dataSource" ref="dataSource" />
<!--可选属性,配置映射文件路径-->
<property name="mapperLocations" value="classpath*:sample/config/mappers/**/*.xml" />
</bean>
复制代码
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--数据源必须和SqlSessionFactoryBean配置的数据源一致-->
<property name="dataSource" ref="dataSource" />
</bean>
复制代码
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="org.mybatis.spring.sample.mapper.UserMapper" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
复制代码
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="org.mybatis.spring.sample.mapper" />
</bean>
复制代码
# application.properties
# 指定mybatis-config.xml文件的位置
mybatis.config-location=classpath:mybatis-config.xml
# 指定mapper的xml文件路径
mybatis.mapper-locations=classpath:com/xx
mybatis.executor-type=SIMPLE
# 指定别名的包,多个用逗号分开
mybatis.type-aliases-package=com.example.domain.model
mybatis.type-handlers-package=com.example.typehandler
mybatis.configuration.map-underscore-to-camel-case=true
mybatis.configuration.default-fetch-size=100
mybatis.configuration.default-statement-timeout=30
复制代码
MybatisAutoConfiguration类内部构造了SqlSessionFactoryBean对象
SqlSessionFactoryBean实现了FactoryBean接口,因此getBean获取实例时实际调用他的getObject方法。内部调用了afterPropertiesSet方法。afterPropertiesSet方法被重写,内部调用buildSqlSessionFactory
buildSqlSessionFactory内部建立了XMLConfigBuilder,用于解析mybatis的配置文件
真正解析配置文件的地方
解析的配置文件的根为configuration,而后依次解析子标签:包括最重要的mappers标签。这部分的解析和前面介绍的配置文件说明是一一对应的,全部标签都有对应的解析标签的代码
对mapper文件的解析,内部又具体调用了XMLMapperBuilder类的parse方法。这部分的解析与前面介绍的mapper配置文件说明也是一一对应的
解析mapper文件时,从根元素mapper开始,包括子节点cache,parameterMap,resultMap,select等。而后将解析的信息都保存到Configuration对象中。
其中select,insert,delete,update语句的解析方法为
解析完以后,放入一个map中,每条sql语句对应一个MappedStatement对象。其余属性的解析相似,大可能是放到map中。
解析完全部的配置文件,获得Configuration对象,将它做为参数传给SqlSessionFactoryBuilder的build方法
SqlSessionFactoryBuilder内部根据Configuration参数,建立DefaultSqlSessionFactory类
DefaultSqlSessionFactory构造函数只是将Configuration保存了下来,当须要获取session时,根据内部的configuration去具体建立
获得SqlSessionFactory后,根据它去建立SqlSessionTemplate
SqlSessionTemplate内部建立SqlSession的代理类,将没有加事务的SqlSession的操做作强制提交
Dao层都是是一些接口 它并无实现类,为何接口能够直接使用呢? 那是由于MyBbatis使用了JDK动态代理机制动态生成了代理类,那么代理类又是如何对SqlSession进行封装的呢?
java -jar mybatis-generator-core-x.x.x.jar -configfile \temp\generatorConfig.xml -overwrite
复制代码
<build>
<plugins>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>${mybatis-generator.version}</version>
<configuration>
<overwrite>true</overwrite>
<verbose>true</verbose>
</configuration>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
复制代码
<?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>
<!--非必填选项,用于添加运行类路径位置到类路径中-->
<classPathEntry location="/Program Files/IBM/SQLLIB/java/db2java.zip" />
<!--元素用于指定生成一组对象的环境-->
<context id="DB2Tables" targetRuntime="MyBatis3">
<!--注释生成器的属性-->
<commentGenerator>
<property name="suppressDate" value="true" />
<!-- 是否去除自动生成的注释 true:是 : false:否 -->
<property name="suppressAllComments" value="true"/>
</commentGenerator>
<!--指定数据库链接信息-->
<jdbcConnection driverClass="COM.ibm.db2.jdbc.app.DB2Driver" connectionURL="jdbc:db2:TEST" userId="db2admin" password="db2admin">
</jdbcConnection>
<!--用于定义Java类型解析器的属性-->
<javaTypeResolver >
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<!-- 生成实体类的包名和位置-->
<javaModelGenerator targetPackage="test.model" targetProject="\MBGTestProject\src">
<property name="enableSubPackages" value="true" />
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!-- 生成mapper xml文件的包名和位置-->
<sqlMapGenerator targetPackage="test.xml" targetProject="\MBGTestProject\src">
<property name="enableSubPackages" value="true" />
</sqlMapGenerator>
<!-- 生成DAO的包名和位置-->
<javaClientGenerator type="XMLMAPPER" targetPackage="test.dao" targetPackage="xx" targetProject="\MBGTestProject\src">
<property name="enableSubPackages" value="true" />
</javaClientGenerator>
<!--指定生成哪一个表的信息-->
<table schema="DB2ADMIN" tableName="ALLTYPES" domainObjectName="Customer" >
<property name="useActualColumnNames" value="true"/>
<!--指定自动生成的主键-->
<generatedKey column="ID" sqlStatement="DB2" identity="true" />
<columnOverride column="DATE_FIELD" property="startDate" />
<ignoreColumn column="FRED" />
<!--自定义列信息,覆盖默认信息,包括property,javaType,jdbcType,typeHandler,delimitedColumnName属性-->
<columnOverride column="LONG_VARCHAR_FIELD" jdbcType="VARCHAR" />
</table>
</context>
</generatorConfiguration>
复制代码
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>${pageHelper.version}</version>
</dependency>
复制代码
# 分页插件会自动检测当前的数据库连接,自动选择合适的分页方式。 你能够配置helperDialect属性来指定分页插件使用哪一种方言
pagehelper.helperDialect=mysql
# 分页合理化参数,默认值为false。当该参数设置为 true 时,pageNum<=0 时会查询第一页,
# pageNum>pages(超过总数时),会查询最后一页。默认false 时,直接根据参数进行查询。
pagehelper.reasonable=true
# 默认值为false,该参数对使用 RowBounds 做为分页参数时有效。 当该参数设置为true时,使用 RowBounds 分页会进行 count 查询。
pagehelper.row-bounds-with-count=false
# 为了支持startPage(Object params)方法,增长了该参数来配置参数映射,用于从对象中根据属性名取值
# 能够配置 pageNum,pageSize,count,pageSizeZero,reasonable,不配置映射的用默认值
# 默认值为pageNum=pageNum;pageSize=pageSize;count=countSql;reasonable=reasonable;pageSizeZero=pageSizeZero
pagehelper.params=
# 支持经过 Mapper 接口参数来传递分页参数,默认值false,分页插件会从查询方法的参数值中,
# 自动根据上面 params 配置的字段中取值,查找到合适的值时就会自动分页
pagehelper.supportMethodsArguments=false
# 默认值为 false,当该参数设置为 true 时,若是 pageSize=0 或者 RowBounds.limit = 0
# 就会查询出所有的结果(至关于没有执行分页查询,可是返回结果仍然是 Page 类型)
pagehelper.pageSizeZero=false
# autoRuntimeDialect:默认值为 false。设置为 true 时,容许在运行时根据多数据源自动识别对应方言的分页
# pring 中配置了动态数据源,而且链接不一样类型的数据库,这时你能够配置为true
pagehelper.autoRuntimeDialect: false
# 默认值为 true。当使用运行时动态数据源或没有设置 helperDialect 属性自动获取数据库类型时,会自动获取一个数据库链接,
# 经过该属性来设置是否关闭获取的这个链接,默认true关闭,设置为 false 后,不会关闭获取的链接
# 这个参数的设置要根据本身选择的数据源来决定
pagehelper.close-conn=false
复制代码
//方法一:Mapper接口方式的调用,startPage,推荐这种使用方式。
PageHelper.startPage(1, 10);
List<Country> list = countryMapper.selectIf(1);
//方法二:Mapper接口方式的调用,offsetPage, 推荐这种使用方式。
PageHelper.offsetPage(1, 10);
List<Country> list = countryMapper.selectIf(1);
//方法三:参数方法调用
//存在如下 Mapper 接口方法,你不须要在 xml 处理后两个参数
public interface CountryMapper {
List<Country> selectByPageNumSize( @Param("user") User user, @Param("pageNum") int pageNum, @Param("pageSize") int pageSize);
}
//配置supportMethodsArguments=true
//在代码中直接调用:
List<Country> list = countryMapper.selectByPageNumSize(user, 1, 10);
//方法四:java8 lambda调用
//jdk8 lambda用法
Page<Country> page = PageHelper.startPage(1, 10).doSelectPage(()-> countryMapper.selectGroupBy());
pageInfo = PageHelper.startPage(1, 10).doSelectPageInfo(() -> countryMapper.selectGroupBy());
//count查询,返回一个查询语句的count数
total = PageHelper.count(()->countryMapper.selectLike(country));
复制代码