jdbc连接数据库存在的问题
数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。
Sql语句在代码中硬编码,造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码。
使用preparedStatement向占有位符号传参数存在硬编码,因为sql语句的where条件不一定,可能多也可能少,修改sql还要修改代码,系统不易维护。
对结果集解析存在硬编码(查询列名),sql变化导致解析代码变化,系统不易维护,如果能将数据库记录封装成pojo对象解析比较方便。
mybatis介绍
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis,实质上Mybatis对ibatis进行一些改进。
MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。
Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。
mybatis环境搭建
加入mybatis核心包、依赖包、数据驱动包。maven(jar包)
1 | asm、cglib、commons-logging、javassist、junit、log4j、log4j-api、 |
配置log4j,src下创建log4j.properties
1 | # Global logging configuration |
SqlMapConfig.xml基础配置
SqlMapConfig.xml是mybatis核心配置文件,下面文件的配置内容为数据源、事务管理。
1 |
|
创建mapper映射文件
创建pojo模型,创建映射文件,映射文件基础配置如下:
1 |
|
其中namespace为命名空间,用于隔离sql语句。
加入以下代码完成查询配置
1 | <!-- select 查询标签 需要 返回类类型resultType parameterType代表输入类型(可选)--> |
在SqlMapConfig.xml中加载映射文件
1 | <!-- 配置映射文件 --> |
执行查询操作
1 | //获取配置文件 |
#{}与${}的区别
#{}表示一个占位符号,通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换,#{}可以有效防止sql注入。 #{}可以接收简单类型值或pojo属性值。 如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。
${}表示拼接sql串,通过${}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换, ${}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是value。
Mybatis增删改
1 | 添加一条数据 |
原始dao开发
编写dao接口(开发中直接提交到版本控制服务器上,其他人可继续开发)
编写dao实现类,实现dao里面的方法,完成功能开发
原始dao开发中存在以下问题
Dao方法体存在重复代码:通过SqlSessionFactory创建SqlSession,调用SqlSession的数据库操作方法
调用sqlSession的数据库操作方法需要指定statement的id,这里存在硬编码,不得于开发维护。
mapper动态代理
Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。(也就是说不需要写实现类)
但Mapper接口开发必需遵循以下规范://sqlSession.getMapper();
1、Mapper.xml文件中的namespace与mapper接口的类路径相同。
2、Mapper接口方法名和Mapper.xml中定义的每个statement的id相同
3、Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同
4、Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同
动态sql-if
1 | if为select标签下子标签表示判断,属性test表示判断条件 |
动态sql-where
1 | where为select标签下子标签,用来表示条件 |
sql片段
1 | Sql中可将重复的sql提取出来,使用时用include引用即可,最终达到sql重用的目的,如下 |
高级映射一对一
首先确定sql语句,确定要查询的列
根据sql语句完成扩展domain类的建立,继承主domain类,将查询的列中不包含在主类中的列名加到扩展domain类中
映射文件输出类型为扩展domain类
定义mapper接口中方法
Sql语句
1 | SELECT o.*,u.username,u.pwd,u.sex,u.age FROM orders o,USER u WHERE o.user_id = u.id AND o.id = 1 |
定义pojo扩展类
1 | public class OrdersCustem extends Orders { |
确定返回类型
1 | resultType="cn.com.aly.po.OrdersCustem" |
定义mapper接口中方法
1 | OrdersCustem selOrdersWithUserById(Orders orders); |
高级映射一对多
首先确定sql语句,确定要查询的列,并将多方创建成list放入一方
根据sql语句完成resultMap的建立,association为一对一的配置,collection为一对多,多方配置
映射文件输出使用resultMap,并将值设置为刚建立的resultMap的id
定义mapper接口中方法
1 | sql语句 |
创建resultMap
1 | <!-- id :下面使用到该resultMap的时候所写的值 type规定当前类是那一个 --> |
确定返回类型
1 | resultMap="resultofuser" |
定义mapper接口中方法
1 | User selUserWithOrdersById(User user); |
高级映射多对多
多对多映射实质为:一对一与一对多的整合,同样使用resultMap,灵活使用association和collection。
association将关联查询信息映射到一个pojo对象中。
collection将关联查询信息映射到一个list集合中。
注意:如果使用resultType则无法关联查询
高级映射延迟加载
需要查询关联信息时,使用mybatis延迟加载特性可有效的减少数据库压力,首次查询只查询主要信息,关联信息等用户获取时再加载。
设置项 | 描述 | 允许值 | 默认值 |
---|---|---|---|
lazyLoadingEnabled | 全局性设置懒加载。如果设为‘false’,则所有相关联的都会被初始化加载 | true、false | false |
aggressiveLazyLoading | 当设置为‘true’的时候,懒加载的对象可能被任何懒属性全部加载。否则,每个属性都按需加载 | true、false | true |
1 | <settings> |
应用时需要在association或collection指定javaType(关联结果映射位置),select(指定关联查询sql),column(需要传入的值)
1 | <resultMap id="resultforlazy" type="cn.com.aly.po.Orders"> |