1.Mybatis解决jdbc编程的问题
1、 数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。
解决:在SqlMapConfig.xml中配置数据链接池,使用连接池管理数据库链接。
2、 Sql语句写在代码中造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码。
解决:将Sql语句配置在XXXXmapper.xml文件中与java代码分离。
3、 向sql语句传参数麻烦,因为sql语句的where条件不一定,可能多也可能少,占位符需要和参数一一对应。
解决:Mybatis自动将java对象映射至sql语句,通过statement中的parameterType定义输入参数的类型。
4、 对结果集解析麻烦,sql变化导致解析代码变化且解析前需要遍历,如果能将数据库记录封装成pojo对象解析比较方便。
解决:Mybatis自动将sql执行结果映射至java对象,通过statement中的resultType定义输出结果的类型。
2. Mybatis与hibernate区别
1. Mybatis和hibernate不同,它不完全是一个ORM框架,因为MyBatis需要程序员自己编写Sql语句,
不过mybatis可以通过 XML或注解方式灵活配置要运行的sql语句,并将java对象和sql语句映射生成最终执行的sql,
最后将sql执行的结果再映射生成java对象。
2. Mybatis学习门槛低,简单易学,程序员直接编写原生态sql,可严格控制sql执行性能,灵活度高,
非常适合对关系数据模型 要求不高的软件开发,例如互联网软件、企业运营类软件等,因为这类软件需求变化频繁,
一但需求变化要求成果输出迅速。但是灵活的前提是mybatis无法做到数据库无关性,如果需要实现支持多种数据库的软件
则需要自定义多套sql映射文件,工作量大。
3. Hibernate对象/关系映射能力强,数据库无关性好,对于关系模型要求高的软件(例如需求固定的定制化软件)
如果用 hibernate开发可以节省很多代码,提高效率。但是Hibernate的学习门槛高,要精通门槛更高,
而且怎么设计O/R映射,在性能和对象模型之间如何权衡,以及怎样用好Hibernate需要具有很强的经验和能力才行。
4. 总之按照用户的需求在有限的资源环境下只要能做出维护性、扩展性良好的软件架构都是好架构,所以框架只有适合才是最好
3.Mybatis中重要类介绍
1 SqlSessionFactoryBuilder
SqlSessionFactoryBuilder用于创建SqlSessionFacoty,SqlSessionFacoty一旦创建完成就不需要SqlSessionFactoryBuilder
因为SqlSession是通过SqlSessionFactory生产,所以可以将SqlSessionFactoryBuilder当成一个工具类使用,
最佳使用范围是方法范围即方法体内局部变量。
2. SqlSessionFactory
SqlSessionFactory是一个接口,接口中定义了openSession的不同重载方法,SqlSessionFactory的最佳使用范围是整个
应用运行期间,一旦创建后可以重复使用,通常以单例模式管理SqlSessionFactory。
并且数据库连接池是在SqlSessionFactory中设置的,还可以设置多种拦截器,比如说 分页拦截器
3.SqlSession
SqlSession是一个面向用户的接口, sqlSession中定义了数据库操作方法。
每个线程都应该有它自己的SqlSession实例。SqlSession的实例不能共享使用,它也是线程不安全的。因此最佳的范围是
请求 或方法范围。绝对不能将SqlSession实例的引用放在一个类的静态字段或实例字段中。
打开一个 SqlSession;使用完毕就要关闭它。通常把这个关闭操作放到 finally 块中以确保每次都能执行关闭。如下:
SqlSession session =sqlSessionFactory.openSession();
try {
// do work
} finally {
session.close();
}
使用范围:
SqlSession中封装了对数据库的操作,如:查询、插入、更新、删除等。
通过SqlSessionFactory创建SqlSession,而SqlSessionFactory是通过SqlSessionFactoryBuilder进行创建。
4.SqlMapConfig.xml
SqlMapConfig.xml是mybatis核心配置文件,上边文件的配置内容为数据源、事务管理。并且定义的映射文件也需要添加在这里面
SqlMapConfig.xml中配置的内容和顺序如下:
properties(属性)
settings(全局配置参数)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境集合属性对象)
environment(环境子属性对象)
transactionManager(事务管理)
dataSource(数据源)
mappers(映射器)
5 输入映射和输出映射
Mapper.xml映射文件中定义了操作数据库的sql,每个sql是一个statement,映射文件是mybatis的核心。
1. parameterType:定义输入到sql中的映射类型,#{id}表示使用preparedstatement设置占位符号并将输入变量id传到sql。
传递pojo对象,Mybatis使用ognl表达式解析对象字段的值,#{}或者${}括号中的值为pojo属性名称。
${value}表示使用参数将${value}替换,做字符串的拼接。如果是取简单数量类型的参数,
括号中的值必须为value名称
2. reulstType: 输出简单类型必须查询出来的结果集有一条记录,最终将第一个字段的值转换为输出类型。
3. resultMap:
resultType可以指定pojo将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名一致方可映射成功。
如果sql查询字段名和pojo的属性名不一致,可以通过resultMap将字段名和属性名作一个对应关系 ,
resultMap实质上还需要将查询结果映射到pojo对象中。
resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list实现一对一查询和一对多查询。
4. 自定义resultMap:可以在type里面写出要映射的类,字段名对应类的成员属性
<id />:此属性表示查询结果集的唯一标识,非常重要。如果是多个字段为复合唯一约束则定义多个<id />。
Property:表示User类的属性。
Column:表示sql查询出来的字段名。
Column和property放在一块儿表示将sql查询出来的字段映射到指定的pojo类属性上。
<result />:普通结果,即pojo的属性。
#{}表示一个占位符号,通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换,#{}可以有效防止
sql注入。 #{}可以接收简单类型值或pojo属性值。如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。
${}表示拼接sql串,通过${}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换, ${}可以接收简单类型值或
pojo属性值如果parameterType传输单个简单类型值,${}括号中只能是value。
#{} 的参数替换是发生在 DBMS 中,而 ${} 则发生在动态解析过程中。
6. Mybatis的常用功能:
1. mysql自增主键返回:
添加selectKey实现将主键返回
keyProperty:返回的主键存储在pojo中的哪个属性
order:selectKey的执行顺序,是相对与insert语句来说,由于mysql的自增原理执行完insert语句之后才将主键生成,
所以这里selectKey的执行顺序为after
resultType:返回的主键是什么类型
LAST_INSERT_ID():是mysql的函数,返回auto_increment自增列新记录id值。
2. 使用UUID作为主键
注意这里使用的order是“BEFORE”
<selectKeyresultType="java.lang.String" order="BEFORE" keyProperty="id">
select uuid()
</selectKey>
3. 通过mybatis提供的各种标签方法实现动态拼接sql。
例如:
<if test="username!=null and username!=''">
and username like '%${username}%'
</if>
<where />可以自动处理第一个and。
select * from user
<where>
<if test="username!=null and username!=''">
and username like '%${username}%'
</if>
</where>
向sql传递数组或List,mybatis使用foreach解析,如下:
<if test="ids!=null andids.size>0">
<foreach collection="ids" open=" and idin(" close=")"item="id" separator=",">
#{id}
</foreach>
</if>
4. sql片段
Sql中可将重复的sql提取出来,使用时用include引用即可,最终达到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引用:
<selectid="findUserList" parameterType="user"resultType="user">
select * from user
<where>
<include refid="query_user_where"/>
</where>
</select>
注意:如果引用其它mapper.xml的sql片段,则在引用时需要加上namespace,如下:
<include refid="namespace.sql片段”/>
5.关联查询
①.关联查询中 : 简单做法定义一个pojo类: 包含两个表内的信息
②. 一对一关联查询可以使用association完成关联查询,将关联查询信息映射到pojo对象中。
association:表示进行关联查询单条记录
property:表示关联查询的结果存储在cn.itcast.mybatis.po.Orders的user属性中
javaType:表示关联查询的结果类型
<id property="id" column="user_id"/>:查询结果的user_id列对应关联对象的id属性,
这里是<id />表示user_id是关联查询对象 的唯一标识。
<result property="username"column="username"/>:查询结果的username列对应关联对象的username属性。
③ 一对多查询
collection部分定义了用户关联的订单信息。表示关联查询结果集
property="orders":关联查询的结果集存储在User对象的上哪个属性。
ofType="orders":指定关联查询的结果集中的对象类型即List中的对象类型。此处可以使用别名,也可以使用全限定名。
<id />及<result/>的意义同一对一查询。
<!-- 一对多关联映射 -->
<collection property="orders" ofType="orders">
<id property="id" column="oid"/>
<!--用户id已经在user对象中存在,此处可以不设置-->
<!-- <result property="userId" column="id"/> -->
<result property="number" column="number"/>
<result property="createtime" column="createtime"/>
<result property="note" column="note"/>
</collection>
案例:查询所有用户信息及用户关联的订单信息。
7.Mapper动态代理方式
1. Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,
代理对象的方法体同上边Dao接口实现类方法。
2.动态代理对象调用sqlSession.selectOne()和sqlSession.selectList()是根据mapper接口方法的返回值决定,如果返回list则调用
selectList方法,如果返回单个对象则调用selectOne方法。
8.判断重复区间的,mybatis的大于等于
SELECT * FROM YourTable b WHERE (a.开始 <= b.结束 AND a.开始 > =b.开始)
OR (a.结束 >= b.开始 AND a.结束 <= b.结束)
第一种写法(1):
原符号 < <= > >= & ' "
替换符号 < <= > >= & ' "
例如:sql如下:
create_date_time >= #{startTime} and create_date_time <= #{endTime}
第二种写法(2):
大于等于
<![CDATA[ >= ]]>
小于等于
<![CDATA[ <= ]]>
例如:sql如下:
create_date_time <![CDATA[ >= ]]> #{startTime} and create_date_time <![CDATA[ <= ]]> #{endTime}
9. mybatis支持别名: typeAliases(类型别名) 也可以自定义
别名 |
映射的类型 |
_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 |
map |
Map |