mybatis中的连接池以及事务控制

  1. 连接池:在实际开发中会使用连接池,可以减少获取连接时所消耗的时间
  2. mybatis中的连接池
    mybatis连接池提供了3种方式的配置:
    配置的位置:
    主配置文件SqlMapConfig.xml中的dataSource标签,type属性就是表示采用何种连接池方式。
    type属性的取值:
    POOLED 采用 传统的javax.sql.DataSource规范中的连接池,mybatis中有针对规范的实现
    UNPOOLED 采用传统的获取连接的方式,虽然也实现了javax.sql.DataSource接口,但是并没有 使用池的思想。
    JNDI 采用服务器提供的JNDI技术实现,来获取DataSource对象,不同的服务器所能拿到的 DataSource对象不一样
    注意:如果不是web或者maven的war过程,是不能使用的。课程中使用tomcat服务器,采用dbcp连接池
  1. mybatis中的事务
  1. 什么是事务
  2. 事务的四大特性
  3. 不考虑隔离性会产生的3个问题
  4. 解决办法:四种隔离级别

通过SqlSession对象的commit方法和rollback方法实现事务的提交和回滚

mybatis中连接池使用分析

mybatis事务控制的分析

mybatis基于XML配置的动态SQL语句使用

mappers配置文件中的几个标签

: 条件判断

and username=#{username}

: sql语句的条件判断

and username=#{username}

and sex=#{sex}

</if>

colletion:表示集合

open:开始

close:结束

item:集合里面的值,决定括号中的写法

separator:分隔符

#{uid}

:抽取重复标签,末尾加";"会导致条件查询中拼接失败

select * from user

抽取之后的使用:

<select id="findAllUser" resultType="USER"> <include refid="defaultUser"></include> </select>


mybatis中的多表操作

一对一(?)

用户和订单就是一对多
订单和用户就是多对一
测试多表查询(一对多):
1.建立一个user表:
CREATE TABLE `user` (
  `id` int(11) NOT NULL auto_increment,
  `username` varchar(32) NOT NULL COMMENT '用户名称',
  `birthday` datetime default NULL COMMENT '生日',
  `sex` char(1) default NULL COMMENT '性别',
  `address` varchar(256) default NULL COMMENT '地址',
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
插入数据:
insert into user (username,birthday,'sex','address') values ('铁憨憨','2000-01-01','男','上海');
insert into user (username,birthday,'sex','address') values ('大风车','2000-01-02','男','北京');
2.建立一个account表,并且让它的uid和用户表user的id产生外键:
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;
这个插入数据使用可视化软件插入,语句好像不行?

查询出所有账户,同时包含用户的名称和地址:
sql语句:
select u.username,u.address,a.* from user u,account a where a.uid=u.id;

第一种方法:

创建一个新的实体类AccountUser,继承Account,新定义成员变量username,address,生成get和set方法,
tostring方法,在tostring方法中使用super关键字调用父类Account的tostring方法,再用"+"连接生成的tostring方法,就能让mybatis进行自动封装,达到想要的功能。此时IAccountDao.xml文件中返回的结果集为accountuser。

第二种方法:

1.在Account实体类下新定义一个User对象(private User user;)
2.生成get和set方法
3.配置IAccountDao.xml文件(定义封装account和user的rusultMap)
<resultMap id="accountUserMap" type="account">
		<!-- 先定义封装account的属性 -->
        <id property="id" column="aid"></id>
        <result property="uid" column="uid"></result>
        <result property="money" column="money"></result>
        <!-- 一对一的关系映射:配置封装user的内容 -->
        <association property="user" column="uid" javaType="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>
        </association>
  </resultMap>
  
4.执行查询语句,并将结果封装到Account集合
  <!-- 使用resultMap的方式进行封装 -->
  <select id="findAll" resultMap="accountUserMap">
        select u.*,a.id as aid,a.uid,a.money from account a,user u where a.uid=u.id;
  </select>
  
5.调用测试:
  创建测试类,使用Junit进行测试:
  		List<Account> accounts = accountDao.findAll();
        for (Account account:accounts){

            System.out.println("------每个account的信息-------");

            System.out.println(account);
            System.out.println(account.getUser());

        }

一对多

人和身份证是一对一
身份证和人是一对一

需求:查询所有用户,同时获取到用户下所有账户信息

sql语句:
select * from user u left outer join on accout a on a.uid=u.id;
1.在User实体类下定义一个Account对象,并生成它的get和set方法
2.配置IUserDao.xml文件
	1.定义User的resultMap
	<resultMap id="userAccountMap" type="user">
		<id property="id" column="id"></id>
		<result property="username" column="username"></result>
		<result property="birthday" column="birthday"></result>
		<result property="sex" column="sex"></result>
		<result property="address" column="address"></result>
		<!-- 配置User对象中accounts集合的映射 -->
		<collection property="accounts" ofType="account">
			<id property="id" column="aid"></id>
			<result property="uid" column="uid"></result>
			<result property="money" column="money"></result>
		</colletion>
	</resultMap>
3.执行查询语句,并将结果封装到User集合
<select id="findAllUser" resultMap="userAccountMap">
	select * user u left outer join account a on a.uid=u.id;
</select>
4.测试类中运行
		List<User> users = userDao.findAllUser();
        for (User user:
             users) {
            System.out.println("-----每个用户的信息-----");
            System.out.println(user);
            System.out.println(user.getAccounts());
        }

多对多

老师和学生之间是多对多
学生和老师之间是多对多

示例:用户和角色

一个用户可以有多个角色

一个角色可以赋予多个用户

步骤:
1.建立两张表:用户表、角色表
	让用户表和角色表之间具备多对多的关系:需要使用中间表,中间表中包含各自的主键,在中间表中是外键。
	
2.建立两个实体类:用户实体类和角色实体类
	让用户和角色的实体类能体现出来多对多的关系
	各自包含对方一个集合引用
	
3.建立两个配置文件
	用户配置文件
	角色配置文件
	
4.实现配置:
	当查询用户时,可以同时得到用户下所包含的角色信息
	当查询角色时,可以同时得到角色的所属用户信息

查询所有的角色,同时角色下的所有用户一起被查询

sql语句:
select r.id as rid,r.role_name,r.role_desc,u.* from role r left outer join user_role ur on r.id=ur.rid left outer join user u on u.id=ur.uid;

1.在Role的实体类下建立User的对象集合(private List<User> users),并生成get和set方法
2.配置IRoleDao.xml文件(定义封装User集合和Role对象的ResultMap)
<resultMap id="roleMap" type="role">
	<!-- 此处封装role对象 -->
	<id property="roleId" column="rid"></id>
	<result property="roleName" column="role_name"></result>
	<result property="roleDesc" column="role_desc"></result>
	<!-- 此处封装 user对象集合 -->
	<collection>
		<id property="users" ofType="user"></id>
        <result property="username" column="username"></result>
        <result property="birthday" column="birthday"></result>
        <result property="sex" column="sex"></result>
        <result property="address" column="address"></result>
	</collection>
</resultMap>
3.执行查询语句,并将结果封装到Role集合
<select id="findAll" resultMap="roleMap">
	select r.id as rid,r.role_name,r.role_desc,u.* from role r left outer join user_role ur on ur.rid=r.id left outer join user u on u.id=ur.uid;
</select>
4.测试
List<Role> roles = roleDao.findAll();

        for (Role role:
             roles) {

            System.out.println(role);

            System.out.println("-----role的user-------");

            System.out.println(role.getUsers());
        }

查询所有用户,同时用户下的所有角色一起被查询

sql语句:
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;

1.在User的实体类下建立Role的对象集合(private List<Role> roles),并生成get和set方法
2.配置IUserDao.xml文件(定义封装Role集合和User对象的ResultMap)
<resultMap id="userRoleMap" type="user">
	<!-- 此处封装user对象 -->
	<id property="id" column="id"></id>
        <result property="username" column="username"></result>
        <result property="birthday" column="birthday"></result>
        <result property="sex" column="sex"></result>
        <result property="address" column="address"></result>
        <!-- 将role对象封装成集合 -->
        <collection property="roles" ofType="role">
            <id property="roleId" column="rid"></id>
            <result property="roleName" column="role_name"></result>
            <result property="roleDesc" column="role_desc"></result>
        </collection>
	</collection>
</resultMap>
3.执行查询语句,并将结果封装到User集合
<select id="findAllUser" 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>
4.测试
		List<User> users = userDao.findAllUser();
        for (User user:
             users) {

            System.out.println(user);
            System.out.println("-----user中的role------");
            System.out.println(user.getRoles());
            System.out.println("-----------");
        }

特例

如果如果拿出每一个订单,它都只能属于一个用户
Mybatis把多对一堪称一对一

mybatis中的多表查询

示例:用户和账户
	一个用户可以有多个账户
	一个账户只能属于一个用户(多个账户也可以属于同一个用户)
步骤:
	1.	建立两张表:用户表,账户表
			让用户表和账户表具备一对多的关系:需要使用外键在账户表中添加
	2.	建立两个实体类:用户实体类和账户实体类
			让用户和账户的实体类能体现出一对多的关系
	3.	建立两个配置文件
		用户的配置文件
		账户的配置文件
	4.	实现配置
		当我们查询用户时,可以同时得到用户下所包含的账户信息
		当我们查询账户时,可以得到账户的所属用户信息

JNDI数据源的使用

1.建立maven工程,框架设置为webapp
2.在webapp文件夹下建立WEB-INF文件夹,并将context.xml文件拷贝进去
具体内容为:
<Context>
<Resource 
name="jdbc/eesy_mybatis"
type="javax.sql.DataSource"
auth="Container"
maxActive="20"
maxWait="10000"
maxIdle="5"
username="root"
password="xxxx"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/eesy_mybatis?serverTimezone=GMT%2B8"  <!-- 此处必须要后缀 -->
/>
</Context>
3.修改主配置文件的数据源信息
<dataSource type="JNDI">
                <!-- value的值:java:comp/env/是固定的,jdbc/eesy_mybatis是context.xml里面name属性的值 -->
                <property name="data_source" value="java:comp/env/jdbc/eesy_mybatis"/>
            </dataSource>

4.执行测试程序
在index.jsp文件里面执行测试程序,先写入:
<%@ page contentType="text/html;charset=UTF-8" language="java"  pageEncoding="UTF-8" %>
<%
    InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
    SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
    SqlSessionFactory factory = builder.build(is);
    SqlSession Sqlsession = factory.openSession();
    IUserDao userDao = Sqlsession.getMapper(IUserDao.class);
    List<User> users = userDao.findAllUser();
    for (User user : users){
        System.out.println(user);
    }
    Sqlsession.close();
    is.close();

%>
ok,现在将工程加入tomcat服务器,启动,刷新,即可看见程序正常执行。