本章学习MyBatis中的连接池技术与事务深入。MyBatis基于xml配置动态sql语句的使用。MyBatyis中的多表操作。
MyBatis中的连接池 一、连接池的基本介绍 1、优点 使用连接池技术可以使我们的开发效率提高,可以减少获取连接数据库的所消耗的时间减少。
2、作用 
连接池就是用于存储连接的一个容器; 
容器其实本质是一个集合对象,而且该集合对象必须是线程安全的,不能让两个线程拿到同一个连接; 
该集合还必须实现队列的特性(先进先出)。 
 
3、MyBatis连接池的分类 MyBatis中的数据源dataSource分为以下几类
由上图可以看出MyBatis的数据源分为三类:
UNPOOLED		不使用连接池的数据源 
POOLED			  使用连接池的数据源 
JBDI					  使用JDNI实现的数据源 
 
MyBatis 内部分别定义了实现了 java.sql.DataSource 接口的 UnpooledDataSource、PooledDataSource 类来表示 UNPOOLED、POOLED 类型的数据源。
PooledDataSource和UnpooledDataSource都实现了java.lang.DataSource接口。并且PooledDataSource持有一个UnpooledDataSource的引用。当PooledDataSource需要创建java.lang.Connection实例对象时,还是通过UnpooledDataSource来创建的,PooledDataSource只是提供一种缓存连接池机制。
4、MyBatis中数据源的配置 数据源的配置在SqlMapConfig.xml文件中,具体配置如下
1 2 3 4 5 6 7 8 <!-- 配置数据源(也叫连接池) -->       <dataSource type="POOLED" >           <!-- 配置连接数据库的4 个基本信息 -->           <property name="driver"  value="com.mysql.jdbc.Driver" />           <property name="url"  value="jdbc:mysql://localhost:3306/eesy_mybatis" />           <property name="username"  value="root" />           <property name="password"  value="root" />       </dataSource> 
MyBatis在初始化时,根据的type属性来创建相应类型的数据源DataSource,即: 
type=“POOLED” :MyBatis会创建PooledDataSource实例**type=”UNPOOLED”**:MyBatis会创建UnpooledDataSource实例 
**type=”JNDI”**:MyBatis会从JNDI服务上查找DataSource实例,然后返回使用。 
 
5、MyBatis中DataSource的存取 MyBatis是通过工厂模式来创建数据源DataSource对象的,MyBatis定义了抽象的工厂接口org.apache.ibatis.datasource.DataSourceFactory,通过其getDataSource()方法返回数据源DataSource。
MyBatis 创建了 DataSource 实例后,会将其放到 Configuration 对象内的 Environment 对象中, 供以后使用。
6、MyBatis中连接的获取过程分析 当我们需要创建SqlSession对象并需要执行SQL语句时,这时候MyBatis才会去调用dataSource对象来创建java.lang.Connection对象。也就是说java.lang.Connection对象的创建会一直延迟到SQL语句执行的时候才创建。
1 2 3 4 5 6 7 8 @Test public  void  testSql ()  throws  Exception {	InputStream  in  =  Resources.getResourceAsStream("SqlMapConfig.xml" ); 	SqlSessionFactory  factory  =  new  SqlSessionFactoryBuilder ().build(in); 	SqlSession  sqlSession  =  factory.openSession(); 	List<User> list = sqlSession.selectList("findUserById" ,41 ); 	System.out.println(list.size()); } 
由上面的代码可知,只有知道第四条语句(sqlSession.selectList(“findUserById”,41))的时候,才会触发MyBatis在底层执行下面的方法来创建java.lang.Connection对象。
下面时获取连接的源码
总结: 真正打开连接的时间点,只是在执行SQL语句的时候才会进行。这样做的原因是因为数据库连接是十分宝贵的资源,只有在要用到的时候才去获取并打开连接,当我们使用完毕之后再立即将数据库连接归还到连接池中。
二、MyBatis中的事务控制 1、MyBatis中的事务提交方式 MyBatis中的事务提交方式本质就是调用JDBC的setAutoCommit()来实现事务控制的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 @Before    public  void  init ()  throws  Exception {                in = Resources.getResourceAsStream("SqlMapConfig.xml" );                SqlSessionFactory  factory  =  new  SqlSessionFactoryBuilder ().build(in);                session = factory.openSession();                userDao = session.getMapper(IUserDao.class);    }    @After     public  void  destroy ()  throws  Exception {                session.commit();                session.close();        in.close();    } @Test public  void  testSaveUser ()  throws  Exception {	User  user  =  new  User (); 	user.setUsername("mybatis user09" ); 	int  res  =  userDao.saveUser(user); 	System.out.println(res); 	System.out.println(user.getId()); } 
在控制台的输出结果为:
由上面可知我们每次进行CUD操作时都要手动的进行事务提交。原因是因为setAutoCommit()方法在执行的时候的值被设置为false,所以在CUD操作时都需调用sqlSession()方法手动的提交操作。
2、MyBatis中自动提交事务 CUD过程中之所以必须使用sqlSession.commit()提交事务,主要原因是在连接池中取出的连接 都会调用connection.setAutoCommit(false)方法提交事务。这样就必须使用sqlSession.commit()方法手动提交,相当于使用了JDBC中的connection.commit()方法实现事务提交。
自动提交事务的修改代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @Before public  void  init ()  throws  Exception {         in = Resources.getResourceAsStream("SqlMapConfig.xml" );          SqlSessionFactoryBuilder  builder  =  new  SqlSessionFactoryBuilder ();          factory = builder.build(in);          session = factory.openSession(true );          userDao = session.getMapper(IUserDao.class); } @After public  void  destroy ()  throws  Exception {         session.close();     in.close(); } 
此时事务便会被设置为自动提交,同样可以实现CUD操作时记录的保存。但就编程而言,设置为自动提交方式为false更为常用。
三、MyBatis的动态SQL语句 在刚开始入门的时候我们所学习的SQL都是比较简单的,但当我们的业务逻辑变得复杂时,我们的SQL是动态变化的。
1、动态SQL语句之标签  在根据实体类的不同取值,使用不同的SQL语句来进行查询。比如id不为空时可以根据id查询,如果username不为空时还需要加入username作为查询的约束条件。
(1)持久层Dao接口 1 2 3 4 5 int  updateUser (User user) ;
(2)持久层Dao映射配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19     <update  id ="updateUser"  parameterType ="com.itheima.domain.User" >          update user         <set >              <if  test ="username != null" >                  username = #{username},             </if >              <if  test ="sex != null" >                  sex = #{sex},             </if >              <if  test ="birthday != birthday" >                  birthday = #{birthday},             </if >              <if  test ="address != null" >                  address = #{address}             </if >          </set >           where id = #{id}     </update >  
注意事项: 标签的test属性写的是对象的属性名,如果是包装类的对象要使用OGNL表达式的写法 
(3)测试 1 2 3 4 5 6 7 8 @Test public  void  updateUserTest () {    User  user  =  new  User (53 ,"wangwu" ,null ,"男" ,null );     System.out.println(userDao.updateUser(user)); } 
2、动态SQL语句之标签  where也可以使用动态的标签来简化开发 
(1)持久层Dao的映射配置 1 2 3 4 5 6 7 8 9 10 11 12   <select  id ="findByUser"  resultType ="user"  parameterType ="user" >         <include  refid ="defaultSql" > </include >          <where >              <if  test ="username!=null and username != '' " >  			and username like #{username} 		</if >             <if  test ="address != null" >  			and address like #{address} 		</if >  	</where >  </select > 
3、动态SQL语句之标签  (1)需求 当传入多个id查询用户信息,可以使用下面的sql语句实现:
SELECT  *  FROM  USER  WHERE  username  LIKE   ‘%张%’  AND  (id  =  10  OR  id  =  98  OR  id  =  16);
SELECT  *  FROM  USER  WHERE  username  LIKE   ‘%张%’  AND  id  IN  (10,98,16);
在进行范围查询时就需要将一个集合中的值作为动态添加进来。
(2)实现方式——在QueryVo中加入一个List集合用于封装参数 1 2 3 4 5 6 7 8 public  class  QueryVo  implements  Serializable  {	private  List<Integer> ids;                public  List<Integer> getIds ()  {return  ids; }                public  void  setIds (List<Integer> ids)  {this .ids = ids; }        } 
(3)持久层Dao接口 1 2 3 4 5 6 List<User> findInIds (QueryVo vo) ; 
(4)持久层Dao映射配置 1 2 3 4 5 6 7 8 9 10 11 12 13   <select  id ="findInIds"  resultType ="user"  parameterType ="queryvo" >        <include  refid ="defaultSql" > </include >         <where >             <if  test ="ids != null and ids.size() > 0" >                 <foreach  collection ="ids"  open ="id in ( "  close =")"  item ="uid"  separator ="," >  				#{uid} 			</foreach >  		</if >  	</where >  </select > 
标签的属性: 
collection:代表要遍历的集合元素,注意编写时不要写#{}; 
open:代表语句要开始的部分; 
close:代表结束部分; 
item:代表遍历集合的每个元素,生成的变量名; 
sperator:代表分隔符。 
 
(5)编写测试用例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Test public  void  testFindInIds ()  {	QueryVo  vo  =  new  QueryVo (); 	List<Integer> ids = new  ArrayList <Integer>(); 	ids.add(41 ); 	ids.add(42 ); 	ids.add(43 ); 	ids.add(46 ); 	ids.add(57 ); 	vo.setIds(ids); 	List<User> users = userDao.findInIds(vo); 	for (User user : users) { 		System.out.println(user); 	}     } 
四、MyBatis中简化编写的SQL片段 1、定义重复出现的sql语句片段 1 2 3 4 <sql  id ="defaultSql" > 	select * from user </sql > 
2、引用代码片段 1 2 3 4 5 6 7 8 9 10 <select  id ="findAll"  resultType ="user" > 	<include  refid ="defaultSql" > </include >  </select > <select  id ="findById"  resultType ="User"  parameterType ="int" > 	<include  refid ="defaultSql" > </include >         where id = #{id} </select > 
五、MyBatis多表查询之一对一 通过Account查询对应的User信息 1、环境搭建 (1)数据库搭建 1 2 3 4 5 6 7 8 9 10 11 12 13 14 DROP  TABLE  IF EXISTS  `account`;CREATE  TABLE  `account` (  `ID` int (11 ) NOT  NULL  COMMENT '编号' ,   `UID` int (11 ) default  NULL  COMMENT '用户编号' ,   `MONEY` double  default  NULL  COMMENT '金额' ,   PRIMARY  KEY  (`ID`),   KEY `FK_Reference_8` (`UID`),   CONSTRAINT  `FK_Reference_8` FOREIGN  KEY (`UID`) REFERENCES  `user ` (`id`) ) ENGINE= InnoDB DEFAULT  CHARSET= utf8; insert   into  `account`(`ID`,`UID`,`MONEY`) values  (1 ,46 ,1000 ),(2 ,45 ,1000 ),(3 ,46 ,2000 );
数据库中数据详情
user表
account表
 
(2)创建maven工程 
2、创建account表的实体类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 package  com.itheima.domain;import  java.io.Serializable;public  class  Account  implements  Serializable  {    private  Integer id;     private  Integer uid;     private  Double money;     private  User user;     @Override      public  String toString ()  {         return  "Account{"  +                 "id="  + id +                 ", uid="  + uid +                 ", money="  + money +                 ", user="  + user +                 '}' ;     }     public  User getUser ()  {         return  user;     }     public  void  setUser (User user)  {         this .user = user;     }     public  Integer getId ()  {         return  id;     }     public  void  setId (Integer id)  {         this .id = id;     }     public  Integer getUid ()  {         return  uid;     }     public  void  setUid (Integer uid)  {         this .uid = uid;     }     public  Double getMoney ()  {         return  money;     }     public  void  setMoney (Double money)  {         this .money = money;     } } 
创建账户表与用户表的另一实体类,用于封装数据
数据格式(account[id,uid,money]		accountUser[username,address])
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 package  com.itheima.domain;public  class  AccountUser  extends  Account  {    private  String username;     private  String address;     public  String getUsername ()  {         return  username;     }     public  void  setUsername (String username)  {         this .username = username;     }     public  String getAddress ()  {         return  address;     }     public  void  setAddress (String address)  {         this .address = address;     }     @Override      public  String toString ()  {         return  super .toString() + "            AccountUser{"  +                 "username='"  + username + '\''  +                 ", address='"  + address + '\''  +                 '}' ;     } } 
3、创建account表的持久层接口 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package  com.itheima.dao;import  com.itheima.domain.Account;import  com.itheima.domain.AccountUser;import  java.util.List;public  interface  IAccountDao  {         List<Account> findAll () ;               List<AccountUser> findAllAccount () ; } 
4、编写持久层Dao接口的映射配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 <?xml version="1.0"  encoding="UTF-8" ?> <!DOCTYPE mapper          PUBLIC  "-//mybatis.org//DTD Mapper 3.0//EN"          "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper  namespace ="com.itheima.dao.IAccountDao" >          <resultMap  id ="accountUserMap"  type ="account" >          <id  property ="id"  column ="aid" > </id >          <result  column ="uid"  property ="uid" > </result >          <result  column ="money"  property ="money" > </result >                   <association  property ="user"  column ="uid"  javaType ="user" >              <id  property ="id"  column ="id" > </id >              <result  column ="username"  property ="username" > </result >              <result  column ="address"  property ="address" > </result >              <result  column ="sex"  property ="sex" > </result >              <result  column ="birthday"  property ="birthday" > </result >          </association >      </resultMap >           <select  id ="findAll"  resultMap ="accountUserMap" >          select a.*,u.username,u.address from account a , user u where u.id = a.uid     </select >           <select  id ="findAllAccount"  resultType ="com.itheima.domain.AccountUser" >          select a.*,u.username,u.address from account a , user u where u.id = a.uid     </select >  </mapper > 
association标签 :当实体类中包含另一个实体类对象作为成员变量时,封装结果集时使用该标签。
总结: 封装的结果集中包含另外一张表的信息,且另外一张表的实体类作为查询表的成员变量时使用该标签封装另一张表的数据。
标签内部的标签与resultMap标签 一致,id标签 为另外一张表的主键信息,result标签 为其余封装的列的信息。
5、编写测试用例用于结果测试 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41    @Test     public  void  findByAllTest () {        List<Account> accounts = accountDao.findAll();        for  (Account account: accounts) {            System.out.println("---------------------------" );            System.out.println(account);            System.out.println(account.getUser());        }    }        @Test     public  void  findByAccountTest () {        List<AccountUser> accountUsers = accountDao.findAllAccount();        for  (AccountUser accountUser: accountUsers) {            System.out.println(accountUser);        }    } 
六、MyBatis多表查询之一对多查询 通过User查询Account的信息 1、User实体类的修改 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 package  com.itheima.domain;import  java.util.Date;import  java.util.List;public  class  User  {    private  Integer id;     private  String username;     private  Date birthday;     private  String sex;     private  String address;          private  List<Account> accounts;     public  User ()  {     }     @Override      public  String toString ()  {         return  "User{"  +                 "id="  + id +                 ", username='"  + username + '\''  +                 ", birthday="  + birthday +                 ", sex='"  + sex + '\''  +                 ", address='"  + address + '\''  +                 '}' ;     }     public  List<Account> getAccounts ()  {         return  accounts;     }     public  void  setAccounts (List<Account> accounts)  {         this .accounts = accounts;     }     public  Integer getId ()  {         return  id;     }     public  void  setId (Integer id)  {         this .id = id;     }     public  String getUsername ()  {         return  username;     }     public  void  setUsername (String username)  {         this .username = username;     }     public  Date getBirthday ()  {         return  birthday;     }     public  void  setBirthday (Date birthday)  {         this .birthday = birthday;     }     public  String getSex ()  {         return  sex;     }     public  void  setSex (String sex)  {         this .sex = sex;     }     public  String getAddress ()  {         return  address;     }     public  void  setAddress (String address)  {         this .address = address;     } } 
2、编写持久层Dao接口 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package  com.itheima.dao;import  com.itheima.domain.User;import  java.util.List;public  interface  IUserDao  {         List<User> findByAll () ;          User findById (int  id) ; } 
3、编写持久层Dao接口的映射配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 <?xml version="1.0"  encoding="UTF-8" ?> <!DOCTYPE mapper          PUBLIC  "-//mybatis.org//DTD Mapper 3.0//EN"          "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper  namespace ="com.itheima.dao.IUserDao" >          <resultMap  id ="userMap"  type ="user" >          <id  property ="id"  column ="id" > </id >          <result  property ="username"  column ="username" > </result >          <result  property ="address"  column ="address" > </result >          <result  property ="sex"  column ="sex" > </result >          <result  property ="birthday"  column ="birthday" > </result >                   <collection  property ="accounts"  ofType ="account" >              <id  property ="id"  column ="aid" > </id >              <result  property ="uid"  column ="uid" > </result >              <result  property ="money"  column ="money" > </result >          </collection >      </resultMap >           <select  id ="findByAll"  resultMap ="userMap" >          select * from user u left  outer join account a on u.id = a.uid     </select >           <select  id ="findById"  resultType ="com.itheima.domain.User"  parameterType ="int" >          select * from user         where id = #{id}     </select >  </mapper > 
collection标签 :与上面的association标签 大致一样,不过该标签使用的对象是集合对象而不是实体类对象。
4、编写接口Dao的测试用例 1 2 3 4 5 6 7 8 9 10 11 12 @Test public  void  findByAll () {    List<User> users = userDao.findByAll();     for  (User user: users) {         System.out.println("----------------------" );         System.out.println(user);         System.out.println(user.getAccounts());     } } 
运行的结果为
七、MyBatis多表查询之多对多 通过角色表Role查询User信息多对多 1、环境搭建 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 DROP  TABLE  IF EXISTS  `role`;CREATE  TABLE  `role` (  `ID` int (11 ) NOT  NULL  COMMENT '编号' ,   `ROLE_NAME` varchar (30 ) default  NULL  COMMENT '角色名称' ,   `ROLE_DESC` varchar (60 ) default  NULL  COMMENT '角色描述' ,   PRIMARY  KEY  (`ID`) ) ENGINE= InnoDB DEFAULT  CHARSET= utf8; insert   into  `role`(`ID`,`ROLE_NAME`,`ROLE_DESC`) values  (1 ,'院长' ,'管理整个学院' ),(2 ,'总裁' ,'管理整个公司' ),(3 ,'校长' ,'管理整个学校' );DROP  TABLE  IF EXISTS  `user_role`;CREATE  TABLE  `user_role` (  `UID` int (11 ) NOT  NULL  COMMENT '用户编号' ,   `RID` int (11 ) NOT  NULL  COMMENT '角色编号' ,   PRIMARY  KEY  (`UID`,`RID`),   KEY `FK_Reference_10` (`RID`),   CONSTRAINT  `FK_Reference_10` FOREIGN  KEY (`RID`) REFERENCES  `role` (`ID`),   CONSTRAINT  `FK_Reference_9` FOREIGN  KEY (`UID`) REFERENCES  `user ` (`id`) ) ENGINE= InnoDB DEFAULT  CHARSET= utf8; insert   into  `user_role`(`UID`,`RID`) values  (41 ,1 ),(45 ,1 ),(41 ,2 );
数据库中数据详情
role表
role_user中间表
 
(2)创建maven工程 
2、编写角色表的实体类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 package  com.itheima.domain;import  java.io.Serializable;import  java.util.List;public  class  Role  implements  Serializable  {    private  Integer roleId;     private  String roleName;     private  String roleDesc;          private  List<User> users;     public  Integer getRoleId ()  {         return  roleId;     }     public  void  setRoleId (Integer roleId)  {         this .roleId = roleId;     }     public  String getRoleName ()  {         return  roleName;     }     public  void  setRoleName (String roleName)  {         this .roleName = roleName;     }     public  String getRoleDesc ()  {         return  roleDesc;     }     public  void  setRoleDesc (String roleDesc)  {         this .roleDesc = roleDesc;     }     public  List<User> getUsers ()  {         return  users;     }     public  void  setUsers (List<User> users)  {         this .users = users;     }     @Override      public  String toString ()  {         return  "Role{"  +                 "roleId="  + roleId +                 ", roleName='"  + roleName + '\''  +                 ", roleDesc='"  + roleDesc + '\''  +                 '}' ;     } } 
3、编写角色表的持久层Dao接口 1 2 3 4 5 6 7 8 9 10 11 12 13 package  com.itheima.dao;import  com.itheima.domain.Role;import  java.util.List;public  interface  IRoleDao  {         List<Role> findAll () ; } 
4、编写持久层Dao接口的配置文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 <?xml version="1.0"  encoding="UTF-8" ?> <!DOCTYPE mapper          PUBLIC  "-//mybatis.org//DTD Mapper 3.0//EN"          "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper  namespace ="com.itheima.dao.IRoleDao" >     <resultMap  id ="roleMap"  type ="role" >          <id  property ="roleId"  column ="rid" />          <result  property ="roleName"  column ="role_name" />          <result  property ="roleDesc"  column ="role_desc" />          <collection  property ="users"  ofType ="user" >              <id  property ="id"  column ="id" />              <result  property ="username"  column ="username" />              <result  property ="sex"  column ="sex" />              <result  property ="address"  column ="address" />              <result  property ="birthday"  column ="birthday" />          </collection >      </resultMap >           <select  id ="findAll"  resultMap ="roleMap" >                   select u.*,r.id as rid,r.role_name,r.role_desc from role r         left outer join user_role ur on r.id = ur.rid         left outer join user u on u.id = ur.uid     </select >  </mapper > 
5、编写测试类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 package  com.itheima.test;import  com.itheima.dao.IRoleDao;import  com.itheima.domain.Role;import  org.apache.ibatis.io.Resources;import  org.apache.ibatis.session.SqlSession;import  org.apache.ibatis.session.SqlSessionFactory;import  org.apache.ibatis.session.SqlSessionFactoryBuilder;import  org.junit.After;import  org.junit.Before;import  org.junit.Test;import  java.io.InputStream;import  java.util.List;public  class  IRoleDaoTest  {    private  InputStream  in  =  null ;     private  SqlSession  session  =  null ;     private  IRoleDao iRoleDao;     @Before      public  void  init ()  throws  Exception {                  in = Resources.getResourceAsStream("SqlMapConfig.xml" );                  SqlSessionFactory  factory  =  new  SqlSessionFactoryBuilder ().build(in);                  session = factory.openSession(true );                  iRoleDao = session.getMapper(IRoleDao.class);     }     @After      public  void  destroy ()  throws  Exception {                           session.close();         in.close();     }     @Test      public  void  findAllTest () {         List<Role> roles = iRoleDao.findAll();         for  (Role role : roles) {             System.out.println("-----------------------" );             System.out.println(role);             System.out.println(role.getUsers());         }     } } 
运行结果为;
通过User表进行多对多查询Account表信息 1、编写用户表的实体类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 package  com.itheima.domain;import  java.util.Date;import  java.util.List;public  class  User  {    private  Integer id;     private  String username;     private  Date birthday;     private  String sex;     private  String address;          private  List<Role> roles;     public  User ()  {     }     @Override      public  String toString ()  {         return  "User{"  +                 "id="  + id +                 ", username='"  + username + '\''  +                 ", birthday="  + birthday +                 ", sex='"  + sex + '\''  +                 ", address='"  + address + '\''  +                 '}' ;     }     public  List<Role> getRoles ()  {         return  roles;     }     public  void  setRoles (List<Role> roles)  {         this .roles = roles;     }     public  Integer getId ()  {         return  id;     }     public  void  setId (Integer id)  {         this .id = id;     }     public  String getUsername ()  {         return  username;     }     public  void  setUsername (String username)  {         this .username = username;     }     public  Date getBirthday ()  {         return  birthday;     }     public  void  setBirthday (Date birthday)  {         this .birthday = birthday;     }     public  String getSex ()  {         return  sex;     }     public  void  setSex (String sex)  {         this .sex = sex;     }     public  String getAddress ()  {         return  address;     }     public  void  setAddress (String address)  {         this .address = address;     } } 
2、编写角色表的持久层Dao接口 1 2 3 4 5    List<User> findAll () ; 
3、编写持久层Dao接口的配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 <?xml version="1.0"  encoding="UTF-8" ?> <!DOCTYPE mapper          PUBLIC  "-//mybatis.org//DTD Mapper 3.0//EN"          "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper  namespace ="com.itheima.dao.IUserDao" >     <resultMap  id ="userRoleMap"  type ="user" >          <id  property ="id"  column ="id" />          <result  property ="username"  column ="username" />          <result  property ="sex"  column ="sex" />          <result  property ="address"  column ="address" />          <result  property ="birthday"  column ="birthday" />          <collection  property ="roles"  ofType ="role" >              <id  property ="roleId"  column ="id" />              <result  property ="roleName"  column ="role_name" />              <result  property ="roleDesc"  column ="role_Desc" />          </collection >      </resultMap >           <select  id ="findAll"  resultMap ="userRoleMap" >          select u.*,r.id as rid,r.role_name,r.role_desc from user u         left outer join user_role ur on ur.uid = u.id         left outer join role r on r.id = ur.rid     </select >  </mapper > 
4、编写测试类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 package  com.itheima.test;import  com.itheima.dao.IUserDao;import  com.itheima.domain.User;import  org.apache.ibatis.io.Resources;import  org.apache.ibatis.session.SqlSession;import  org.apache.ibatis.session.SqlSessionFactory;import  org.apache.ibatis.session.SqlSessionFactoryBuilder;import  org.junit.After;import  org.junit.Before;import  org.junit.Test;import  java.io.InputStream;import  java.util.List;public  class  IUserDaoTest  {    private  InputStream  in  =  null ;     private  SqlSession  session  =  null ;     private  IUserDao userDao;     @Before      public  void  init ()  throws  Exception {                  in = Resources.getResourceAsStream("SqlMapConfig.xml" );                  SqlSessionFactory  factory  =  new  SqlSessionFactoryBuilder ().build(in);                  session = factory.openSession(true );                  userDao = session.getMapper(IUserDao.class);     }     @After      public  void  destroy ()  throws  Exception {                           session.close();         in.close();     }     @Test      public  void  findAllTest () {         List<User> users = userDao.findAll();         for  (User user : users) {             System.out.println("---------------------" );             System.out.println(user);             System.out.println(user.getRoles());         }     } } 
运行结果:
八、JNDI搭建maven的war工程 1、JNDI的基本概念 JNDI(Java Naming and Directory Interface,Java命名和目录接口)是SUN公司提供的一种标准的Java命名系统接口,JNDI提供统一的客户端API,通过不同的访问提供者接口JNDI服务供应接口(SPI)的实现,由管理者将JNDI API映射为特定的命名服务和目录系统,使得Java应用程序可以和这些命名服务和目录服务之间进行交互。
目录服务是命名服务的一种自然扩展。两者之间的关键差别是目录服务中对象不但可以有名称还可以有属性(例如,用户有email地址),而命名服务中对象没有属性。
2、创建一个war工程 (1)create new modules 创建maven下的webapp工程
(2)填写坐标信息 (3)在创建好的项目的main目录下创建文件夹 在main目录下新建java和resoures,并将两个文件设置为source root和resoures root源码文件
在test目录下新建一个java文件夹,设置为test source root文件夹
(4)导入依赖 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 <?xml version="1.0"  encoding="UTF-8" ?> <project  xmlns ="http://maven.apache.org/POM/4.0.0"  xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"    xsi:schemaLocation ="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" >   <modelVersion > 4.0.0</modelVersion >    <groupId > com.itheima</groupId >    <artifactId > day03_eesy_jndi</artifactId >    <version > 1.0-SNAPSHOT</version >    <packaging > war</packaging >    <name > day03_eesy_jndi Maven Webapp</name >       <url > http://www.example.com</url >    <properties >      <project.build.sourceEncoding > UTF-8</project.build.sourceEncoding >      <maven.compiler.source > 1.7</maven.compiler.source >      <maven.compiler.target > 1.7</maven.compiler.target >    </properties >    <dependencies >      <dependency >        <groupId > org.mybatis</groupId >        <artifactId > mybatis</artifactId >        <version > 3.4.5</version >      </dependency >      <dependency >        <groupId > mysql</groupId >        <artifactId > mysql-connector-java</artifactId >        <version > 5.1.6</version >      </dependency >      <dependency >        <groupId > junit</groupId >        <artifactId > junit</artifactId >        <version > 4.10</version >      </dependency >      <dependency >        <groupId > log4j</groupId >        <artifactId > log4j</artifactId >        <version > 1.2.12</version >      </dependency >      <dependency >        <groupId > javax.servlet</groupId >        <artifactId > servlet-api</artifactId >        <version > 2.5</version >      </dependency >      <dependency >        <groupId > javax.servlet.jsp</groupId >        <artifactId > jsp-api</artifactId >        <version > 2.0</version >      </dependency >    </dependencies >    <build >      <finalName > day03_eesy_jndi</finalName >      <pluginManagement >        <plugins >          <plugin >            <artifactId > maven-clean-plugin</artifactId >            <version > 3.1.0</version >          </plugin >                   <plugin >            <artifactId > maven-resources-plugin</artifactId >            <version > 3.0.2</version >          </plugin >          <plugin >            <artifactId > maven-compiler-plugin</artifactId >            <version > 3.8.0</version >          </plugin >          <plugin >            <artifactId > maven-surefire-plugin</artifactId >            <version > 2.22.1</version >          </plugin >          <plugin >            <artifactId > maven-war-plugin</artifactId >            <version > 3.2.2</version >          </plugin >          <plugin >            <artifactId > maven-install-plugin</artifactId >            <version > 2.5.2</version >          </plugin >          <plugin >            <artifactId > maven-deploy-plugin</artifactId >            <version > 2.8.2</version >          </plugin >        </plugins >      </pluginManagement >    </build >  </project > 
(5)修改SqlMapConfig.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 <?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 ="com.itheima.domain" />      </typeAliases >           <environments  default ="development" >                   <environment  id ="development" >                           <transactionManager  type ="JDBC" > </transactionManager >                           <dataSource  type ="JNDI" >                  <property  name ="data_source"  value ="java:comp/env/jdbc/eesy_mybatis" />              </dataSource >          </environment >      </environments >           <mappers >          <mapper  resource ="com/itheima/dao/IAccountDao.xml" />          <mapper  resource ="com/itheima/dao/IUserDao.xml" />      </mappers >  </configuration > 
(6)在webapp目录下新建配置文件 在webapp目录下新建META-INF文件,并在文件夹中导入数据库配置文件context.xml
以下是context.xml文件配置的数据库文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 <?xml version="1.0"  encoding="UTF-8" ?> <Context > <Resource   name ="jdbc/eesy_mybatis" type ="javax.sql.DataSource" auth ="Container" maxActive ="20" maxWait ="10000" maxIdle ="5" username ="root" password ="root" driverClassName ="com.mysql.jdbc.Driver" url ="jdbc:mysql://localhost:3306/eesy_mybatis" /> </Context > 
(7)修改index.jsp文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 <%@ page import ="java.io.InputStream"  %> <%@ page import ="org.apache.ibatis.io.Resources"  %> <%@ page import ="org.apache.ibatis.session.SqlSessionFactoryBuilder"  %> <%@ page import ="org.apache.ibatis.session.SqlSessionFactory"  %> <%@ page import ="org.apache.ibatis.session.SqlSession"  %> <%@ page import ="com.itheima.dao.IUserDao"  %> <%@ page import ="com.itheima.domain.User"  %> <%@ page import ="java.util.List"  %> <%@ page language="java"  contentType="text/html; charset=UTF-8"  pageEncoding="UTF-8" %> <html> <body> <h2>Hello World!</h2> <%               InputStream  in  =  Resources.getResourceAsStream("SqlMapConfig.xml" );          SqlSessionFactoryBuilder  builder  =  new  SqlSessionFactoryBuilder ();     SqlSessionFactory  factory  =  builder.build(in);          SqlSession  sqlSession  =  factory.openSession();          IUserDao  userDao  =  sqlSession.getMapper(IUserDao.class);          List<User> users = userDao.findAll();     for (User user : users){         System.out.println(user);     }          sqlSession.close();     in.close(); %> </body> </html> 
(8)配置Tomcat项目 /JDNI Tomcat.JPG)
启动服务器打开浏览器即可在控制台看到如下内容
参考资料
传智黑马MyBatis
[https://www.bilibili.com/video/BV1SJ411679L] :