本章学习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](MyBatis框架学习(三)/JDNI Tomcat.JPG)
启动服务器打开浏览器即可在控制台看到如下内容
参考资料
传智黑马MyBatis
[https://www.bilibili.com/video/BV1SJ411679L] :