**Mybatis框架 笔记三[共四篇,史上最全重点]*

版权声明:文章为作者自己原创文章,转载请注明出处。 https://blog.csdn.net/qq_37128049/article/details/83536542

今日内容

1.重点一(原理部分了解)
	* mybatis中的连接池以及事务控制
	* mybaits中连接池的使用及分析
	* mybaits事务控制的分析
2.重点二(掌握应用)
	* mybatis基于XML配置的动态SQL语句使用
	* mappers配置文件中的几个标签
		* if
		* where
		* foreach
		* sql
3.重点三 (掌握应用)
	* mybatis中的多表结构
		* 一对一	
		* 多对一
		* 一对多

连接池

1.线程池介绍
1.作用:
* 它是预先创建线程的一种技术,减少频繁的创建和销毁对象
2.四种策略:
1. 如果线程数小于corePoolSize,则每来一个任务,就会创建执行这个任务。
2. 如果当前线程池中的线程数目>=corePoolSize,则每来一个任务,会尝试将其添加到任务缓存队列中。若添加失败(一般来说是任务缓存队列已满,针对的是有界队列),则会尝试创建新的线程去执行这个任务。
3. 如果当前线程池中的线程数目达到maximumPoolSize,则会采取任务拒绝策略进行处理
4. 如果线程池的线程数量大于corePoolSize时,如果某线程空闲时间超过keepAliveTIme,线程将被终止,直至线程池中的线程数目不大于corePoolSize;如果允许为核心池中的线程设置存活时间,那么核心池中的线程池空闲时间超过keepAliveTime,线程也会被终止。

2.实现的子类介绍

1.ThreadPoolExecutor.AbortPolicy
	* 当添加任务出错时的策略捕获器,如果出现错误,则直接抛出异常
2.ThreadPoolExecutor.CallerRunsPolicy

	* 当添加任务出错时的策略捕获器,如果出现错误,直接执行加入的任务
3.ThreadPoolExecutor.DiscardOldestPolicy
	* 当添加任务出错时的策略捕获器,如果出现错误,移除第一个任务,执行加入的任务
4.ThreadPoolExecutor.DiscardPolicy
	* 当添加任务出错时的策略捕获器,如果出现错误,不做处理

2.连接池介绍[实际开发中都会使用连接池]:
1.优点:因为它可以减少获取连接时间
2.mybaits中的连接池
* mybatis连接池提供了3种方式配置
1. 配置的位置
1. 主配置文件SqlMapConfig.xml中的dataSource标签,type属性就是表示采用何种连接池方式。
2. type属性的取值:
1. POOLED:采用传统的javax.sql.DataSource规范中的连接池,mybatis中有针对规范的实现。
2. UNPOOLED:采用传统的获取连接的方式,虽然也实现了Javax.sql.DataSource接口看,但是并没有使用连接池思想。【这个表示没有连接池】
3. JNDI:采用服务器提供的JNDI技术实现,来获取DataSource对象,不同的服务器所能拿到的连接池对象是不一样的,它是服务器中的连接池,tomcat使用的就是dbcp。
1. 注意:如果不是web或者maven的war工程,是不能使用的
3. 工作中使用什么连接池技术?
1. c3po或者德鲁伊,最常用的是德鲁伊。
4.使用方式:
1. POOLED:使用了连接池技术,在执行过程中可以看到,该连接方式创建了连接池对象,关闭连接对象,归还连接对象。
1. 源码分析:
1. synchronized锁 -->所以它是线程安全的。
2. new ArrayList -->所以它的容器是一个集合对象
3. 策略:
1. 先看是否有空闲状态下的PooledConnecttion对象;
1. 如果有,就直接返回一个可用的PooledConnection对象;[state.idleConnections.remove(0)–>将空闲池中第0个连接池移出使用。]
2. 否则进行第二步;
2. 查看活动状态的PooledConnection池activeConnection是否已满;
1. 如果没有满,则创建一个新的PooledConnection对象,然后放到activeConnection池中,然后返回此PooledConnection对象;
2. 否则进行第三步。
3. 看最先进入activeCOnnections池中的PooledConnection对象是否已经过期:
1. 如果过期,从activeConnection池中移出此对象,然后创建一个新的PooledConnection对象,添加到activeConnections中,然后将此对象返回
2. 否则进行第4步
4. 线程等待,循环第2步。
2. UNPOOLED:源码中->注册驱动,获取连接 【所以它未使用连接池技术】
5.配置信息:
1. 空闲池数量:5个 [数组结构]
2. 活动池数量:10个 [集合]
3. 解析:
* 当我们第一次进来获取连接的时候,先判断空闲连接池中是否还有连接?
1. 如果有连接:取出第一个连接出来idleConnections.remove(0),返回!
2. 如果没有连接:判断活动连接池中数量是否达到最大10个?
* 判断:活动连接池数量是否达到最大值10?
1. 如果没有达到10个,则创建一个新的连接放入activeConnections中,返回!
2. 如果活动连接池数量等于最大值10个,则获取出第0个连接,也就是最先使用的那个连接
* 判断:获取的这个第0个连接对象是否超时[过期],参照:如果大于poolMaximumCheckoutTime=20000;
1. 如果过期,则把这个老的连接对象进行包装,重新使用
2. 如果没有过期,线程等待,循环第二个判断
4. 连接池中的连接对象最多能创建多少个? -->10个 一开始有5个,最多还能再创建5个。

事务

1.介绍_什么是事务?
* 数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。 事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。通过将一组相关操作组合为一个要么全部成功要么全部失败的单元,可以简化错误恢复并使应用程序更加可靠。一个逻辑工作单元要成为事务,必须满足所谓的ACID(原子性、一致性、隔离性和持久性)属性。事务是数据库运行中的逻辑工作单位,由DBMS中的事务管理子系统负责事务的处理。
* 事务提交:
* 我们的mybatis框架因为是对JDBC的封装,所以Mybatis框架的事务控制方式,本身也是用JDBC的setAutoCommit()方法来设置事务提交方式的。
* 设置自动提交:
* SqlSession sqlSession =sqlSessionFactory.openSession(true); //将事务的手动提交设置为自动提交;
* 在工作中建议使用手动提交,因为在复杂的操作中手动提交能将几行所联合的数据改变做出安全机制。而自动提交事务是有安全风险的。
* 自动提交事务,是每行自动提交事务。
* 手动提交事务,是在设置点到提交事务点之间进行回滚或者提交操作,是有一定的范围的。

动态SQL

1.概念:根据传入的参数条件查询,条件可能是用户名,可能是id,可能是地址等等。
2.条件查询:
1. if标签

		* <select id ="findUserByCondition" resultMap="userMap" parameterType="user">
		* select * from user where 1=1 
		* <if test="username!=null">
		* and username= #{username};
		* </if>
		* </select>
2. where标签  [where标签的使用可以避免在select中加上1=1的语句,更简洁清晰]
	* <select id ="findUserByCondition" resultMap="userMap" parameterType="user">
	* select * from user
	* <where>
	* <if test="username!=null">
	* and username= #{username};
	* </if>
	* </where>
	* </select>
3. foreach标签:
	1. 语句代码演示:[已经将id传入一个list集合中]
		*  <select id ="findUserInids" resultMap="userMap" parameterType="queryvo">
		* select * from user
		* <where>
		* <if test ="ids" !=null and ids.size()>0">
		*  <foreach collection="ids" open="and id in (" close=")" item="uid" separator="," >
		* #{uid}
		* </foreach>
		* </if>
		* </where>
		* </select>
	2.SQL语句
		* select 字段 from user where id in(in)
		* <foreach> 标签用于遍历集合,它的属性:
		* open:代表语句的开始部分
		* close:代表结束部分
		* item:代表遍历集合的每个元素
		* separator:代表分隔符
	3. 如果它是第一个查询因子,加不加and都可以,但是最好在语句前面都加一个and,整体释义:在collection的集合中,遍历每一个元素id,将id的值传入开头为open值,结束值为close值的中间。
4. 注意:
	1. where标签是mybatis中特有提供的。在where中if语句,在if语句中最好在前面加一个and,即便是只有一句if语句,mybatis也会自动省略掉,所以只要if语句,就最好都写上。其他亦然。

多表查询 (!!!重点)

1.表之间的关系有几种
	1. 一对多
	2. 多对一
	3. 一对一
	4. 多对多
2.举例:
	1. 用户和订单就是一对多
	2. 订单和用户就是多对一
		1.一个用户可以下多个订单
		2.多个订单属于同一个用户
	3.人和身份证号就是一对一
		1.一个人只能有一个身份证号
		2.一个身份证号只能属于一个人
	4.老师和学生之间就是多对多
		1.一个学生可以被多个老师教过
		2.一个老师可以交多个学生
	5.特例:
		1.如果拿出每一个订单,他都只能属于一个用户,所以Mybatis就把多对一看成一个用户。
3.mybatis中的多表查询
	1.一对多的关系
		1. 示例:用户和账户:
			* 一个用户可以有多个账户
			* 一个账户只能属于一个用户(多个账户也可以属于同一个用户)
		2. 步骤:[select user]
			1. 建立两张表:用户表,账户表: 让用户表和账户表之间具备一对多的关系:需要使用外键在用户表中添加。
			2. 建立两个实体类:
				1. 用户实体类和账户实体类
				2. 让用户和账户的实体类能体现出来一对多的关系
			3. 建立两个配置文件
				1. 用户的配置文件
				2. 账户的配置文件
			4. 实现配置:
				1. 当我们查询用户时,可以同时得到用户下所包含的账户信息
				2. 当我们查询账户时,可以同时得到账户的所属用户信息。
		3. 查询方法:
			1. 封装对象: 	
				* 如果需要查询Account实体类中的所有信息和User中username和address信息。可以创建一个新的对象继承Acount,在新的对象中设置User中的username,address参数,并实现toString方法,toString方法继承Acount并加入username,address。[通过写acount的子类的方法进行查询]
			2. 左外连接:		
				* 将a,b表连接,并查询指定内容。	
			3. 常用方式:
				1. 以前的查询方法:[select u*,a.ID as aid,a.uid,a.Money from user u, account a where a.uid = u.id; ]
				2. 推崇的方法:
					1. 从表实体对主表的引用:
						1. 配置:在IAccountDao.xml下配置:
							* <resultMap id="accountUserMap" type="account">
							* <id property="id" column="aid"></id>
							* <result property="money" colum="money"></result>
							* // 一对一的关系映射:配置封装user的内容
							* <associaiton property ="user" column="money"></result>
							* <id property="id" column="id"></id>
							* <result column="username" property="username"></result>
							* <result column="address" property="adress"></result>
							* <result column="sex" property="sex"></result>
							* <result column="birthday" property="birthday"></result>
							* </association>
							* </resultMap>
							* <select id="findAll" resultMap="accountMap">
							* select u*,a.ID as aid,a.uid,a.Money from user u, account a where a.uid = u.id;
							* </select>
						2. 使用:
							1. sql语句执行完成后的结果集封装成我们需要的对象;
							2. AcountUser acountUser=userDao.findAll();
							3. acountUser.getUser.getusername		//查询user的名字
							4. acountUser.get(...)
						3. 实体类的配置:
							1. 在实体类中加入User类
							2. 代码演示:
								1. private User user;
								2. public User getUser(User user){return user}
						4. IUser.xml的配置:
							1. 在<mapper>标签内进行配置
								* <resultMap id="userAcountMao" type="user"> 
								* <id property="id" column="id"></id>
								* <result property="" column=""></result>
								* <result property="" column=""></result>
								* <result property="" column=""></result>
								* <result property="" column=""></result>
								* //配置user对象中accounts集合的映射
								* <collection property="accounts" ofType="account">
								* <id column="aid" property="id"></id>
								* <result property="uid" colum="uid"></result>
								* <result property="money" colum="money"></result>
								* </collection>
								* </resultMap>
	2.多对多的关系
		1. 示例:用户和角色之间的关系
			1. 解析:
				1. 用户和角色之间的关系  [用户,角色,各都有一张表]
				2. 用户可以有多个角色,角色又可以被多个用户所持有
			2. 步骤:
				1. 建立两张表:用户表,角色表
					* 让用户表 和角色表具有多对多的关系。需要使用中间表;中间表包含各自的主键,在中间表中是外键。
				2. 建立两个实体类:用户实体类和角色实体类
					* 让用户和角色实体类能体现出来多对多的关系
					* 各自包含对方一个集合引用
				3. 建立两个配置文件
					* 用户的配置文件
					* 角色的配置文件
				4. 实现配置:
					* 当我们查询用户时,可以同时得到用户所包含的角色信息
					* 当我们查询角色时,可以同时得到角色的所赋予的用户信息
			3. 实现细节:
				1. 创建两个实体类:Role,User;
				2. 创建两个实体类的接口:IRoleDao,IUSerDao
				3. 创建测试类
					* List<Role> roles=roleDao.findAll()
					* for(role : roles){
					* 
				4. 创建映射文件,并写入映射配置文件:
					1. IRoleDao.xml(查询角色获取用户的信息):
						* <mapper namespace="com.iheima.dao.IRoleDao">
						* <resultMap id="roleMap" type="role">
						* <id property="roleId" column="rid"></id>
						* <result property="roleName" column="role_name"></result>
						* <result property="roleDesc" column="role_desc"></result>
						* <collection property="users" ofType="user">
						* <id column="username" property="username" ></result>
						* <id column="address" property="address" ></result>
						* <id column="sex" property="sex" ></result>
						* <id column="birthday" property="birthday" ></result>
						* </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>
					2. IUser.Dao.xml(查询用户并获取对应角色的信息):
						* <mapper namespace="com.itheima.dao.IUserDao">
						* //定义User的resultMap
						* <resultMap id="userMap" type="user">
						* <id property="username" column="username"></result>
						* <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">
						* 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>
						* //根据id查询所有用户
						* <select id="findById"  parameterType="int" resultType="User">
						* select * from user where id =#{uid}
						* </select>
						* </mapper>
			4. 注意:
				1. 规范(可遵守可不遵守): 
					1. 数据库表的命名规范:User_Name 下划线进行连接
					2. java命名规范:userName  小驼峰
				2. 在实现查询的时候,需要先分清楚主表是谁,从表为谁。
			5. 查询语句:
				1. 查询每个角色所对应用户的所有信息:
					* 先通过中间表连接左表为角色,再通过角色为左表连接用户;
					* 语句:select u.*,rid 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;
				2. 查询每个用户所对应的角色的所有信息
					* 先通过中间表连接左表为用户,再通过用户为左表连接角色;
					* 语句: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

JNDI

1.JNDI的数据结构
	1.winndows注册表结构:
2.JNDI连接
	1.配置SqlMapConfig.xml
		* <?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"></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_mybatis"/>
		            </dataSource>
		        </environment>
		    </environments>
		
		    <!-- 指定mapper配置文件的位置 -->
		    <mappers>
		        <mapper resource="com/itheima/dao/IUserDao.xml"/>
		    </mappers>
		</configuration>
	2.在webapp目录下创建META-INF文件夹并创建context.xml
		* 写入内容:
		<?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="1234"									密码
		driverClassName="com.mysql.jdbc.Driver"			驱动类
		url="jdbc:mysql://localhost:3306/eesy_mybatis"	连接url字符串
		/>
		 -->
		<Resource 
		name="jdbc/eesy_mybatis"
		type="javax.sql.DataSource"
		auth="Container"
		maxActive="20"
		maxWait="10000"
		maxIdle="5"
		username="root"
		password="1234"
		driverClassName="com.mysql.jdbc.Driver"
		url="jdbc:mysql://localhost:3306/eesy_mybatis"
		/>
		</Context>

今日作业:

1.动态SQL语句练习一下,掌握where,foreach,if的使用
2.多表查询每种方法做一次,一对多,多对多。

猜你喜欢

转载自blog.csdn.net/qq_37128049/article/details/83536542
今日推荐