Mybatis
原生态jdbc程序中问题总结
- 数据库连接,使用时创建,不使用立即释放,对数据库进行频繁连接开启和关闭,造成数据库资源浪费,影响数据库性能
解决方案:使用数据库连接池管理数据连接
- 将sql语句硬编码到java代码,如果sql语句修改,需要重新编译java代码,不利于系统维护
设想:将sql语句配置在xml配置文件中,即使sql变化,不需要java代码进行重新编译
- 向prepareStatement中设置参数,对占位符和设置参数值,硬编码在java代码中,不利于系统维护
设想:将sql语句及占位符和参数全部配置在xml中
- 从resultSet中遍历结果集时,存在硬编码,将获取表的字段进行硬编码,不利于系统维护
设想:将查询的结果集,自动映射成java对象
Mybatis框架
- 持久层框架
- mybatis让程序员将主要精力放在sql上,通过mybatis提供的映射方式,自由灵活生成(半自动化,大部分需要程序员编写sql),满足需要sql语句
- 可将向prepareStatement中的输入参数自动进行输入映射,将查询结果集灵活映射成java对象(输出映射)
入门程序
sqlMapConfig
根据用户id(主键)查询用户信息
创建po类
映射文件
映射文件命名:
User.xml(原始ibatis命名),mapper代理开发映射文件名称叫XXXMapper.xml
在映射文件中配置sql语句
在sqlMapConfig.xml中配置映射文件
程序编写
根据用户名称模糊查询用户信息
添加用户
- 自增主键返回
通过mysql函数获取到刚插入记录的自增主键:
LAST_INSERT_ID()
是insert之后调用此函数
- 非自增主键返回(使用uuid())
删除用户
更新用户
总结
- parameterType
在映射文件中通过parameterType指定输入参数类型
- resultType
指定输出参数类型
#{}和${}
#{}表示一个占位符号,#{}接收输入参数,类型可以是简单类型,pojo,hashmap
如果接受简单类型,#{}中可以写成value或其他名称
#{}接收pojo对象值,通过OGNL读取对象中的属性值
{}
${}接收输入参数,类型可以是简单类型,pojo,hashmap
如果接受简单类型,${}中只能写成value
${}接收pojo对象值,通过OGNL读取对象中的属性值
selectOne和selectList
selectOne表示查询一条记录进行映射,如果使用selectOne可以实现使用selectList也可以实现(list中只有一个对象)
selectList表示查询一个列表(多条记录)进行映射,如果使用selectLIst查询多条记录,不能使用selectOne
mybatis和hibernate本质区别和应用场景
hibernate:标准ORM(对象关系映射)框架入门门槛高,不需要程序写sql,sql自动生成
对sql语句进行优化、修改比较困难
应用场景:
适用于需求变化不多的中小型项目,比如:后台管理系统,erp,orm,oa
mybatis:专注sql本身,需要程序员编写sql语句,sql修改、优化比较方便。mybatis是一个不完全的ORM框架,虽然程序员自己写sql,mybatis也可以实现映射(输入映射、输出映射)
应用场景:
适用于需求变化较多的项目,比如:互联网项目
企业进行技术选型,以低成本,高回报作为技术选型的原则,适用项目组的技术力量进行选择。
mybatis开发dao的方法
SqlSession使用范围
- SqlSessionFactoryBuilder
通过SqlSessionFactoryBuilder创建会话工厂SqlSessionFactory
在需要创建sqlSessionFactory时候,new一个Builder即可
- SqlSessionFactory
通过SqlSessionFactory创建SqlSession,使用单例模式管理sqlSessionFactory(工厂一旦创建,使用一个实例)
将来mybatis和spring整合后,使用单例模式管理sqlSessionFactory
- SqlSession
SqlSession是一个面向程序员的接口
sqlSession线程不安全,在SqlSession实现类中除了有接口中的方法(操作数据库的方法)还有数据域属性
SqlSession最佳应用场合在方法体内,定义成局部变量使用
原始dao开发方法(程序员写dao接口和dao实现类)
- 思路
需要向dao实现类中注入SqlSessionFactory,在方法体内通过SqlSessionFactory创建SqlSession
- dao接口
- dao接口实现类
- 测试代码
- 原始dao开发问题
- dao接口实现类方法中存在大量模版方法,设想能否将这些代码提取出来,减轻工作量
- 调用sqlsession方法时将statement的id硬编码了
- 调用sqlsession方法时传入的变量,由于sqlsession方法使用泛型,即使变量类型传入错误,在编译阶段也不报错,不利于程序员开发
Mapper代理方法
思路
程序员需要编写mapper映射文件
只需要编写mapper接口,遵循一些开发规范,mybatis可以自动生成mapper接口实现类代理对象
开发规范:
- 在mapper.xml中namespace等于mapper接口地址
- mapper.java接口的方法名和mapper.xml中statement的id一致
- mapper.java接口中的方法输入参数类型和mapper.xml中statement的parameterType指定的类型一致
- mapper.java接口中的方法返回值和mapper.xml中statement的resultType指定的类型一致
总结
以上开发规范主要对下边的代码进行统一的生成
代理对象内部调用selectOne或selectList
如果mapper方法返回单个pojo对象(非集合对象),代理对象内部通过selectOne查询数据库
如果mapper方法返回集合对象,代理对象内部通过selectList查询数据库
记得在SqlMapConfig.xml中加载mapper.xml
SqlMapConfig.xml
properties属性
需求:
将数据库连接参数单独配置在db.properties中,只需要在SqlMapConfig.xml中加载db.properties的属性值
在SqlMapConfig.xml中不需要数据库连接参数硬编码
将数据库连接参数只配置在db.properties中,原因是方便对参数进行统一管理,其他xml可以引用db.properties。
db.properties:
在SqlMapConfig加载属性文件:
建议:
不要在properties元素体内添加任何属性值,只将属性值定义在properties文件中
在properties文件中定义属性名要有一定的特殊性,如XXXX.XXXX
Settings全局参数配置
mybaits框架运行设置一些全局配置参数,比如:开启二级缓存 ,开启延迟加载。。。
在ibatis中有一些设置性能参数(最大线程数、最大请求数。。),在mybatis中没有这些性能参数。
注意:设置全局参数会影响mybatis框架运行,谨慎设置。
typeAliases(别名)
需求
在parameterType和resultType设置时,为了方便编码,定义别名代替pojo的全路径。
mybatis默认别名
别名 映射的类型
_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
- 定义别名
有定义单个别名也有批量定义别名
<!-- 定义别名 -->
<typeAliases>
<!-- 单个别名定义
type:pojo的路径
alias:别名的名称
-->
<!-- <typeAlias type="cn.itcast.mybatis.po.User" alias="user"/> -->
<!-- 批量别名定义
name:指定包名,将包下边的所有pojo定义别名 ,别名为类名(首字母大写或小写都行)
-->
<package name="cn.itcast.mybatis.po"/>
</typeAliases>
使用别名,在下面中返回值使用的是别名
<select id="findUserById" parameterType="int" resultType="user">
SELECT * FROM USER WHERE id = #{id}
</select>
typeHandlers(类型处理器)
类型处理器用于java类型和jdbc类型映射:
Mybatis提供的类型处理器满足日常需要。
mappers(映射配置)
<mapper resource=" " />
使用相对于类路径的资源
如:<mapper resource="sqlmap/user.xml" />
批量加载mapper(常用)
输入映射
通过parameter指定输入参数的类型,类型可以是简单类型、hashmap、pojo的包装类型
传递pojo的包装对象
- 需求
完成用户信息的综合查询,需要传入查询条件复杂(可能包括用户信息、其他信息,比如商品、订单)
针对上边需求,建议使用自定义的包装类型的pojo
在包装类型的pojo中将复杂的查询条件包装进去
输出映射
- resultType
使用resultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功。
如果查询出来的列名和pojo中的属性名全部不一致,没有创建pojo对象
只要查询出来的列名和pojo中的属性有一个一致,就会创建pojo对象
输出pojo对象和pojo列表
不管输出的是单个对象还是一个列表(list中包括pojo),在mapper.xml中resultType指定的类型是一样的。在mapper.java中指定的返回值类型不一样
- resultMap
如果查询出来的列名和pojo属性吗不一致,通过定义一个resultMap对列名和pojo属性名之间进行一个映射关系。
- 定义resultMap
- 使用resultMap作为statement的输出映射类型
动态sql
- if判断
- sql片段
foreach
向sql传递数组或list,mybatis使用foreach解析
在用户查询列表和查询总数的statemen中增加多个id输入查询
sql语句如下:
两种方法:
select * from user where id=1 or id=10 or id=16
select * from user where ID in(1,10,16)