输入映射和输出映射
parameterType(输入类型)
1.传递简单类型
2.传递pojo对象
3.传递pojo包装对象
新建包装对象
1 package com.likai.mybatis.pojo; 2 3 /** 4 * 测试包装的pojo 5 * @author 黎跑跑 6 * 7 */ 8 public class QueryVo { 9 10 private User user; 11 12 public User getUser() { 13 return user; 14 } 15 16 public void setUser(User user) { 17 this.user = user; 18 } 19 }
映射文件与sql
resultType:如果返回数据集合,只需设定为每一个元素的数据类型
包装的pojo取值通过 “.” 来获取
1 <!-- 测试包装的pojo --> 2 <select id="getUserByQueryVo" parameterType="QueryVo" resultType="com.likai.mybatis.pojo.User"> 3 SELECT * FROM `user` WHERE username LIKE ‘%${user.username}%‘; 4 </select>
新增接口方法
1 /** 2 * 测试包装的pojo 3 * @param userName 4 * @return 5 */ 6 List<User> getUserByQueryVo(QueryVo queryVo);
新增测试方法,完成测试
1 @Test 2 public void testGetUserByQueryVo(){ 3 SqlSession sqlSession = SqlSessionFactoryUtils.getSqlsessionFactory().openSession(); 4 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 5 QueryVo queryVo = new QueryVo(); 6 User user = new User(); 7 user.setUsername("凯"); 8 queryVo.setUser(user); 9 List<User> list = userMapper.getUserByQueryVo(queryVo); 10 for (User user1 : list) { 11 System.out.println(user1); 12 } 13 sqlSession.close(); 14 }
resultType(输出类型)
1.输出简单类型
2.输出pojo对象
3.输出pojo列表
输出resultMap
由于数据库中的user_id与pojo属性中的userId不一致时产生的查询问题。
OrderMapper.java
1 package com.likai.mybatis.mapper; 2 3 import java.util.List; 4 5 import com.likai.mybatis.pojo.Order; 6 7 public interface OrderMapper { 8 9 /** 10 * 获取订单信息 11 * @return 12 */ 13 List<Order> getOrder(); 14 }
OrderMapper.xml
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 <mapper namespace="com.likai.mybatis.mapper.OrderMapper"> 6 <select id="getOrder" resultType="order"> 7 SELECT id, user_id, number, createtime, note FROM `order`; 8 </select> 9 </mapper>
测试类
1 package com.likai.mybatis.test; 2 3 import static org.junit.Assert.*; 4 5 import java.util.List; 6 7 import org.apache.ibatis.session.SqlSession; 8 import org.junit.Test; 9 10 import com.likai.mybatis.mapper.OrderMapper; 11 import com.likai.mybatis.pojo.Order; 12 import com.likai.mybatis.utils.SqlSessionFactoryUtils; 13 14 public class OrderMapperTest { 15 16 @Test 17 public void testGetOrder() { 18 SqlSession sqlSession = SqlSessionFactoryUtils.getSqlsessionFactory().openSession(); 19 OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class); 20 List<Order> list = orderMapper.getOrder(); 21 for (Order order : list) { 22 System.out.println(order); 23 } 24 } 25 26 }
结果:userId的值全为null
Order [id=3, userId=null, number=1000010, createtime=Wed Feb 04 13:22:35 CST 2015, note=null] Order [id=4, userId=null, number=1000011, createtime=Tue Feb 03 13:22:41 CST 2015, note=null] Order [id=5, userId=null, number=1000012, createtime=Thu Feb 12 16:13:23 CST 2015, note=null]
解决方法:
一:在sql语句中添加别名
OrderMapper.xml
1 1 <?xml version="1.0" encoding="UTF-8" ?> 2 2 <!DOCTYPE mapper 3 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 5 <mapper namespace="com.likai.mybatis.mapper.OrderMapper"> 6 6 <select id="getOrder" resultType="order"> 7 7 SELECT id, user_id userId, number, createtime, note FROM `order`; 8 8 </select> 9 9 </mapper>
结果
1 Order [id=3, userId=1, number=1000010, createtime=Wed Feb 04 13:22:35 CST 2015, note=null] 2 Order [id=4, userId=1, number=1000011, createtime=Tue Feb 03 13:22:41 CST 2015, note=null] 3 Order [id=5, userId=10, number=1000012, createtime=Thu Feb 12 16:13:23 CST 2015, note=null]
二:输出resultMap
OrderMap.xml
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 <mapper namespace="com.likai.mybatis.mapper.OrderMapper"> 6 7 <!-- resultMap入门: 8 type:映射成的pojo类型 9 id:resultMap唯一标识 10 --> 11 <resultMap type="order" id="orderMap"> 12 <!-- <id>标签用于绑定主键 --> 13 <id property="id" column="id"/> 14 <!-- 使用result绑定普通字段
property:类中的变量
column:sql语句中的变量,用于接受数据并且传入类中
--> 15 <result property="userId" column="user_id"/> 16 <result property="number" column="number"/> 17 <result property="createtime" column="createtime"/> 18 <result property="note" column="note"/> 19 </resultMap> 20 21 <!-- 使用resultMap --> 22 <select id="getOrder" resultMap="orderMap"> 23 SELECT * FROM `order`; 24 </select> 25 </mapper>
结果
1 1 Order [id=3, userId=1, number=1000010, createtime=Wed Feb 04 13:22:35 CST 2015, note=null] 2 2 Order [id=4, userId=1, number=1000011, createtime=Tue Feb 03 13:22:41 CST 2015, note=null] 3 3 Order [id=5, userId=10, number=1000012, createtime=Thu Feb 12 16:13:23 CST 2015, note=null]
动态sql
if标签
查询用户列表,多查询条件拼装
1 <select id="getUserByWhere" parameterType="User" resultType="User"> 2 SELECT * FROM USER WHERE 1 = 1
<!-- <if>标签的使用 --> 3 <if test="username != null and username != ‘‘"> 4 AND username LIKE ‘%${username}%‘ 5 </if> 6 7 <if test="sex != null and sex != ‘‘"> 8 AND sex = #{sex}; 9 </if> 10 </select>
输出语句
1 Preparing: SELECT * FROM USER WHERE 1 = 1 AND username LIKE ‘%小%‘ AND sex = ?;
注解:为什么添加where 1=1 和第一个语句前添加and。
如果第一个if判断不成立第二个判断成立,则变为where and sex = ?,语法不成立,所以在where前添加一个永恒成立的语句1=1,既然添加了1=1,第一个语句不添加and语法也不成立
where标签
每次语句写1=1挺麻烦,解决办法,where标签
where标签作用:自动加上where同时处理多余的and
1 <select id="getUserByWhere" parameterType="User" resultType="User"> 2 SELECT * FROM USER 3 <!-- 使用where标签 --> 4 <where> 5 <if test="username != null and username != ‘‘"> 6 AND username LIKE ‘%${username}%‘ 7 </if> 8 9 <if test="sex != null and sex != ‘‘"> 10 AND sex = #{sex}; 11 </if> 12 </where> 13 </select>
输出语句
Preparing: SELECT * FROM USER WHERE username LIKE ‘%小%‘ AND sex = ?;
sql片段
这样显得太臃肿,可以抽取sql片段
1 <sql id="user_sql"> 2 id, 3 username, 4 birthday, 5 sex, 6 address 7 </sql>
1 <select id="getUserByWhere" parameterType="User" resultType="User"> 2 SELECT 3 <include refid="user_sql"/> 4 FROM USER 5 <!-- 使用where标签 --> 6 <where> 7 <if test="username != null and username != ‘‘"> 8 AND username LIKE ‘%${username}%‘ 9 </if> 10 11 <if test="sex != null and sex != ‘‘"> 12 AND sex = #{sex}; 13 </if> 14 </where> 15 </select>
foreach标签
需求引入:查询一系列id
sql语句:select * from user where id in (1,16,27,32);需动态输入,难点在in(1,16,27,32);
解决:可以将id集合封装在一个类中(之前封装过user集合的类),这样就可以传入id集合
QueryVo.java添加集合
1 private List<Integer> ids; 2 3 public List<Integer> getIds() { 4 return ids; 5 } 6 7 public void setIds(List<Integer> ids) { 8 this.ids = ids; 9 }
foreach标签的使用:
collection:要遍历的集合,来源入参
open:循环开始前的sql
item:遍历的变量
separator:分隔符
close:循环结束拼接的sql
1 <!-- 演示动态sql-foreach标签的使用情景 --> 2 <select id="getUserByIds" parameterType="QueryVo" resultType="User"> 3 SELECT 4 <include refid="user_sql"/> 5 FROM USER 6 <where> 7 <!-- id IN (1,16,27,32); --> 8 <!-- foreach标签的使用 9 collection:要遍历的集合,来源入参 10 open:循环开始前的sql 11 item:遍历的变量 12 separator:分隔符 13 close:循环结束拼接的sql 14 --> 15 <foreach collection="ids" open="id IN (" item="uid" separator="," close=");"> 16 #{uid} 17 </foreach> 18 </where> 19 </select>
结果
1 Preparing: SELECT id, username, birthday, sex, address FROM USER WHERE id IN ( ? , ? , ? , ? , ? );
关联查询
一对一关联
1.使用resultType
一个订单只能由一个用户创建,从订单的角度关联查询用户为一对一查询。
sql语句:select u.username,u.birthday,u.sex,u.address, o.id,o.user_id,o.number,o.createtime,o.note from `order` o left join `user` u on o.user_id = u.id;
查询出的信息包括Order表和User表的信息,新建一个pojo包含两个表的内容
1 package com.likai.mybatis.pojo; 2 3 public class OrderUser extends Order { 4 5 private String username; 6 private String address; 7 8 public String getUsername() { 9 return username; 10 } 11 12 13 public void setUsername(String username) { 14 this.username = username; 15 } 16 17 18 public String getAddress() { 19 return address; 20 } 21 22 public void setAddress(String address) { 23 this.address = address; 24 } 25 26 @Override 27 public String toString() { 28 return "OrderUser [username=" + username + ", address=" + address + ", getId()=" + getId() + ", getNumber()=" 29 + getNumber() + ", getCreatetime()=" + getCreatetime() + ", getNote()=" + getNote() + "]"; 30 } 31 32 }
配置OrderMapper.xml
1 <!-- 使用resultType实现一对一查询 --> 2 <select id="getOrdersByUser" resultType="OrderUser"> 3 select u.username,u.address, o.id,o.user_id userId,o.number,o.createtime,o.note 4 from `order` o left join `user` u on o.user_id = u.id; 5 </select>
2.使用resultMap
方法一新建pojo放置order和user不符合面向对象的特点,这里采用该种方法。在Order中插入用户,Order.java
1 private User user; 2 3 public User getUser() { 4 return user; 5 } 6 7 public void setUser(User user) { 8 this.user = user; 9 }
配置OrderMapper.xml
1 <!-- 使用resultMap实现一对一查询 --> 2 <sql id="order_user_sql"> 3 o.id,o.user_id,o.number,o.createtime,o.note, 4 u.id,u.username,u.birthday,u.sex,u.address 5 </sql> 6 7 <resultMap type="Order" id="OrderUser"> 8 <id property="id" column="id"/> 9 <result property="userId" column="user_id"/> 10 <result property="number" column="number"/> 11 <result property="createtime" column="createtime"/> 12 <result property="note" column="note"/> 13 <!-- 14 association:配置一对一关联 15 property:绑定的用户属性,即订单里的user变量 16 javaType:属性数据类型,支持别名,即user变量的类型 17 --> 18 <association property="user" javaType="User"> 19 <id property="id" column="user_id"/> 20 <result property="username" column="username"/> 21 <result property="sex" column="sex"/> 22 <result property="birthday" column="birthday"/> 23 <result property="address" column="address"/> 24 </association> 25 </resultMap> 26 27 <select id="getOrdersFromUser" resultMap="OrderUser"> 28 SELECT 29 <include refid="order_user_sql"/> 30 FROM `order` o LEFT JOIN `user` u ON o.user_id = u.id; 31 </select>
多对一关联查询
一个用户可以创建多个订单,从用户的角度分析是多对一的关系
sql语句:SELECT u.id,u.username,u.birthday,u.sex,u.address,o.id,o.number,o.createtime,o.note FROM `user` u LEFT JOIN `order` o ON u.id = o.user_id;
在user.java中添加order集合对象
1 private List<Order> list; 2 3 public List<Order> getList() { 4 return list; 5 } 6 7 public void setList(List<Order> list) { 8 this.list = list; 9 }
配置User.xml
1 <!-- 演示多对一的关系 --> 2 <!-- u.id和o.id两个id会重复,o.id取个别名--> 3 <sql id="user_order_sql"> 4 u.id,u.username,u.birthday,u.sex,u.address, 5 o.id oid,o.number,o.createtime,o.note 6 </sql> 7 8 <resultMap id="user_order_map" type="user"> 9 <id property="id" column="id"/> 10 <result property="username" column="username"/> 11 <result property="sex" column="sex"/> 12 <result property="birthday" column="birthday"/> 13 <result property="address" column="address"/> 14 <!-- 一对多用 collection 15 property:一的一放放置的多的一放集合变量,这里为list 16 ofType:property的数据类型,支持别名 17 --> 18 <collection property="list" ofType="order"> 19 <id property="id" column="oid"/> 20 <result property="userId" column="id"/> 21 <result property="number" column="number"/> 22 <result property="createtime" column="createtime"/> 23 <result property="note" column="note"/> 24 </collection> 25 </resultMap> 26 27 <select id="getUserOrder" resultMap="user_order_map"> 28 SELECT 29 <include refid="user_order_sql"/> 30 FROM `user` u LEFT JOIN `order` o ON u.id = o.user_id; 31 </select>
编写测试
1 @Test 2 public void testGetUserOrder(){ 3 SqlSession sqlSession = SqlSessionFactoryUtils.getSqlsessionFactory().openSession(); 4 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 5 List<User> users = userMapper.getUserOrder(); 6 for (User user : users) { 7 System.out.println(user); 8 for (Order order : user.getList()) { 9 if(order.getId() != null){ 10 System.out.println("该用户下的订单有..." + order); 11 } 12 } 13 } 14 }
结果
1 User [id=1, username=王五, sex=2, birthday=null, address=null] 2 该用户下的订单有...Order [id=3, userId=1, number=1000010, createtime=Wed Feb 04 13:22:35 CST 2015, note=null] 3 该用户下的订单有...Order [id=4, userId=1, number=1000011, createtime=Tue Feb 03 13:22:41 CST 2015, note=null] 4 User [id=10, username=张三, sex=1, birthday=Thu Jul 10 00:00:00 CST 2014, address=北京市] 5 该用户下的订单有...Order [id=5, userId=10, number=1000012, createtime=Thu Feb 12 16:13:23 CST 2015, note=null] 6 User [id=16, username=张小明, sex=1, birthday=null, address=河南郑州] 7 User [id=22, username=陈小明, sex=1, birthday=null, address=河南郑州] 8 User [id=24, username=张三丰, sex=1, birthday=null, address=河南郑州] 9 User [id=27, username=黎凯, sex=1, birthday=Sun Sep 08 00:00:00 CST 1996, address=江苏南京] 10 User [id=29, username=燕燕, sex=2, birthday=Wed Jun 01 00:00:00 CST 1994, address=江苏南京] 11 User [id=30, username=小燕燕, sex=2, birthday=Wed Jun 01 00:00:00 CST 1994, address=江苏徐州] 12 User [id=31, username=小凯凯, sex=1, birthday=Sun Sep 08 00:00:00 CST 1996, address=浙江杭州] 13 User [id=32, username=黎跑跑triplejump, sex=1, birthday=Sun Sep 08 00:00:00 CST 1996, address=江苏南京] 14 User [id=33, username=凯神, sex=1, birthday=Sun Sep 08 00:00:00 CST 1996, address=江苏南京]
Mybatis整合spring
整合思路
1.SqlSessionFactory对象应该放到spring容器中作为单例存在。
2.传统dao的开发方式中,应该从spring容器中获得sqlsession对象。
3.Mapper代理形式中,应该从spring容器中直接获得mapper的代理对象。
4.数据库的连接以及数据库连接池事务管理都交给spring容器来完成。
整合步骤
1. 创建一个java工程。
2.导入jar包。(mybatis与spring整合所有包)
3.mybatis的配置文件SqlMapConfig.xml
自定义别名,数据库连接和映射文件都可以交给spring管理,所以SqlMapConfig.xml
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE configuration 3 PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-config.dtd"> 5 <configuration> 6 7 </configuration>
4.编写Spring的配置文件
a.数据库连接及连接池
b.sqlsessionFactory对象,配置到spring容器中
1 <!-- SqlSessionFactory配置 --> 2 <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> 3 <property name="dataSource" ref="dataSource"/> 4 <!-- 加载核心配置文件 --> 5 <property name="configLocation" value="classpath:SqlMapConfig.xml"/> 6 <!-- 别名的配置 --> 7 <property name="typeAliasesPackage" value="cn.likai.mybatis.pojo"/> 8 </bean>
c.编写Spring的配置文件
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" 4 xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" 5 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 6 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd 7 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd 8 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 9 http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd"> 10 11 <!-- 加载配置文件 --> 12 <context:property-placeholder location="classpath:jdbc.properties" /> 13 14 <!-- 数据库连接池 --> 15 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" 16 destroy-method="close"> 17 <property name="driverClassName" value="${jdbc.driver}" /> 18 <property name="url" value="${jdbc.url}" /> 19 <property name="username" value="${jdbc.username}" /> 20 <property name="password" value="${jdbc.password}" /> 21 <!-- 连接池的最大数据库连接数 --> 22 <property name="maxActive" value="10" /> 23 <!-- 最大空闲数 --> 24 <property name="maxIdle" value="5" /> 25 </bean> 26 27 <!-- SqlSessionFactory配置 --> 28 <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> 29 <property name="dataSource" ref="dataSource"/> 30 <!-- 加载核心配置文件 --> 31 <property name="configLocation" value="classpath:SqlMapConfig.xml"/> 32 <!-- 别名的配置 --> 33 <property name="typeAliasesPackage" value="cn.likai.mybatis.pojo"/> 34 </bean> 35 </beans>
5.创建jdbc.properties配置文件
6.创建log4j.properties配置文件
Dao开发
传统Dao开发
1.在config文件下创建文件夹并编写user.xml
2.在SqlMapConfig.xml加载user.xml
3.创建UserDao接口
4.编写UserDaoImpl实现类,关键是继承SqlSessionDaoSupport
1 public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao { 2 3 @Override 4 public User getUserById(int id) { 5 SqlSession sqlSession = getSqlSession(); 6 User user = sqlSession.selectOne("getUserById", id); 7 //不能关闭SqlSession,全部交给spring管理 8 return user; 9 } 10 11 @Override 12 public List<User> getUserByName(String userName) { 13 SqlSession sqlSession = getSqlSession(); 14 List<User> list = sqlSession.selectList("getUserByName", userName); 15 return list; 16 } 17 18 @Override 19 public void insertUser(User user) { 20 SqlSession sqlSession = getSqlSession(); 21 sqlSession.insert("insertUser", user); 22 } 23 24 }
5.在applicationContext中配置UserDaoImpl实现类
1 <!-- 传统dao --> 2 <bean id="userDao" class="cn.likai.mybatis.dao.impl.UserDaoImpl"> 3 <property name="sqlSessionFactory" ref="sqlSessionFactory"/> 4 </bean>
6.编写测试类
1 package cn.likai.mybatis.dao.test; 2 3 import static org.junit.Assert.*; 4 5 import java.util.List; 6 7 import org.junit.Before; 8 import org.junit.Test; 9 import org.springframework.context.ApplicationContext; 10 import org.springframework.context.support.ClassPathXmlApplicationContext; 11 12 import cn.likai.mybatis.dao.UserDao; 13 import cn.likai.mybatis.pojo.User; 14 15 public class UserDaoImplTest { 16 17 private ApplicationContext applicationContext; 18 19 //在执行任何方法之前先执行这个方法 20 @Before 21 public void init(){ 22 applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); 23 } 24 25 @Test 26 public void testGetUserById() { 27 UserDao userDao = applicationContext.getBean(UserDao.class); 28 User user = userDao.getUserById(27); 29 System.out.println(user); 30 } 31 32 @Test 33 public void testGetUserByName() { 34 UserDao userDao = applicationContext.getBean(UserDao.class); 35 User user = new User(); 36 user.setUsername("凯"); 37 List<User> list = userDao.getUserByName(user.getUsername()); 38 for (User user2 : list) { 39 System.out.println(user2); 40 } 41 } 42 43 @Test 44 public void testInsertUser() { 45 46 } 47 48 }
Mapper代理模式开发Dao
1.创建UserMapper.xml
2.创建UserMapper.java
3.配置Mapper
a.单个接口配置MapperFactoryBean
1 <!-- 动态代理Dao开发,第一种方式:MapperFactoryBean --> 2 <bean id="baseMapper" class="org.mybatis.spring.mapper.MapperFactoryBean" abstract="true" lazy-init="true"> 3 <property name="sqlSessionFactory" ref="sqlSessionFactory" /> 4 </bean> 5 6 <!-- 用户动态代理扫描 --> 7 <bean parent="baseMapper"> 8 <property name="mapperInterface" value="cn.likai.mybatis.mapper.UserMapper" /> 9 </bean>
b.配置包扫描器
1 <!-- 动态代理Dao开发,第二种方式:包扫描器(推荐使用) --> 2 <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> 3 <!-- basePackage:配置映射包装扫描,多个包时用","或";"分隔 --> 4 <property name="basePackage" value="cn.likai.mybatis.mapper"/> 5 </bean>
测试
1 public class UserMapperTest { 2 3 private ApplicationContext applicationContext; 4 5 @Before 6 public void init(){ 7 applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); 8 } 9 10 @Test 11 public void test() { 12 UserMapper userMapper = applicationContext.getBean(UserMapper.class); 13 User user = userMapper.getUserById(32); 14 System.out.println(user); 15 }
Mybatis逆向工程
原文:https://www.cnblogs.com/lipaopao/p/11020420.html