mybatis框架是什么?
mybatis框架是一个优秀的持久层框架,它支持定制化SQL,存储过程以及高级映射。简单点说,mybatis框架的作用就是对数据库的数据进行增删改查。然后相应的框架或者工具非常多,为什么我们要选择mybatis呢?一方面是因为mybatis上手比较简单,所以对于开发过程来说也简单很多。同时他也能与Spring进行较好的融合。
Spring与mybatis的整合
1.首先我们需要在pom.xml中引入所需要的jar包,如下所示:
<!--spring的三个核心依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<!--mybatis依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.4</version>
</dependency>
<!--mybatis整合spring依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
<!--数据库驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.41</version>
</dependency>
首先解释一下各个jar包的作用:
Spring的三个核心依赖:是Spring框架必备的核心基础包;
mybatis依赖:是mybatis框架对应的jar包;
mybatis整合spring依赖:MyBatis-Spring 会帮助你将 MyBatis 代码无缝地整合到 Spring 中。它将允许 MyBatis 参与到 Spring 的事务管理之中,创建映射器 mapper 和 SqlSession 并注入到 bean 中,以及将 Mybatis 的异常转换为 Spring 的 DataAccessException。最终,可以做到应用代码不依赖于 MyBatis,Spring 或 MyBatis-Spring。
数据库驱动:关于数据库驱动,我们都知道是需要连接数据库的必须jar包,之所以是必须,是因为该jar包本质上还是软件代码,其主要作用是计算机系统与硬件设备之间完成数据传送的功能,只有借助驱动程序,两者才能通信并完成特定的功能。
2.接下来我们就需要通过业务需求分析在mysql中创建我们的数据库表,完成我们的表设计。完成表设计以后我们就可以通过使用mybatis-generator工具来生成对应的entity、dao,以及dao对应的xml文件。
3.上述两步完成以后我们就要进行今天的核心内容,Spring与myatis的整合
我们一直讲Spring与mybatis的整合,那我们为什么要对spring与mybatis进行整合呢?有什么好处呢?整合的原理是什么呢?
在实际开发中我们一般是直接在service的impl代码中直接通过spring的DI注入mybatis 的dao对象既然要注入dao对象,那么dao就必须要在Spring容器中,也就是说需要Spring容器帮助我们去创建dao对象。我们知道mybatis框架创建代理对象,首先要加载主配置文件,构建sqlSessionFactory对象,只有创建的sqlSessionFactory对象mybatis才能进行后续的操作。也就是说我们进行Spring与mybatis的整合,需要的做的就是使Spring去创建sqlSessionFacetory对象。关于在Spring中创建sqlSessionFactory对象,如下所示:
<!--数据库连接池-->
<!--加载配置文件-->
<context:property-placeholder location="classpath:conf/jdbc.properties"/>
<!-- 配置数据源 -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="123456"/>
</bean>
<!-- 配置mybatis的sqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- 自动扫描mappers.xml文件 -->
<property name="mapperLocations" value="classpath:mapper/*.xml"/>
<!-- mybatis配置文件 -->
<property name="configLocation" value="classpath:conf/mybatis-config.xml"/>
</bean>
<!-- DAO接口所在包名,Spring会自动查找其下的类 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.myself.study.dao" />
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>
首先,加载properties文件,即数据库的配置文件,然后进行数据源的配置;
第二步,配置mybatis的sqlSessionFactory,并配置相应的参数属性,其中包括数据源、dao对应的xml文件位置、mybatis的配置文件。
第三步,配置mybatis-spring的jar包下的MapperScannerConfigurer类的bean属性,spring会自动查找该配置下的类;配置的属性参数扫描dao包的位置,以及上述配置的sqlSessionFactory的bean对象;
至此,spring与mybatis 的整合就完成了;
Mybatis的标签
通过上述配置,我们就完成了Spring与mybatis 的整合;接下来就说一下mybatis中常用的一些标签;
select 标签的使用
属性介绍:
id :唯一的标识符.
parameterType:传给此语句的参数的全路径名或别名 例:com.test.poso.User或user
resultType :语句返回值类型或别名。注意,如果是集合,那么这里填写的
是集合的泛型,而不是集合本身(resultType 与resultMap 不能并用)
例子:
sql:
<select id="userList" parameterType="user" resultType="User">
select * from user where name =#{name}
</select>
在select标签中返回结果除了使用resultType还有一个属性:resultMap,resultMap的作用是建立sql查询结果字段与实体属性的映射关系,查询的结果转换为Java对象方便进一步操作,栗子如下:
<resultMap id="getStudentRM" type="EStudnet">
<id property="id" column="ID"/>
<result property="studentName" column="Name"/>
<result property="studentAge" column="Age"/>
</resultMap>
<select id="getStudent" resultMap="getStudentRM">
SELECT ID, Name, Age
FROM TStudent
</select>
column对应的属性为sql查询结果的列,而prperty对应的为对应对象的属性值
insert 标签的使用
属性介绍:
id :唯一的标识符
parameterType:传给此语句的参数的全路径名或别名
delete 标签的使用
<delete id="deleteUser" parameterType="int">
delete from user
where id = #{id}
</delete>
update 标签的使用
类似于insert
if 标签的使用
<select id=" getStudentListLikeName " parameterType="StudentEntity" resultMap="studentResultMap">
SELECT * from STUDENT_TBL ST
<if test="studentName!=null and studentName!='' ">
WHERE ST.STUDENT_NAME LIKE CONCAT(CONCAT('%', #{studentName}),'%')
</if>
</select>
foreach 标签的使用
forearch标签的使用我有一片专门的文章介绍用法;
mybatis传入多个参数以及List集合参数
where标签的使用
<!-- 查询学生list,like姓名,=性别 -->
<select id="getStudentListWhere" parameterType="StudentEntity" resultMap="studentResultMap">
SELECT * from STUDENT_TBL ST
<where>
<if test="studentName!=null and studentName!='' ">
ST.STUDENT_NAME LIKE CONCAT(CONCAT('%', #{studentName}),'%')
</if>
<if test="studentSex!= null and studentSex!= '' ">
AND ST.STUDENT_SEX = #{studentSex}
</if>
</where>
</select>
sql标签的使用
sql元素标签用来定义可重复使用的SQL代码片段,使用时只需要用include元素标签引用即可,最终达到SQL语句重用的目的;同时它可以被静态地(在加载参数) 参数化,不同的属性值通过包含的实例变化,比如:
//建立sql片段
<sql id="query_user_where">
<if test="id!=null and id!=''">
and id=#{id}
</if>
<if test="username!=null and username!=''">
and username like '%${username}%'
</if>
</sql>
//使用include引用sql片段
<select id="findUserList" parameterType="user" resultType="user">
select * from user
<where>
<include refid="query_user_where"/>
</where>
</select>
//引用其它mapper.xml的sql片段
<include refid="namespace.sql片段"/>
属性值也可以被用在 include 元素的 refid 属性里
<include refid="${include_target}"/>
属性值也可以被用在include 内部语句中
<sql id="sometable">
${prefix}Table
</sql>
<sql id="someinclude">
from
<include refid="${include_target}"/>
</sql>
<select id="select" resultType="map">
select
field1, field2, field3
<include refid="someinclude">
<property name="prefix" value="Some"/>
<property name="include_target" value="sometable"/>
</include>
</select>
Mybatis一级缓存与二级缓存
-
mybatis一级缓存
mybatis的一级缓存是sqlsession级别的,也就是说sqlsession只能访问自己的一级缓存数据,一级缓存查询存在于sqlsession类的对象实例中,当第一次查询某一个数据的时候,sqlsession类的实例对象会将数据存入到一级缓存,这样就可以在没有收到改变数据的请求之前,我们所查询的数据都是从缓存中获取的,这样就大大减少了数据库的频繁查询。总结:(1)在同一个 SqlSession 中, Mybatis 会把执行的方法和参数通过算法生成缓存的键值, 将键值和结果存放在一个 Map 中, 如果后续的键值一样, 则直接从 Map 中获取数据;(2)不同的 SqlSession 之间的缓存是相互隔离的;(3)用一个 SqlSession, 可以通过配置使得在查询前清空缓存;(4)任何的 UPDATE, INSERT, DELETE 语句都会清空缓存。 -
mybatis二级缓存
MyBatis的一级缓存是默认开启的,不需要我们任何配置;当我们将spring与mybatis整合以后,mybatis的一级缓存就自动失效了;但是并不是真正的失效;而二级缓存默认关闭的,想要开启二级缓存,我们得去SqlConfig.xml文件配置setting属性,把name设置cacheEnable以及value设置为ture,因为由于二级缓存是mapper级别的,所以我还需要开启二级缓存,在具体的mapper.xml文件添加一个cache标签即可。
原理如下:
第一次调用mapper下的SQL去查询用户信息。查询到的信息会存到该mapper对应的二级缓存区域内。第二次调用相同namespace下的mapper映射文件中相同的SQL去查询用户信息。会去对应的二级缓存内取结果。如果调用相同namespace下的mapper映射文件中的增删改SQL,并执行了commit操作。此时会清空该namespace下的二级缓存。
默认二级缓存的粒度是Mapper级别的,但是如果在同一个Mapper文件中某个查询不想使用二级缓存的话,就需要对缓存的控制粒度更细。
默认设置
* 当为select语句时:flushCache默认为false,表示任何时候语句被调用,都不会去清空本地缓存和二级缓存。useCache默认为true,表示会将本条语句的结果进行二级缓存。
* 当为insert、update、delete语句时:flushCache默认为true,表示任何时候语句被调用,都会导致本地缓存和二级缓存被清空。useCache属性在该情况下没有。
默认配置解读
*如果查询语句设置成true,那么每次查询都是去数据库查询,即意味着该查询的二级缓存失效。
*如果增删改语句设置成false,即使用二级缓存,那么如果在数据库中修改了数据,而缓存数据还是原来的,这个时候就会出现脏读。
flushCache与useCache设置示例如下:
<selectid="findUserById"parameterType="int"
resultType="com.kkb.mybatis.po.User"useCache="true"flushCache="true">
SELECT * FROM user WHERE id =#{id}
</select>
Mybatis的批量操作
关于mybatis进行批量新增,目前常用的有三种方法:
- 使用for循环,多次调用dao接口进行批量inset、update、delete操作
- 使用list结构传入多个参数,然后在mybatis的xml文件中使用forEach标签拼装sql语句进行批量新增;
- 基于mybatis的SqlSession的ExecutorType做批量操作。
三种方法,第一种的方法会耗费大量的数据库连接资源,性能肯定是最差的,并不适合做大批量的新增操作;而第二种方法,如果数据量过大,则会拼装过长的sql语句,造成CPU的飙升。而第三种方法的性能则优于第二种。