mybatis中的连接池以及事务控制
- 连接池:在实际开发中会使用连接池,可以减少获取连接时所消耗的时间
- 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连接池
- mybatis中的事务
- 什么是事务
- 事务的四大特性
- 不考虑隔离性会产生的3个问题
- 解决办法:四种隔离级别
通过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服务器,启动,刷新,即可看见程序正常执行。