接着昨天的 MyBatis 入门程序来讲,今天我们来讲一下 MyBatis 的高级用法,例如动态 sql 查询,关联查询,整合 Spring 框架,希望对大家能有所帮助。
通过 mybatis 提供的各种标签方法实现动态拼接 sql。
- <!-- 传递pojo综合查询用户信息 -->
- <
- select
- id
- =
- "findUserList"
- parameterType
- =
- "user"
- resultType
- =
- "user"
- >
- select * from user
- where 1=1
- <if test="id!=null">
- and id=#{id}
- </if>
- <if test="username!=null and username!=''">
- and username like '%${username}%'
- </if>
- </select>
注意要做不等于空字符串校验。
上边的 sql 也可以改为:
- <select id="findUserList" parameterType="user" resultType="user">
- select * from user
- <where>
- <if test="id!=null and id!=''">
- and id=#{id}
- </if>
- <if test="username!=null and username!=''">
- and username like '%${username}%'
- </if>
- </where>
- </select>
可以自动处理第一个 and。
- <where />
向 sql 传递数组或 List,mybatis 使用 foreach 解析,如下:
传入多个 id 查询用户信息,用下边两个 sql 实现:
- SELECT * FROM USERS WHERE username LIKE '%张%' AND (id =10 OR id =89 OR id=16)
- SELECT * FROM USERS WHERE username LIKE '%张%' id IN (10,89,16)
- public class QueryVo {
- private User user;
- //自定义用户扩展类
- private UserCustom userCustom;
- //传递多个用户id
- private List < Integer > ids;
- }
- <if test="ids!=null and ids.size>0">
- <foreach collection="ids" open=" and id in(" close=")" item="id" separator=",">
- #{id}
- </foreach>
- </if>
- List < Integer > ids = new ArrayList < Integer > ();
- ids.add(1); //查询id为1的用户
- ids.add(10); //查询id为10的用户
- queryVo.setIds(ids);
- List < User > list = userMapper.findUserList(queryVo);
Sql 中可将重复的 sql 提取出来,使用时用 include 引用即可,最终达到 sql 重用的目的,如下:
- <!-- 传递pojo综合查询用户信息 -->
- <
- select
- id
- =
- "findUserList"
- parameterType
- =
- "user"
- resultType
- =
- "user"
- >
- select * from user
- <where>
- <if test="id!=null and id!=''">
- and id=#{id}
- </if>
- <if test="username!=null and username!=''">
- and username like '%${username}%'
- </if>
- </where>
- </select>
- <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>
- <select id="findUserList" parameterType="user" resultType="user">
- select * from user
- <where>
- <include refid="query_user_where" />
- </where>
- </select>
注意:如果引用其它 mapper.xml 的 sql 片段,则在引用时需要加上 namespace,如下:
- <include refid="namespace.sql片段"/>
案例:查询所有订单信息,关联查询下单用户信息。
注意:因为一个订单信息只会是一个人下的订单,所以从查询订单信息出发关联查询用户信息为一对一查询。如果从用户信息出发查询用户下的订单信息则为一对多查询,因为一个用户可以下多个订单。
方法一
使用 resultType,定义订单信息 po 类,此 po 类中包括了订单信息和用户信息:
- SELECT
- orders.*,
- user.username,
- user.address
- FROM
- orders,
- user
- WHERE orders.user_id = user.id
Po 类中应该包括上边 sql 查询出来的所有字段,如下:
- public
- class
- OrdersCustom
- extends
- Orders
- {
- private String username;// 用户名称
- private String address;// 用户地址
- get/set......
- }
OrdersCustom 类继承 Orders 类后 OrdersCustom 类包括了 Orders 类的所有字段,只需要定义用户的信息字段即可。
- <!-- 查询所有订单信息 -->
- <
- select
- id
- =
- "findOrdersList"
- resultType
- =
- "cn.zy.mybatis.po.OrdersCustom"
- >
- SELECT orders.*,user.username,user.address
- FROM orders,user
- WHERE orders.user_id = user.id
- </select>
- public List < OrdersCustom > findOrdersList() throws Exception;
- Public void testfindOrdersList() throws Exception {
- //获取session
- SqlSession session = sqlSessionFactory.openSession();
- //获限mapper接口实例
- UserMapper userMapper = session.getMapper(UserMapper.class);
- //查询订单信息
- List < OrdersCustom > list = userMapper.findOrdersList();
- System.out.println(list);
- //关闭session
- session.close();
- }
定义专门的 po 类作为输出类型,其中定义了 sql 查询结果集所有的字段。此方法较为简单,企业中使用普遍。
方法二
使用 resultMap,定义专门的 resultMap 用于映射一对一查询结果。
- SELECT
- orders.*,
- user.username,
- user.address
- FROM
- orders,
- user
- WHERE orders.user_id = user.id
在 Orders 类中加入 User 属性,user 属性中用于存储关联查询的用户信息,因为订单关联查询用户是一对一关系,所以这里使用单个 User 对象存储关联查询的用户信息。
- public class Orders {
- private Integer id;
- private Integer userId;
- private String number;
- private Date createtime;
- private String note;
- private User user;
- getter()、setter()方法......
- }
- <!-- 查询订单关联用户信息使用resultmap -->
- <
- resultMap
- type
- =
- "cn.itheima.po.Orders"
- id
- =
- "orderUserResultMap"
- >
- <
- id
- column
- =
- "id"
- property
- =
- "id"
- />
- <
- result
- column
- =
- "user_id"
- property
- =
- "userId"
- />
- <
- result
- column
- =
- "number"
- property
- =
- "number"
- />
- <
- result
- column
- =
- "createtime"
- property
- =
- "createtime"
- />
- <
- result
- column
- =
- "note"
- property
- =
- "note"
- />
- <!-- 一对一关联映射 -->
- <!--
- property:Orders对象的user属性
- javaType:user属性对应 的类型
- -->
- <
- association
- property
- =
- "user"
- javaType
- =
- "cn.itcast.po.User"
- >
- <!-- column:user表的主键对应的列 property:user对象中id属性-->
- <
- id
- column
- =
- "user_id"
- property
- =
- "id"
- />
- <
- result
- column
- =
- "username"
- property
- =
- "username"
- />
- <
- result
- column
- =
- "address"
- property
- =
- "address"
- />
- </association>
- </resultMap>
- <
- select
- id
- =
- "findOrdersWithUserResultMap"
- resultMap
- =
- "orderUserResultMap"
- >
- SELECT
- o.id,
- o.user_id,
- o.number,
- o.createtime,
- o.note,
- u.username,
- u.address
- FROM
- orders o
- JOIN `user` u ON u.id = o.user_id
- </select>
这里 resultMap 指定 orderUserResultMap。
association:表示进行关联查询单条记录
property:表示关联查询的结果存储在 cn.itcast.mybatis.po.Orders 的 user 属性中
javaType:表示关联查询的结果类型
:查询结果的 user_id 列对应关联对象的 id 属性,这里是表示 user_id 是关联查询对象的唯一标识。
- <id property="id" column="user_id"/>
:查询结果的 username 列对应关联对象的 username 属性。
- <result property="username" column="username"/>
- public List < Orders > findOrdersListResultMap() throws Exception;
- Public void testfindOrdersListResultMap() throws Exception {
- //获取session
- SqlSession session = sqlSessionFactory.openSession();
- //获限mapper接口实例
- UserMapper userMapper = session.getMapper(UserMapper.class);
- //查询订单信息
- List < Orders > list = userMapper.findOrdersWithUserResultMap();
- System.out.println(list);
- //关闭session
- session.close();
- }
使用 association 完成关联查询,将关联查询信息映射到 pojo 对象中。
案例:查询所有用户信息及用户关联的订单信息。
用户信息和订单信息为一对多关系。
使用 resultMap 实现如下:
- SELECT
- u.*, o.id oid,
- o.number,
- o.createtime,
- o.note
- FROM
- `user` u
- LEFT JOIN orders o ON u.id = o.user_id
在 User 类中加入
属性
- List<Orders> orders
- public class User {
- private Integer id;
- private String username;
- private String sex;
- private Date birthday;
- private String address;
- private List < Orders > orders;
- getter()、setter()方法......
- }
- <
- resultMap
- type
- =
- "cn.itheima.po.user"
- id
- =
- "userOrderResultMap"
- >
- <!-- 用户信息映射 -->
- <
- id
- property
- =
- "id"
- column
- =
- "id"
- />
- <
- result
- property
- =
- "username"
- column
- =
- "username"
- />
- <
- result
- property
- =
- "birthday"
- column
- =
- "birthday"
- />
- <
- result
- property
- =
- "sex"
- column
- =
- "sex"
- />
- <
- result
- property
- =
- "address"
- column
- =
- "address"
- />
- <!-- 一对多关联映射 -->
- <
- collection
- property
- =
- "orders"
- ofType
- =
- "cn.itheima.po.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>
- </resultMap>
- <
- select
- id
- =
- "getUserOrderList"
- resultMap
- =
- "userOrderResultMap"
- >
- SELECT
- u.*, o.id oid,
- o.number,
- o.createtime,
- o.note
- FROM
- `user` u
- LEFT JOIN orders o ON u.id = o.user_id
- </select>
collection 部分定义了用户关联的订单信息。表示关联查询结果集
property="orders":关联查询的结果集存储在 User 对象的上哪个属性。
ofType="orders":指定关联查询的结果集中的对象类型即 List 中的对象类型。此处可以使用别名,也可以使用全限定名。
及
- <id />
的意义同一对一查询。
- <result/>
- List < User > getUserOrderList();
- @Test
- public void getUserOrderList() {
- SqlSession session = sqlSessionFactory.openSession();
- UserMapper userMapper = session.getMapper(UserMapper.class);
- List<User> result = userMapper.getUserOrderList();
- for (User user : result) {
- System.out.println(user);
- }
- session.close();
- }
1、SqlSessionFactory 对象应该放到 spring 容器中作为单例存在。
2、传统 dao 的开发方式中,应该从 spring 容器中获得 sqlsession 对象。
3、Mapper 代理形式中,应该从 spring 容器中直接获得 mapper 的代理对象。
4、数据库的连接以及数据库连接池事务管理都交给 spring 容器来完成。
1、spring 的 jar 包
2、Mybatis 的 jar 包
3、Spring+mybatis 的整合包。
4、Mysql 的数据库驱动 jar 包。
5、数据库连接池的 jar 包。
第一步:创建一个 java 工程。
第二步:导入 jar 包。(上面提到的 jar 包)
第三步:mybatis 的配置文件 sqlmapConfig.xml
第四步:编写 Spring 的配置文件
1、数据库连接及连接池
2、事务管理(暂时可以不配置)
3、sqlsessionFactory 对象,配置到 spring 容器中
4、mapeer 代理对象或者是 dao 实现类配置到 spring 容器中。
第五步:编写 dao 或者 mapper 文件
第六步:测试。
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE configuration
- PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-config.dtd">
- <configuration>
- <typeAliases>
- <package name="cn.itcast.mybatis.pojo"/>
- </typeAliases>
- <mappers>
- <mapper resource="sqlmap/User.xml"/>
- </mappers>
- </configuration>
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
- xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
- http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
- http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
- <!-- 加载配置文件 -->
- <context:property-placeholder location="classpath:db.properties" />
- <!-- 数据库连接池 -->
- <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
- destroy-method="close">
- <
- property
- name
- =
- "driverClassName"
- value
- =
- "${jdbc.driver}"
- />
- <
- property
- name
- =
- "url"
- value
- =
- "${jdbc.url}"
- />
- <
- property
- name
- =
- "username"
- value
- =
- "${jdbc.username}"
- />
- <
- property
- name
- =
- "password"
- value
- =
- "${jdbc.password}"
- />
- <
- property
- name
- =
- "maxActive"
- value
- =
- "10"
- />
- <
- property
- name
- =
- "maxIdle"
- value
- =
- "5"
- />
- </bean>
- <!-- mapper配置 -->
- <!-- 让spring管理sqlsessionfactory 使用mybatis和spring整合包中的 -->
- <
- bean
- id
- =
- "sqlSessionFactory"
- class
- =
- "org.mybatis.spring.SqlSessionFactoryBean"
- >
- <!-- 数据库连接池 -->
- <
- property
- name
- =
- "dataSource"
- ref
- =
- "dataSource"
- />
- <!-- 加载mybatis的全局配置文件 -->
- <
- property
- name
- =
- "configLocation"
- value
- =
- "classpath:mybatis/SqlMapConfig.xml"
- />
- </bean>
- </beans>
- jdbc.driver=com.mysql.jdbc.Driver
- jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8
- jdbc.username=root
- jdbc.password=root
三种 dao 的实现方式:
1、传统 dao 的开发方式
2、使用 mapper 代理形式开发方式
3、使用扫描包配置 mapper 代理。
3.4.1 传统 dao 的开发方式
接口 + 实现类来完成。需要 dao 实现类需要继承 SqlsessionDaoSupport 类。
- public
- class
- UserDaoImpl
- extends
- SqlSessionDaoSupport
- implements
- UserDao
- {
- @Override
- public User findUserById(int id) throws Exception {
- SqlSession session = getSqlSession();
- User user = session.selectOne("test.findUserById", id);
- //不能关闭SqlSession,让spring容器来完成
- //session.close();
- return user;
- }
- @Override
- public void insertUser(User user) throws Exception {
- SqlSession session = getSqlSession();
- session.insert("test.insertUser", user);
- session.commit();
- //session.close();
- }
- }
把 dao 实现类配置到 spring 容器中
- <!-- 配置UserDao实现类 -->
- <
- bean
- id
- =
- "userDao"
- class
- =
- "cn.zy.dao.UserDaoImpl"
- >
- <
- property
- name
- =
- "sqlSessionFactory"
- ref
- =
- "sqlSessionFactory"
- />
- </bean>
初始化:
- private ApplicationContext applicationContext;
- @Before
- public void setUp() throws Exception{
- String configLocation = "classpath:spring/ApplicationContext.xml";
- //初始化spring运行环境
- applicationContext = new ClassPathXmlApplicationContext(configLocation);
- }
测试:
- @Test
- public void testFindUserById() throws Exception {
- UserDao userDao = (UserDao) applicationContext.getBean("userDao");
- User user = userDao.findUserById(1);
- System.out.println(user);
- }
3.4.2 Mapper 代理形式开发 dao
编写 mapper 接口,注意接口中的方法名需要和 mapper.xml 配置文件中的 id 名相同。
- <!-- 配置mapper代理对象 -->
- <bean class="org.mybatis.spring.mapper.MapperFactoryBean">
- <
- property
- name
- =
- "mapperInterface"
- value
- =
- "cn.zy.mybatis.mapper.UserMapper"
- />
- <
- property
- name
- =
- "sqlSessionFactory"
- ref
- =
- "sqlSessionFactory"
- />
- </bean>
- public class UserMapperTest {
- private ApplicationContext applicationContext;
- @Before
- public void setUp() throws Exception {
- applicationContext = new ClassPathXmlApplicationContext("classpath:spring/applicationContext.xml");
- }
- @Test
- public void testGetUserById() {
- UserMapper userMapper = applicationContext.getBean(UserMapper.class);
- User user = userMapper.getUserById(1);
- System.out.println(user);
- }
- }
3.4.3 扫描包形式配置 mapper
- <!-- 使用扫描包的形式来创建mapper代理对象 -->
- <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
- <
- property
- name
- =
- "basePackage"
- value
- =
- "cn.zy.mybatis.mapper"
- />
- </bean>
每个 mapper 代理对象的 id 就是类名,首字母小写
ok,写到最后,今天的这篇关于 MyBatis 的进阶用法已经讲完了,按理说写的应该算是步骤详细,言简意赅的了,希望对大家有所帮助咯,有什么疑问可以留言,如果我会的话,会和大家讨论的,如果有错误的地方,也欢迎大家指出改正~
来源: http://blog.csdn.net/woshizisezise/article/details/78796228