mybatis详解 2017-01-05
MyBatis之代理开发模式
1 mybatis-Dao的代理开发模式
Dao:数据访问对象
原来:定义dao接口,在定义dao的实现类
dao的代理开发模式
只需要定义dao接口,由mybatis产生dao接口的实现类。
1.1定义Mapper接口
1package org.guangsoft.mapper; 2 3import java.util.List; 4 5import org.guangsoft.entity.Dept; 6import org.guangsoft.vo.DeptVo; 7 8public interface DeptMapper 9 { 10 public List<DeptVo> getDeptPost(); 11 public void saveDept(Dept dept); 12 }
1.2定义Mapper.xml文件
定义Mapper接口中方法对应的操作
<?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE mapper PUBLIC "-//mybatis.org/DTD Mapper 3.0" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 3 <mapper namespace="org.guangsoft.mapper.DeptMapper"> 4 <!-- 使用dao的代理开发模式的时候 5 1,namespace必须和map接口的完全限定名完全一样 6 2.对应的数据库库擦操作id必须和接口中抽象放安防名一致 7 3,parameterType必须和抽闲接口的抽象方法参数类型一致 8 4,resultType必须和接口抽象方法的返回类型一样 9 --> 10 <select id="getDeptPost" resultType="org.guangsoft.vo.DeptVo"> 11 select dept.did,dname,pname from dept inner join post on dept.did=post.did 12 </select> 13 <insert id="saveDept" parameterType="org.guangsoft.entity.Dept"> 14 insert into dept values(null,#{dname}) 15 </insert> 16 </mapper>
1.3通过session产生Mapper接口的代理对象
public class TestDeptMapper 2{ 3 SqlSessionFactory ssf = null; 4 @Before 5 public void before() 6 { 7 SqlSessionFactoryBuilder ssfb = new SqlSessionFactoryBuilder(); 8 ssf = ssfb.build(this.getClass().getClassLoader().getResourceAsStream("MyBatis.xml")); 9 } 10 11 @Test 12 public void testGetDeptPost() 13 { 14 SqlSession sqlSession = ssf.openSession(); 15 DeptMapper deptMapper = sqlSession.getMapper(DeptMapper.class); 16 List<DeptVo> deptVoList = deptMapper.getDeptPost(); 17 for(DeptVo deptVo : deptVoList) 18 { 19 System.out.println(deptVo); 20 } 21 sqlSession.close(); 22 } 23 24 @Test 25 public void testSaveDept() 26 { 27 SqlSession sqlSession = ssf.openSession(); 28 DeptMapper deptMapper = sqlSession.getMapper(DeptMapper.class); 29 Dept dept = new Dept(); 30 dept.setDname("danme"); 31 deptMapper.saveDept(dept); 32 sqlSession.commit(); 33 sqlSession.close(); 34 } 35 }
2 mybatis的关联查询
Mybatis多表查询。
2.1 one-to-one 查询
需求:查询某个订单和订单对应的用户信息
订单编号 用户名 时间 金额 描述
2.1.1建立数据库模型
用户表,订单表。
1 /* 2 Navicat MySQL Data Transfer 3 4 Source Server : MySQL 5 Source Server Version : 50715 6 Source Host : localhost:3306 7 Source Database : test 8 9 Target Server Type : MYSQL 10 Target Server Version : 50715 11 File Encoding : 65001 12 13 Date: 2016-12-14 20:47:27 14 */ 15 16 SET FOREIGN_KEY_CHECKS=0; 17 18 -- ---------------------------- 19 -- Table structure for orders 20 -- ---------------------------- 21 DROP TABLE IF EXISTS `orders`; 22 CREATE TABLE `orders` ( 23 `oid` int(11) NOT NULL AUTO_INCREMENT, 24 `odate` datetime DEFAULT NULL, 25 `ototal` double DEFAULT NULL, 26 `odesc` varchar(255) DEFAULT NULL, 27 `uid` int(11) DEFAULT NULL, 28 PRIMARY KEY (`oid`), 29 KEY `fk_uid` (`uid`), 30 CONSTRAINT `fk_uid` FOREIGN KEY (`uid`) REFERENCES `user` (`uid`) 31 ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; 32 33 -- ---------------------------- 34 -- Table structure for user 35 -- ---------------------------- 36 DROP TABLE IF EXISTS `user`; 37 CREATE TABLE `user` ( 38 `uid` int(11) NOT NULL AUTO_INCREMENT, 39 `username` varchar(255) DEFAULT NULL, 40 `password` varchar(255) DEFAULT NULL, 41 PRIMARY KEY (`uid`) 42 ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
2.1.2产生java实体模型
1package org.guangsoft.entity; 2 3import java.util.Set; 4 5public class User 6{ 7 private Integer uid; 8 private String username; 9 private String password; 10 private Set<Orders> orders; 11 public Integer getUid() 12 { 13 return uid; 14 } 15 public void setUid(Integer uid) 16 { 17 this.uid = uid; 18 } 19 public String getUsername() 20 { 21 return username; 22 } 23 public void setUsername(String username) 24 { 25 this.username = username; 26 } 27 public String getPassword() 28 { 29 return password; 30 } 31 public void setPassword(String password) 32 { 33 this.password = password; 34 } 35 public Set<Orders> getOrders() 36 { 37 return orders; 38 } 39 public void setOrders(Set<Orders> orders) 40 { 41 this.orders = orders; 42 } 43 44 }
1 package org.guangsoft.entity; 2 3 import java.util.Date; 4 import java.util.Set; 5 6 7 public class Orders 8 { 9 private Integer oid; 10 private Date odate; 11 private Double ototal; 12 private String odesc; 13 private User user; 14 //关联订单下的明细 15 private Set<Detail> details; 16 public Integer getOid() 17 { 18 return oid; 19 } 20 public void setOid(Integer oid) 21 { 22 this.oid = oid; 23 } 24 public Date getOdate() 25 { 26 return odate; 27 } 28 public void setOdate(Date odate) 29 { 30 this.odate = odate; 31 } 32 public Double getOtotal() 33 { 34 return ototal; 35 } 36 public void setOtotal(Double ototal) 37 { 38 this.ototal = ototal; 39 } 40 public String getOdesc() 41 { 42 return odesc; 43 } 44 public void setOdesc(String odesc) 45 { 46 this.odesc = odesc; 47 } 48 public User getUser() 49 { 50 return user; 51 } 52 public void setUser(User user) 53 { 54 this.user = user; 55 } 56 public Set<Detail> getDetails() 57 { 58 return details; 59 } 60 public void setDetails(Set<Detail> details) 61 { 62 this.details = details; 63 } 64 65 }
2.1.3定义Mapper接口
1package org.guangsoft.mapper; 2 3import org.guangsoft.entity.Orders; 4 5public interface OrdersMapper 6{ 7 public Orders loadOrdersUser(Integer oid); 8 }
2.1.4定义Mapper.xml
描述接口中方法对应的操作。
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE mapper PUBLIC "-//mybatis.org/DTD Mapper 3.0" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 3 <mapper namespace="org.guangsoft.mapper.OrdersMapper"> 4 <resultMap type="org.guangsoft.entity.Orders" id="ordersUser"> 5 <id column="oid" property="oid" /> 6 <result column="odate" property="odate" /> 7 <result column="odesc" property="odesc" /> 8 <result column="ototal" property="ototal" /> <!--一对一时使用--> <!--javaType--> 9 <association property="user" javaType="org.guangsoft.entity.User"> 10 <id column="uid" property="uid" /> 11 <result column="username" property="username" /> 12 <result column="password" property="password" /> 13 </association> 14 </resultMap> 15 <select id="loadOrdersUser" parameterType="java.lang.Integer" resultMap="ordersUser"> 16 select oid ,odate,ototal,odesc,username 17 from orders inner join user 18 on orders.uid = user.uid where orders.oid = #{oid} 19 </select> 20 </mapper>
2.1.5获得Mapper接口代理对象
1 public class TestDeptMapper 2 { 3 SqlSessionFactory ssf = null; 4 @Before 5 public void before() 6 { 7 SqlSessionFactoryBuilder ssfb = new SqlSessionFactoryBuilder(); 8 ssf = ssfb.build(this.getClass().getClassLoader().getResourceAsStream("MyBatis.xml")); 9 } 10 11 @Test 12 public void testGetDeptPost() 13 { 14 SqlSession sqlSession = ssf.openSession(); 15 DeptMapper deptMapper = sqlSession.getMapper(DeptMapper.class); 16 List<DeptVo> deptVoList = deptMapper.getDeptPost(); 17 for(DeptVo deptVo : deptVoList) 18 { 19 System.out.println(deptVo); 20 } 21 sqlSession.close(); 22 } 23 }
2.2 one-to-many查询
对表关联查询
给Users加入orders的集合属性
2.2.1定义Mapper接口
1 package org.guangsoft.mapper; 2 3 import java.util.List; 4 5 import org.guangsoft.entity.User; 6 7 public interface UserMapper 8 { 9 public User loadUserOrders(Integer uid); 10 public List<User> loadUserOrdersDetail(); 11 public List<User> loadUserOrdersDetail2(); 12 }
2.2.2定义Mapper文件
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE mapper PUBLIC "-//mybatis.org/DTD Mapper 3.0" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 3 <mapper namespace="org.guangsoft.mapper.UserMapper"> 4 <resultMap type="org.guangsoft.entity.User" id="userOrders"> 5 <id column="uid" property="uid" /> 6 <result column="username" property="username"></result> <!--一对多时使用--> <!--ofType--> 7 <collection property="orders" ofType="org.guangsoft.entity.Orders"> 8 <id column="oid" property="oid" /> 9 <result column="odate" property="odate" /> 10 <result column="odesc" property="odesc" /> 11 <result column="ototal" property="ototal" /> 12 </collection> 13 </resultMap> 14 <select id="loadUserOrders" parameterType="java.lang.Integer" resultMap="userOrders"> 15 select user.uid ,oid ,odate,ototal,odesc,username 16 from orders inner join user 17 on orders.uid = user.uid where user.uid = #{uid} 18 </select> <!--一个用户对应多个订单 一个订单对应多个订单项--> 19 <resultMap type="org.guangsoft.entity.User" id="userOrdersDetail"> <!--用户--> 20 <id column="uid" property="uid" /> 21 <result column="username" property="username" /> <!--订单--> 22 <collection property="orders" ofType="org.guangsoft.entity.Orders"> 23 <id column="oid" property="oid" ></id> 24 <result column="odate" property="odate" ></result> <!--订单项--> 25 <collection property="details" ofType="org.guangsoft.entity.Detail"> 26 <id column="did" property="did"></id> 27 <result column="price" property="price"></result> 28 <result column="pname" property="pname"></result> 29 <result column="cts" property="cts"></result> 30 </collection> 31 </collection> 32 </resultMap> 33 <select id="loadUserOrdersDetail" resultMap="userOrdersDetail"> 34 select user.uid,orders.oid,username,odate,pname,price,cts 35 from user left join orders on user.uid=orders.uid 36 left join detail on orders.oid = detail.oid 37 </select> 38 39 <select id="loadUserOrdersDetail2" resultMap="userOrdersDetail"> 40 select user.uid,username from user 41 </select> 42 <select id="loadOrders" parameterType="java.lang.Integer" resultType="org.guangsoft.entity.Orders"> 43 select oid,odate from orders where orders.uid=#{uid} 44 </select> 45 <select id="loadDetail" parameterType="java.lang.Integer" resultType="org.guangsoft.entity.Detail"> 46 select pname,price,cts,odid from detail where detail.oid=#{oid} 47 </select> 48 </mapper>
2.2.3获得Mapper接口的代理对象
代码见上
2.3 many-to-many查询(代码见上)
查询所有用户的所有订单信息和订单明细
订单号 ,用户名,日期,商品名称,单价,数量,小计
2.3.1建立订单明细表
订单明细表和订单表之间存在者主外键.
多个用户对应者多个订单,多个订单对应多个明细
2.3.2 定义Mapper接口
2.3.3 定义Mapper.xml文件
2.3.4 获得Mapper接口代理对象
3 mybatis的懒加载
将多表关联查询的sql语句,分开执行
3.1开启懒加载
1 <!-- 开启mybatis的懒加载 --> 2 <setting name="lazyLoadingEnabled" value="true"/> 3 <setting name="aggressiveLazyLoading" value="false"/>
3.2Mapper接口中添加方法
3.3拆分sql语句
3.4获得Mapper代理对象
4 mybatis的动态sql
根据业务需要,可以对sql完成动态的构造。
4.1 if标签
需求:查询订单明细,可以根据订单的编号,商品的名称,商品数量,商品的单价查询。
问题:select * from ordersdetails where (?)
4.1.1定义Mapper接口
1 package org.guangsoft.mapper; 2 3 import java.util.List; 4 5 import org.guangsoft.entity.Detail; 6 7 public interface DetailMapper 8 { 9 /** 10 * 按照订单的编号,商品的名称,商品的数量,商品单价查询订单信息 11 * @return 12 */ 13 public List<Detail> loadDetail(Detail detail); 14 public void deleteDetails(Integer dids[]); 15 }
4.1.2定义Mapper.xml文件
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE mapper PUBLIC "-//mybatis.org/DTD Mapper 3.0" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 3 <mapper namespace="org.guangsoft.mapper.DetailMapper"> <!--自定义sql片段--> 4 <sql id="cond"> 5 <where> 6 <if test="pname != null"><!-- 商品名称 --> 7 and pname = #{pname} 8 </if> 9 <if test="price != null"><!-- 商品价格 --> 10 and price = #{price} 11 </if> 12 <if test="cts != null"><!-- 商品 --> 13 and cts = #{cts} 14 </if> 15 </where> 16 </sql> 17 <select id="loadDetail" resultType="org.guangsoft.entity.Detail"> 18 select * from detail 19 <!-- 动态关联where关键字 --> 20 <include refid="cond"></include> 21 </select> 22 <delete id="deleteDetails" parameterType="org.guangsoft.entity.Detail"> 23 delete from detail 24 <!-- 25 collection需要遍历的集合 26 item集合汇总的每个元素 27 open第一次遍历 28 close最后一次遍历 29 separator将遍历的元素使用什么隔开 30 --> 31 <foreach collection="dids" item="did" open="where did in (" close=")" 32 separator=","></foreach> 33 </delete> 34 <insert id="saveDept" parameterType="org.guangsoft.entity.Dept"> 35 insert into dept values(null,#{dname}) 36 </insert> 37 </mapper>
4.1.3获得Mapper代理对象
1 package org.guangsoft.test; 2 3 import java.util.List; 4 import java.util.Set; 5 6 import org.apache.ibatis.session.SqlSession; 7 import org.apache.ibatis.session.SqlSessionFactory; 8 import org.apache.ibatis.session.SqlSessionFactoryBuilder; 9 import org.guangsoft.entity.Dept; 10 import org.guangsoft.entity.Detail; 11 import org.guangsoft.entity.Orders; 12 import org.guangsoft.entity.User; 13 import org.guangsoft.mapper.DeptMapper; 14 import org.guangsoft.mapper.DetailMapper; 15 import org.guangsoft.mapper.OrdersMapper; 16 import org.guangsoft.mapper.UserMapper; 17 import org.guangsoft.vo.DeptVo; 18 import org.junit.Before; 19 import org.junit.Test; 20 21 public class TestDeptMapper 22 { 23 SqlSessionFactory ssf = null; 24 @Before 25 public void before() 26 { 27 SqlSessionFactoryBuilder ssfb = new SqlSessionFactoryBuilder(); 28 ssf = ssfb.build(this.getClass().getClassLoader().getResourceAsStream("MyBatis.xml")); 29 } 30 31 @Test 32 public void testGetDeptPost() 33 { 34 SqlSession sqlSession = ssf.openSession(); 35 DeptMapper deptMapper = sqlSession.getMapper(DeptMapper.class); 36 List<DeptVo> deptVoList = deptMapper.getDeptPost(); 37 for(DeptVo deptVo : deptVoList) 38 { 39 System.out.println(deptVo); 40 } 41 sqlSession.close(); 42 } 43 44 @Test 45 public void testSaveDept() 46 { 47 SqlSession sqlSession = ssf.openSession(); 48 DeptMapper deptMapper = sqlSession.getMapper(DeptMapper.class); 49 Dept dept = new Dept(); 50 dept.setDname("danme"); 51 deptMapper.saveDept(dept); 52 sqlSession.commit(); 53 sqlSession.close(); 54 } 55 56 @Test 57 public void testGetUserOrders() 58 { 59 SqlSession sqlSession = ssf.openSession(); 60 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 61 User user = userMapper.loadUserOrders(1); 62 Set<Orders> ordersSet = user.getOrders(); 63 for(Orders orders : ordersSet) 64 { 65 System.out.println(orders); 66 } 67 } 68 69 @Test 70 public void testGetOrdersUser() 71 { 72 SqlSession sqlSession = ssf.openSession(); 73 OrdersMapper ordersMapper = sqlSession.getMapper(OrdersMapper.class); 74 Orders orders = ordersMapper.loadOrdersUser(1); 75 System.out.println(orders.getUser().getUsername()); 76 sqlSession.close(); 77 } 78 79 @Test 80 public void testDetail() 81 { 82 SqlSession sqlSession = ssf.openSession(); 83 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 84 List<User> ulist = userMapper.loadUserOrdersDetail(); 85 for(User user : ulist) 86 { 87 Set<Orders> orders = user.getOrders(); 88 if(orders != null) 89 { 90 for(Orders o : orders) 91 { 92 Set<Detail> details = o.getDetails(); 93 for(Detail d : details) 94 { 95 System.out.println(d.getPname()); 96 } 97 } 98 } 99 } 100 } 101 102 @Test 103 public void testDetail2() 104 { 105 SqlSession sqlSession = ssf.openSession(); 106 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 107 OrdersMapper ordersMapper = sqlSession.getMapper(OrdersMapper.class); 108 List<User> userList = userMapper.loadUserOrdersDetail2(); 109 for(User user : userList) 110 { 111 System.out.println(user.getUsername()); 112 Set<Orders> orders = user.getOrders(); 113 if(orders != null) 114 { 115 for(Orders o : orders) 116 { 117 Set<Detail> details = o.getDetails(); 118 for(Detail d : details) 119 { 120 System.out.println(d.getPname()); 121 } 122 } 123 } 124 } 125 } 126 }
4.2foreach标签
完成订单明细的批量删除
Delete from ordersdetails where odid in (1,3,4,5)
4.2.1定义Mapper接口
4.2.2定义Mapper.xml
4.2.3获得Mapper代理对象
5定义sql片段
使用sql标签定义sql片段,
提高sql语句复用性.
使用include标签引用sql片段
6 mybatis的缓存机制
查询缓存:只有在做查询操作的时候,将数据进行缓存
6.1 mybaits的一级缓存
Session级别的缓存,不同的客户端访问数据库,缓存是独立的。
在进行查询操作的时候,数据自动放入一级缓存。
缓存数据消失:
提交事务的时候。
关闭数据库会话。
数据进行缓存的key:namespace+id+params+limit(缓存的界定,通过namespace+id+查询参数+结果集的限定),产生本次查询缓存对应的key
6.2二级缓存
二级sessionFactory级别的缓存(共享缓存)
开启二级缓存
加入缓存插件包(二级缓存为外部缓存插件)
配置缓存策略,在需要进行缓存的Mapper.xml
1 <cache readOnly="true" type="org.mybatis.caches.ehcache.EhcacheCache"></cache>
提供ehcache的配置文件
作者:little飞 出处:http://www.cnblogs.com/little-fly/ 欢迎转载 也请保留这段声明 谢谢!