学习MyBatis
MyBatis简介:
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。 MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。
Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatement、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。
为什么学习MyBatis:
MyBatis解决了以下JDBC操作数据可能遇到的问题
1、数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。
2、Sql语句在代码中硬编码,造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码。
3、使用preparedStatement向占有位符号传参数存在硬编码,因为sql语句的where条件不一定,可能多也可能少,修改sql还要修改代码,系统不易维护。
4、对结果集解析存在硬编码(查询列名),sql变化导致解析代码变化,系统不易维护,如果能将数据库记录封装成pojo对象解析比较方便。
下载MyBatis
mybaits的代码由github.com管理,
下载好,解压后就是这样
在这里我用的编程软件是Eclipse,导入Eclipse项目
把解压好的文件内的lib目录下的所有包,加上mybatis-3.2.7.jar一起放图中这个目录下
在这里创建一个config目录(source folder类型)
创建这两个文件,log4j是日志文件,另一个是主配置文件
log4j文件内容如下:
#Global logging configuration
log4j.rootLogger=DEBUG, stdout
#Console output…
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.Cnotallow=%5p [%t] - %m%n
Driver:是你的驱动
URL:是你的连接数据库的路径
username:数据库用户名
password:数据库密码
现在可以开始写第一个MyBatis程序
设置类的set,get方法,之后创建一个该类的配置文件User.xml
mybatis框架需要加载映射文件,将User.xml添加在SqlMapConfig.xml
现在我们来写测试程序
这里的测试程序呢用到了,这个junit.jar这个包,来帮助我们测试
测试成功,现在我们在测试一下使用用户来进行查询
这里说一下获取值时的符号用法
说了查询,在说一下增加,增加呢,我在User这个类中,添加了一个构造方法用来初始化值
这个时User.xml配置文件内容,添加了一个返回自增主键的内容
这里新建了一个类User2
mapper动态代理
开发规范
Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。
Mapper接口开发需要遵循以下规范:
1、Mapper.xml文件中的namespace与mapper接口的类路径相同。
2、Mapper接口方法名和Mapper.xml中定义的每个statement的id相同
3、Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同
4、Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同
测试程序
最后强调
selectOne和selectList
动态代理对象调用sqlSession.selectOne()和sqlSession.selectList()是根据mapper接口方法的返回值决定,如果返回list则调用selectList方法,如果返回单个对象则调用selectOne方法。
namespace
mybatis官方推荐使用mapper代理方法开发mapper接口,程序员不用编写mapper接口实现类,使用mapper代理方法时,输入参数可以使用pojo包装对象或map对象,保证dao的通用性。
properties属性
SqlMapConfig.xml可以引用java属性文件中的配置
信息如下:
jdbc.driver=com.mysql.jdbc.Driver(驱动)
jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8(路径)
jdbc.username=root(用户名)
jdbc.password=root(密码)
SqlMapConfig.xml引用如下:
输入映射
parameterType(输入类型)
2.1.1传递简单类型
已讲。
2.1.2传递pojo对象
Mybatis使用ognl表达式解析对象字段的值,#{}或者${}括号中的值为pojo属性名称。
2.1.3传递pojo包装对象
开发中通过pojo传递查询条件 ,查询条件是综合的查询条件,不仅包括用户查询条件还包括其它的查询条件(比如将用户购买商品信息也作为查询条件),这时可以使用包装对象传递输入参数。
Pojo类中包含pojo。
需求:根据用户名查询用户信息,查询条件放到QueryVo的user属性中。
resultMap(单表一般都不用,一般都用resultType)
resultType可以指定pojo将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名一致方可映射成功。
如果sql查询字段名和pojo的属性名不一致,可以通过resultMap将字段名和属性名作一个对应关系 ,
resultMap实质上还需要将查询结果映射到pojo对象中。
resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list实现一对一查询
和一对多查询。
动态SQL语句
通过mybatis提供的各种标签方法实现动态拼接sql。
也可以改成这样
多表查询
商品订单数据模型
一对一查询
案例:查询所有订单信息,关联查询下单用户信息。
注意:因为一个订单信息只会是一个人下的订单,所以从查询订单信息出发关联查询用户信息为一对一查询。如果从用户信息出发查询用户下的订单信息则为一对多查询,因为一个用户可以下多个订单。
方法一:
使用resultType,定义订单信息po类,此po类中包括了订单信息和用户信息:
Sql语句:
SELECT orders.*,user.username,userss.address
FROM orders,user
WHERE orders.user_id = user.id
定义po类
Po类中应该包括上边sql查询出来的所有字段,如下:
public class OrdersCustom extends Orders {
private String username;// 用户名称
private String address;// 用户地址
get/set。。。。
OrdersCustom类继承Orders类后OrdersCustom类包括了Orders类的所有字段,只需要定义用户的信息字段即可。
测试:
Public void testfindOrdersList()throws Exception{
//获取session
SqlSession session = sqlSessionFactory.openSession();
//获限mapper接口实例
UserMapper userMapper = session.getMapper(UserMapper.class);
//查询订单信息
List list = userMapper.findOrdersList();
System.out.println(list);
//关闭session
session.close();
}
小结:
定义专门的po类作为输出类型,其中定义了sql查询结果集所有的字段。此方法较为简单,企业中使用普遍。
方法二:
使用resultMap,定义专门的resultMap用于映射一对一查询结果。
4.2.2.1Sql语句:
SELECT
orders.*,
user.username,
user.address
FROM
orders,
user
WHERE orders.user_id = user.id
定义po类
在Orders类中加入User属性,user属性中用于存储关联查询的用户信息,因为订单关联查询用户是一对一关系,所以这里使用单个User对象存储关联查询的用户信息。
一对多查询
案例:查询所有用户信息及用户关联的订单信息。
用户信息和订单信息为一对多关系。
使用resultMap实现如下:
Sql语句:
SELECT
u.*, o.id oid,
o.number,
o.createtime,
o.note
FROMuser
u
LEFT JOIN orders o ON u.id = o.user_id
定义po类
mapper.xml配置
Mapper接口:
List getUserOrderList();
测试
多对多(双向的一对多,了解):
查询所有订单信息及订单明细的商品信息
主查询表:订单表
关联查询表:用户表、订单明细表、商品表
SQL语句:
SELECT
orders.*,
user.username,
user.address,
orderdetail.id orderdetail_id,
orderdetail.item_id,
orderdetail.item_num,
orderdetail.item_price ,
items.item_detail,
items.item_name,
items.item_price item_price_price
FROM
orders,
USER,
orderdetail,
items
WHERE orders.user_id = user.id
AND orders.id = orderdetail.orders_id
AND orderdetail.item_id = items.id
resultMap可以相互继承