今日课程内容
![](https://i-blog.csdnimg.cn/blog_migrate/5313b510371c6903bc17eb56af2f65c1.png)
一、mybatis中的连接池以及事务控制
1.1 连接池
- 我们在实际开发中都会使用到连接池。
- 因为它可以减少我们获取连接所消耗的时间。
![](https://i-blog.csdnimg.cn/blog_migrate/c510bf85f02f03cc22a873b6f6b88b1b.png)
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.3 POOLED和UNPOOLED区别及配置连接池的原理分析
- POOLED和UNPOOLED设置的位置
![](https://i-blog.csdnimg.cn/blog_migrate/2f9bcd37eb4c58a800650b22e952e5c6.png)
- POOLED和UNPOOLED区别
![](https://i-blog.csdnimg.cn/blog_migrate/f4b6f5f6287065ab96a9907952f75986.png)
- UNPOOLED源码分析(Mybatis中非连接池方式)
- UNPOOLED每次创建一个新的连接来用
- 步骤:每次都要注册驱动->获取连接->将连接返回去。
- POOLED源码分析(Mybatis中连接池方式)
![](https://i-blog.csdnimg.cn/blog_migrate/00a815607d8dc610a9586c34a1fc9e90.png)
- 上面源码图的分析
- POOLED它是从池中获取连接来用
- 总结:整个过程就是Mybatis给我们提供连接池的思想(及没有用以前讲的c3p0也没有用dbcp)
1.4 mybatis中的事务
- 面试内容:
- 什么是事务
- 事务的四大特性ACID
- 不考虑隔离性会产生的3个额问题
- Mybatis中的事务是通过Sqlsession对象的commit方法和rollback方法实现事务的提交和回滚。
- 注:将手动提交事务改为自动提交的方法
![](https://i-blog.csdnimg.cn/blog_migrate/be76eaee9edbff50fff5f46a5c42eed3.png)
二、mybatis映射文件的SQL深入理解
- 动态SQL之标签
- 【演示】根据条件查询【xml方式】
- 首先做好如pom.xml相应的导包。
- 在IUserDao.java接口中写方法
![](https://i-blog.csdnimg.cn/blog_migrate/27116ba5735667e2a500d09ba3e7e106.png)
- 在IUserDao.xml中配置
- 注:SQL中连接两个条件要用and,不是&&
- 注:SQL语句中不分大小写,但是其他的地方分。
![](https://i-blog.csdnimg.cn/blog_migrate/4d5a47263107aa15e6fcace49f538814.png)
- 写测试
- 这里配置了名字和性别,两个条件都满足的才可以
![](https://i-blog.csdnimg.cn/blog_migrate/71fd7e634d23eec606edae6157cc08f0.png)
- 动态SQL值标签
- where 1=1的作用
- 仅仅只是为了满足多条件查询页面中不确定的各种因素而采用的一种构造一条正确能运行的动态SQL语句的一种方法。(如果用户在多条件查询页面中,不选择任何字段、不输入任何关键词,那么,必将返回表中所有数据;如果用户在页面中,选择了部分字段并且输入了部分查询关键词,那么,就按用户设置的条件进行查询。)
- where标签的使用:
- 在 mybatis 中,为了防止此问题发生,做法如下,加where可以自动将第一个and去掉。
- 就是为了避免在每个查询语句后面加上where 1 = 1
- 使我们的SQL语句更加的清晰
![](https://i-blog.csdnimg.cn/blog_migrate/444bb09ccdc581ac61e44051f691ffbb.png)
- 动态SQL值和标签
- 【演示】SQL传参的方式用代码表示【xml方式】
- select * form user where id in(41, 42, 46);–>子查询
- 使用实体类的包装对象作为查询条件
- 将查询条件封装到对象中(只不过查询的条件被封装到一个对象里面了 )
![](https://i-blog.csdnimg.cn/blog_migrate/6e230b90020d81f6362767f30ad6ebd5.png)
- 在IUserDao.java中写方法
![](https://i-blog.csdnimg.cn/blog_migrate/7cad0d6af0d31065e9cd01ac2be22c80.png)
4.1 今天foreach标签的介绍
![](https://i-blog.csdnimg.cn/blog_migrate/5cdbc265d529814d9e6d110656f4ec3b.png)
4.2 在IUserDao.xml中配置
- 注:其实SQL语句在这里写不写;号都可以的,但是动态SQL语句要有拼接,所以不能写; 号
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O6vjuFgx-1624207232690)(http://note.youdao.com/yws/public/resource/fdbcde569b9d89bd2981a9293059b4f0/xmlnote/AAC7429DAE4B4782830FFC645E9D81E7/32479)]
- 测试方法
![](https://i-blog.csdnimg.cn/blog_migrate/e7fe6f54f06a5d08fa8124880c5fe406.png)
- 执行结果
![](https://i-blog.csdnimg.cn/blog_migrate/d0ffafb524ce51860ade76777715d907.png)
- 了解内容:抽取重复的sql语句
- 注:动态SQL语句,由于还有语句的拼接,所以要把抽取部分中的;号去掉
三、mybatis映射文件的SQL深入理解
3.1 mybatis中的多表查询
- 表之间的关系有几种:
一对多
多对一
一对一
多对多
- 举例:
用户和订单就是一对多
订单和用户就是多对一
一个用户可以下多个订单
多个订单属于同一个用户
人和身份证号就是一对一
一个人只能有一个身份证号
一个身份证号只能属于一个人
老师和学生之间就是多对多
一个学生可以被多个老师教过
一个老师可以交多个学生
- 特例:
如果拿出每一个订单,他都只能属于一个用户。
所以Mybatis就把多对一看成了一对一。
- mybatis中多表查询的
- 实例:用户和账号
- 一个用户可以有多个账户
- 一个账户只能属于一个用户(多个账户也可以属于同一个用户)
- 步骤:
- 建立两张表:用户表,账户表
- 让用户表和账户表之间具备一对多的关系:需要使用外键在账户表中添加
- 建立两个实体类:用户实体类和账户实体类
- 建立两个配置文件
- 实现配置:
- 当我们查询用户时,可以同时得到用户下所包含的账户信息
- 当我们查询账户时,可以同时得到账户的所属用户信息
- 完成account表的建立及实现单表查询(p11)
- 完成account的一对一操作(p12,13)
- 通过写account的子类方式查询【了解】
- 建立实体类关系的方式【常用】
- 首先做好如pom.xml相应的导包,数据库的搭建等
![](https://i-blog.csdnimg.cn/blog_migrate/4b25fd047e7c13dcf864461a330592e5.png)
- 创建实体类
![](https://i-blog.csdnimg.cn/blog_migrate/1f4b359644791e0530778405c5018ad6.png)
![](https://i-blog.csdnimg.cn/blog_migrate/d7d1a14af35432e2843920d17e1f66b9.png)
- 在IAccountDao.java接口中写方法
![](https://i-blog.csdnimg.cn/blog_migrate/6229b368798b0c796aa85245bfc6090e.png)
- 在IAccountDao.xml中配置
![](https://i-blog.csdnimg.cn/blog_migrate/7ded8220a30733d3ed34248b99385444.png)
- 写测试
![](https://i-blog.csdnimg.cn/blog_migrate/c0c2a3d7ad8096b815d39b9b9c1b0d77.png)
![](https://i-blog.csdnimg.cn/blog_migrate/6199f68f432adc8f60d5b0c3de1652cf.png)
- 测试结果
![](https://i-blog.csdnimg.cn/blog_migrate/bcbcc5a87292d535de8d01a49ff36389.png)
- 完成user的一对多操作(p14)
- 重要步骤一:主表实体应该包含从表实体的集合引用
![](https://i-blog.csdnimg.cn/blog_migrate/00f2f5818afd5e2d08253c0805903e64.png)
- 重要步骤二:在IUserDao.xml中配置
![](https://i-blog.csdnimg.cn/blog_migrate/da5c5cbf8f3b679b73a22b5c36abb076.png)
- 测试及结果
![](https://i-blog.csdnimg.cn/blog_migrate/66053dfa436b5334036cdef36ed30d5d.png)
![](https://i-blog.csdnimg.cn/blog_migrate/1516a07ed53863a12ead355fd972a494.png)
- 分析mybatis多对多的步骤并搭建环境
- 实例:用户和角色
- 步骤:
- 建立两张表:用户表,角色表
- 让用户表和角色表之间具备多对多的关系:需要使用中间表,中间表中包含各自的主键,在中间表中是外键
- 建立两个实体类:用户实体类和角色实体类
- 让用户和角色的实体类能体现出来多对多的关系
- 各自包含对方一个集合引用
- 建立两个配置文件
- 实现配置:
- 当我们查询用户时,可以同时得到用户下所包含的角色信息
- 当我们查询角色时,可以同时得到角色所赋予的用户信息
- 准备工程
- 创建maven项目
- 将上面项目的main和test复制到项目目录下覆盖原文件
- 复制pom.xml内容
- 删掉关于account的内容,只保留user
- 仿照写出查询role的内容
- 查询角色获取角色下所属用户信息的重点流程
- 在Role.java中包含对方集合引用
//多对多的关系映射:一个角色可以赋予多个用户
private List<User> users;
public List<User> getUsers() {
return users;
}
- 数据库实现功能图
- 需要两个左外连接才可以
![](https://i-blog.csdnimg.cn/blog_migrate/c8111cf5b383ac28c421092e471093ba.png)
- 写SQL语句
- 在第一个左外连接时就要把条件写好
![](https://i-blog.csdnimg.cn/blog_migrate/555cf3b31bab498a26b4c525c5fa954b.png)
- 再写另一个左外连接。
![](https://i-blog.csdnimg.cn/blog_migrate/61edf4266def441712d11a521605f8f1.png)
- 查询不需要中间表值
![](https://i-blog.csdnimg.cn/blog_migrate/690883efca69cb6d12086612d215661b.png)
- 会出现id重复问题
- 所以给查询少的表起别名
![](https://i-blog.csdnimg.cn/blog_migrate/a03fccb652eeded9797466dfb327ed52.png)
- 将SQL语句复制到配置文件中
- 注:放到配置中时要记得在每行前面加上空格
- 不然一行识别时就变成了:rleft
- IRoleDao.xml配置文件
<mapper namespace="com.kami.dao.IRoleDao">
<!-- 定义role表的resultMap-->
<resultMap id="roleMap" type="role">
<id property="roleId" column="id"></id>
<result property="roleName" column="role_name"></result>
<result property="roleDesc" column="role_desc"></result>
<collection property="users" ofType="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>
</resultMap>
<!-- 查询所有-->
<select id="findAll" resultMap="roleMap">
<!-- 注意:放到配置中时要记得在每行前面加上空格,不然一行识别时就变成了:rleft-->
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>
- 查询角色获取角色下所属用户信息的测试类
/**
* 测试查询账户,同时获取所属的用户信息
*/
@Test
public void testFindAll(){
List<Role> roles = roleDao.findAll();
for(Role role : roles){
System.out.println("每个角色的信息");
System.out.println(role);
System.out.println(role.getUsers());
}
}
- 查询用户获取用户所包含的角色信息重点流程
- user.java实体类
//多对多的关系映射:一个用户可以具备多个角色
private List<Role> rolles;
public List<Role> getRolles() {
return rolles;
}
public void setRolles(List<Role> rolles) {
this.rolles = rolles;
}
- IUserDao.xml配置文件
<!-- 定义User的resultMap -->
<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="roles" ofType="role">
<id property="roleId" column="rid"></id>
<result property="roleName" column="role_name"></result>
<result property="roleDesc" column="role_desc"></result>
</collection>
</resultMap>
<!-- 查询所有 -->
<select id="findAll" resultMap="userMap">
<!-- left outer join:左外连接(会返回左表的所有数据)-->
SELECT u.*,r.id AS rid,r.role_name, r.role_desc FROM user u
LEFT OUTER JOIN user_role ur ON u.id = ur.uid
LEFT OUTER JOIN role r ON r.id = ur.rid;
</select>
- UserTest.java测试类
/**
* 每个用户的信息(切具备的角色)
*/
@Test
public void testFindAll(){
List<User> users = userDao.findAll();
for(User user : users){
System.out.println("每个用户的信息(切具备的角色)");
System.out.println(user);
System.out.println(user.getRoles());
}
}
- 执行结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6FRqyA4h-1624207232705)(http://note.youdao.com/yws/public/resource/fdbcde569b9d89bd2981a9293059b4f0/xmlnote/8250E00FD47A48F3BC1719B645989E15/33716)]
四、JNDI概述和原理
4.1 JNDI概述和原理
![](https://i-blog.csdnimg.cn/blog_migrate/625995bdd59ae2cfe969afd9c65bca4b.png)
- JNDI模拟的是windows中的注册表
- tomcat服务器里面的,前面写的Java工程没有这个功能,需要创建maven的war工程【重点】
- windows注册表(win中输入regedit)
- 也就是MAP结构(windows和JNDI原理图)
![](https://i-blog.csdnimg.cn/blog_migrate/14731fd7d3aa8877d9efb2847e1f138d.png)
4.2 JNDI搭建maven的war工程
- 创建项目
![](https://i-blog.csdnimg.cn/blog_migrate/0976eef9660d203f8dc73aab0a7f9c86.png)
- 补全目录
![](https://i-blog.csdnimg.cn/blog_migrate/e46b756528ab58de1b15f8a97b2a73d4.png)
- 相应文件夹赋予对应的目录属性
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X9jZDH1Z-1624207232709)(http://note.youdao.com/yws/public/resource/fdbcde569b9d89bd2981a9293059b4f0/xmlnote/78F7580D7C2349D4971ED79C1E0A6B1E/33756)] - 复制准备好的项目中的文件及pom.xml内容
<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>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</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>
4.3 测试JNDI数据源的使用以及使用细节
- 在webapp目录下创建META-INF,里面创建context.xml文件
- 替换原有的SqlMapConfig.xml
- 注:java:comp/env路径是固定的,不能改动
<?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.kami.domain"></package>
</typeAliases>
<!-- 配置mybatis的环境 -->
<environments default="mysql">
<!-- 配置mysql的环境 -->
<environment id="mysql">
<!-- 配置事务控制的方式 -->
<transactionManager type="JDBC"></transactionManager>
<!-- 配置连接数据库的必备信息 type属性表示是否使用数据源(连接池)-->
<dataSource type="JNDI">
<property name="data_source" value="java:comp/env/jdbc/eesy"/>
</dataSource>
</environment>
</environments>
<!-- 指定mapper配置文件的位置 -->
<mappers>
<mapper resource="com/kami/dao/IUserDao.xml"/>
</mappers>
</configuration>
- 部署到tomcat中
- 创建一个jsp文件做测试
- 注学习JNDI目的:前面自己写的单元测试,都是属于Java的,没有经过tomcat中的数据源,也就是没经过tomcat,就只是一个Java程序在运行
详细的原文
详页连接