为什么要使用MyBatis?
环境搭建:
测试:
接口式编程:
SqlSession:
MyBatis 的配置文件包含了影响 MyBatis 行为甚深的设置(settings)和属性(properties)信息。文档的顶层结构如下:
• configuration 配置
• properties 属性
• settings 设置
• typeAliases 类型命名
• typeHandlers 类型处理器
• objectFactory 对象工厂
• plugins 插件
• environments 环境
• environment 环境变量
• transactionManager 事务管理器
• dataSource 数据源
• databaseIdProvider 数据库厂商标识
• mappers 映射器
<properties resource="dbconfig.properties"></properties>
resource:引入类路径下的资源
url:引入网络路径或者磁盘路径下的资源
如果属性在不只一个地方进行了配置,那么 MyBatis 将按照下面的顺序来加载:
这是 MyBatis 中极为重要的调整设置,它们会改变MyBatis 的运行时行为。
• 类型别名是为 Java 类型设置一个短的名字,可以方便我们引用某个类。
<typeAliases>
<typeAlias type="com.bean.Employee' alisa="employee" />
<typeAlias type="com.bean.Department' alisa="department" />
<typeAliases/>
• 类很多的情况下,可以批量设置别名这个包下的每一个类创建一个默认的别名,就是简单类名小写。
<typeAliases>
<package name="com.bean" />
<typeAliases/>
• 也可以使用@Alias注解为其指定一个别名
@Alias("emps")
pubulic class Employee{
值得注意的是,MyBatis已经为许多常见的 Java 类型内建了相应的类型别名。它们都是大小写不敏感的,我们在起别名的时候千万不要占用已有的别名。
无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时, 都会用类型处理器将获取的值以合适的方式转换成 Java 类型。
日期类型的处理:
自定义类型处理器:
我们可以重写类型处理器或创建自己的类型处理器来处理不支持的或非标准的类型。
步骤:
插件是MyBatis提供的一个非常强大的机制,我们可以通过插件来修改MyBatis的一些核心行为。插
件通过动态代理机制,可以介入四大对象的任何一个方法的执行。后面会有专门的章节我们来介绍mybatis运行原理以及插件。
• Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
• ParameterHandler (getParameterObject, setParameters)
• ResultSetHandler (handleResultSets, handleOutputParameters)
• StatementHandler (prepare, parameterize, batch, update, query)
environment-指定具体环境:
transactionManager
• type: JDBC | MANAGED | 自定义
dataSource
• type: UNPOOLED | POOLED | JNDI | 自定义
实际开发中我们使用Spring管理数据源,并进行事务控制的配置来覆盖上述配置
<environments default="dev_mysql">
<environment id="dev_mysql">
<transactionManager type="JDBC"></transactionManager>
<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="dev_oracle">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="${orcl.driver}" />
<property name="url" value="${orcl.url}" />
<property name="username" value="${orcl.username}" />
<property name="password" value="${orcl.password}" />
</dataSource>
</environment>
</environments>
DML与事务:
对于DML数据操作,我们必须要记住提交事务,如果autocommit为true的话,当然就不用我们自己操心了!!数据库会帮我们提交的!!但是在MyBatis持久层框架中,进行DML操作时我们必须要手动开启事务,并且手动提交事务!!因为在MyBatis持久层框架中,它们处理DML语句的时候会自动设置autocommit=false;如果DML中不进行手动提交事务,那么最后事务就会进行回滚。
为什么不设置autocommit=true自动提交呢?
因为autocommit是针对于单条sql语句的自动提交。反而我们真实写项目的时候,用到的事务都是包含多条sql语句,所以我们不得不自己手动显示开启事务,并且手动进行事务提交!!以此来创建一个事务作用边界。
DQL与事务:
MyBatis框架中DQL不需要我们手动开启事务或者提交事务。我们不做同样能够读取到最新数据!!DQL的事务开启或者提交是框架帮我们做!!
DQL不同隔离级别查询的值会不同,针对于MySQL,InnoDB的REPEATABLE_READ,其保证了同一个事务里,查询的结果和开启事务时并且第一次查询数据时的数据总是一样的。
有很多程序员说,DQL不需要开启事务,但是通过我们的最佳实践知道,就算我们不开启事务,数据库也会帮我们开启事务。而且在一个事务中查询数据还会一直相同(REPEATABLE_READ事务隔离级别)。所以这和很多程序员的观点:”DQL不需要开启事务”是矛盾的!!
MyBatis 可以根据不同的数据库厂商执行不同的语句。
Type: DB_VENDOR
– 使用MyBatis提供的VendorDatabaseIdProvider解析数据库厂商标识。也可以实现DatabaseIdProvider接口来自定义。
• Property-name:数据库厂商标识
• Property-value:为标识起一个别名,方便SQL语句使用databaseId属性引用
<databaseIdProvider type="DB_VENDOR">
<!-- 为不同的数据库厂商起别名 -->
<property name="MySQL" value="mysql"/>
<property name="Oracle" value="oracle"/>
<property name="SQL Server" value="sqlserver"/>
</databaseIdProvider>
• mapper逐个注册SQL映射文件
<mappers>
<mapper resource="mybatis/mapper/EmployeeMapper.xml"/>
<mapper url="file:///D:UserDao.xml"/>
<mapper class="com.mybatis.dao.EmployeeMapperAnnotation"/>
<mappers/>
• 或者使用批量注册:
• 这种方式要求SQL映射文件名必须和接口名相同并且在同一目录下
<mappers>
<package name="com.mybatis.dao"/>
<mappers/>
注册接口
class:引用(注册)接口,
1、有sql映射文件,映射文件名必须和接口同名,并且放在与接口同一目录下;
2、没有sql映射文件,所有的sql都是利用注解写在接口上;
推荐:
比较重要的,复杂的Dao接口我们来写sql映射文件
不重要,简单的Dao接口为了开发快速可以使用注解。
映射文件指导着MyBatis如何进行数据库增删改查,有着非常重要的意义。
•cache –命名空间的二级缓存配置
•cache-ref – 其他命名空间缓存配置的引用。
•resultMap – 自定义结果集映射
•parameterMap – 已废弃!老式风格的参数映射
•sql –抽取可重用语句块。
•insert – 映射插入语句
•update – 映射更新语句
•delete – 映射删除语句
•select – 映射查询语句
主键生成方式:
Select元素来定义查询操作。
• constructor - 类在实例化时, 用来注入结果到构造方法中
– idArg - ID 参数; 标记结果作为 ID 可以帮助提高整体效能
– arg - 注入到构造方法的一个普通结果
• id – 一个 ID 结果; 标记结果作为 ID 可以帮助提高整体效能
• result – 注入到字段或 JavaBean 属性的普通结果
• association – 一个复杂的类型关联;许多结果将包成这种类型
– 嵌入结果映射 – 结果映射自身的关联,或者参考一个
• collection – 复杂类型的集
– 嵌入结果映射 – 结果映射自身的集,或者参考一个
• discriminator – 使用结果值来决定使用哪个结果映射
– case – 基于某些值的结果映射
•嵌入结果映射 – 这种情形结果也映射它本身,因此可以包含很多相同的元素,或者它可以参照一个外部的结果映射。
id 和 result 映射一个单独列的值到简单数据类型(字符串,整型,双精度浮点数,日期等)的属性或字段。
association-嵌套结果集:
<resultMap type="com.bean.Lock" id="myLock">
<id column="id" property="id"/>
<result column="lock_name" property="lockName"/>
<association property="key" javaType="com.bean.Key">
<id column="key_id" property="id"/>
<result column="key_name" property="keyName"/>
</association>
</resultMap>
association-分段查询:
<resultMap type="com.bean.Lock" id="myLock">
<id column="id" property="id"/>
<result column="lock_name" property="lockName"/>
<association property="key"
select="com.dao.KeyMapper.getKeyId"
column="key_id">
</association>
</resultMap>
select:调用目标的方法查询当前属性的值
column:将指定列的值传入目标方法
association-分段查询&延迟加载:
开启延迟加载和属性按需加载
<settings>
<setting name="LazyLoadingEnabled" value="true">
<setting name="aggressiveLazyLoading" value="false">
</settings>
Collection-集合类型&嵌套结果集:
<resultMap type="com.bean.Department" id="myDeptSetp">
<id column="id" property="id"/>
<result column="dept_name" property="deptName"/>
<collection property="emps" ofType="com.bean.Employee"
columnPrefix="e_">
<id column="id" property="id"/>
<result column="last_name" property="lastName"/>
<result column="emial" property="emial"/>
<result column="gender" property="gender"/>
</collection>
</resultMap>
Collection-分步查询:
<resultMap type="com.bean.Department" id="myDeptSetp">
<id column="id" property="id"/>
<result column="dept_name" property="deptName"/>
<collection property="emps"
select="com.dao.EmployeeMapper.getEmpsByDeptId"
column="id">
</collection>
</resultMap>
Collection-分步查询&延迟加载:
开启延迟加载和属性按需加载
<settings>
<setting name="LazyLoadingEnabled" value="true">
<setting name="aggressiveLazyLoading" value="false">
</settings>
<resultMap type="com.bean.Department" id="myDeptSetp">
<id column="id" property="id"/>
<result column="dept_name" property="deptName"/>
<collection property="emps"
select="com.dao.EmployeeMapper.getEmpsByDeptId"
column="{deptId=id}">
</collection>
</resultMap>
其中set是update语句中的set。
MySQL下批量保存:
MySQL下批量保存可以foreach遍历。
mysql支持values(),(),()语法。
这种方式需要数据库连接属性allowMultiQueries=true;
这种分号分隔多个sql可以用于其他的批量操作(删除,修改)
foreach:
两个内置参数:
mybatis默认还有两个内置参数:
_parameter:代表整个参数
单个参数:_parameter就是这个参数
多个参数:参数会被封装为一个map;_parameter就是代表这个map
_databaseId:如果配置了databaseIdProvider标签。_databaseId就是代表当前数据库的别名
bind:
bind 元素可以从 OGNL 表达式中创建一个变量并将其绑定到上下文。比如:
<select id="getEmpByLastNameLike" resultType="com.bean.Employee">
<bind name="myLastName" value="'%'+lastName+'%'"/>
select * from employee where last_name like #{myLastName}
</select>
抽取可重用的sql片段:
抽取可重用的sql片段方便后面引用
1、sql抽取:经常将要查询的列名,或者插入用的列名抽取出来方便引用
2、include来引用已经抽取的sql:
3、include还可以自定义一些property,sql标签内部就能使用自定义的属性
MyBatis 包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制。
缓存可以极大的提升查询效率。
• MyBatis系统中默认定义了两级缓存。
• 一级缓存和二级缓存。
– 1、默认情况下,只有一级缓存(SqlSession级别的缓存,也称为本地缓存)开启。
– 2、二级缓存需要手动开启和配置,他是基于namespace级别的缓存。
– 3、为了提高扩展性。MyBatis定义了缓存接口Cache。我们可以通过实现Cache接口来自定义二级缓存
一级缓存(local cache), 即本地缓存, 作用域默认为sqlSession。当 Session flush 或 close 后, 该Session 中的所有 Cache 将被清空。
• 本地缓存不能被关闭, 但可以调用 clearCache() 来清空本地缓存, 或者改变缓存的作用域.
• 在mybatis3.1之后, 可以配置本地缓存的作用域. 在 mybatis.xml 中配置
一级缓存演示&失效情况:
同一次会话期间只要查询过的数据都会保存在当前SqlSession的一个Map中
• 一级缓存失效的四种情况
– 1、不同的SqlSession对应不同的一级缓存
– 2、同一个SqlSession但是查询条件不同
– 3、同一个SqlSession两次查询期间执行了任何一次增删改操作
– 4、同一个SqlSession两次查询期间手动清空了缓存
• 二级缓存(second level cache),全局作用域缓存
• 二级缓存默认不开启,需要手动配置
• MyBatis提供二级缓存的接口以及实现,缓存实现要求POJO实现Serializable接口
• 二级缓存在 SqlSession 关闭或提交之后才会生效
• 使用步骤
– 1、全局配置文件中开启二级缓存
• <setting name=“cacheEnabled” value=“true”/>
– 2、需要使用二级缓存的映射文件处使用cache配置缓存
• <cache />
– 3、注意:POJO需要实现Serializable接口
缓存相关属性:
• eviction=“FIFO”:缓存回收策略:
• LRU – 最近最少使用的:移除最长时间不被使用的对象。
• FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
• SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
• WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
• 默认的是 LRU。
• flushInterval:刷新间隔,单位毫秒
• 默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新
• size:引用数目,正整数
• 代表缓存最多可以存储多少个对象,太大容易导致内存溢出
• readOnly:只读,true/false
• true:只读缓存;会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。
• false:读写缓存;会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是 false。
缓存有关设置:
• 1、全局setting的cacheEnable:
– 配置二级缓存的开关。一级缓存一直是打开的。
• 2、select标签的useCache属性:
– 配置这个select是否使用二级缓存。一级缓存一直是使用的
• 3、sql标签的flushCache属性:
– 增删改默认flushCache=true。sql执行以后,会同时清空一级和二级缓存。查询默认flushCache=false。
• 4、sqlSession.clearCache():
– 只是用来清除一级缓存。
• 5、当在某一个作用域 (一级缓存Session/二级缓存Namespaces) 进行了 C/U/D 操作后,默认该作用域下所 有 select 中的缓存将被clear。
•EhCache 是一个纯Java的进程内缓存框架,具有快速、精干等特点,是Hibernate中默认的CacheProvider。
• MyBatis定义了Cache接口方便我们进行自定义扩展。
• 步骤:
– 1、导入ehcache包,以及整合包,日志包ehcache-core-2.6.8.jar、mybatis-ehcache-1.0.3.jar
slf4j-api-1.6.1.jar、slf4j-log4j12-1.6.2.jar
– 2、编写ehcache.xml配置文件
– 3、配置cache标签
– <cache type=“org.mybatis.caches.ehcache.EhcacheCache”></cache>
• 参照缓存:若想在命名空间中共享相同的缓存配置和实例。可以使用 cache-ref 元素来引用另外一个缓存
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 指定mybatis全局配置文件位置 -->
<property name="configLocation" value="classpath:mybatis/mybatis-config.xml"></property>
<!--指定数据源 -->
<property name="dataSource" ref="dataSource"></property>
<!--mapperLocations:所有sql映射文件所在的位置 -->
<property name="mapperLocations" value="classpath:mybatis/mapper/*.xml"></property>
<!--typeAliasesPackage:批量别名处理-->
<property name="typeAliasesPackage" value="com.atguigu.bean"></property>
</bean>
<!--自动的扫描所有的mapper的实现并加入到ioc容器中 -->
<bean id="configure" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!– basePackage:指定包下所有的mapper接口实现自动扫描并加入到ioc容器中 -->
<property name="basePackage" value="com.atguigu.dao"></property>
</bean>
本文地址:https://blog.csdn.net/weixin_41005188/article/details/107438362
如对本文有疑问, 点击进行留言回复!!
SpringBoot引用阿里easyexcel,Excel导出返回浏览器下载
HashMap、Hashtable、ConcurrentHashMap三者间的异同
解决RecycleView 中Item包含Edittext时,滑动view复用导致数据错乱的问题
多线程、同步工作原理、死锁案例、Lock接口、线程的生命周期的讲解及实现
网友评论