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/ 欢迎转载 也请保留这段声明 谢谢!