Mybatis连接池 事务 动态Sql语句 多表查询

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 自动提交事务
     	CUD 过程中必须使用 sqlSession.commit()提交事务?
     		主要原因就是在连接池中取出的连接,都会将调用 connection.setAutoCommit(false)方法,
     		就必须使用 sqlSession.commit()方法,相当于使用了 JDBC 中的 connection.commit()方法实现事务提交。
     	设置自动提交
     		// 创建 SqlSession 对象
     		session = factory.openSession(true);
    
  2. Mybatis 的动态 SQL 语句

     * bind
     	<!-- bind:在输入参数的前或后面拼接 一个字符串,
     		 然后组成一个新的字符串
     		 当parameterType="String"时,value="'%'+_parameter+'%'"
     		 -->
         <select id="selectByName" parameterType="user" resultType="User">
             <!--name:新字符串的变量名 ,value:要拼接的字符串,获取输入参数通过_parameter变量 -->
             <bind name="uname" value="'%'+_parameter.getUsername()+'%'"/>
             select * from user where username like #{uname}
         </select>
     * trim
     	<!-- trim:用来格式化sql语句,同时提供四个属性:
             prefix:前缀
             suffix:后缀
             prefixOverrides:忽略前缀
             suffixOverrides:忽略后缀-->
         <update id="updUserbak" parameterType="user">
         <trim prefix="update user set" suffix="where    id=#{id}" suffixOverrides=",">
             <if test="username!=null and username!=''">
                 username=#{username},
             </if>
             <if test="sex!=null and sex!=''">
                 sex=#{sex}
             </if>
         </trim>
    		</update>
     * set if
     	<!-- set,if -->
         <update id="updateUser" parameterType="user">
         	update user
         	<!--set:1.拼接set关键字 2.自动去掉最后一个限定条件后的逗号  -->
         	<set>
         		<if test="username != null and username != ''">
         			username=#{username},
         		</if>
         		<if test="sex!=null and sex!=''">
                 	 sex=#{sex}
              	</if>
         	</set>
         	 where id = #{id},
         </update>
    
         测试:
         	@Test
     		public void updateUser() {
     			User u=new User();
     			u.setUsername("张明浩");
     			//u.setSex("女");
     			u.setId(21);
     			userDao.updateUser(u);
     		}
     * choose
     	    <!-- choose when 标签的使用 
     	    	 uname,usex map集合中的 key值
     	    -->
     	    <select id="findUserByNameOrSex" parameterType="map" resultType="user">
     	    	select * from user where
     	    	<choose>
     	    		<when test="uname != null and uname != ''">
     	    			username like '%${uname}%'
     	    		</when>
     	    		<when test="usex != null and usex != ''">
     	    			sex like '%${usex}%'
     	    		</when>
     	    		<otherwise>
     	    			1=1
     	    		</otherwise>
     	    	</choose>
     	    </select>
    
     	    测试:
     	    	@Test
     			public void findUserByNameOrSex() {
     				Map<String, String> map = new HashMap<>();
     				//map.put("uname", "阿");
     				map.put("usex", "男");
     				List<User> list = userDao.findUserByNameOrSex(map);
     				for (User user : list) {
     					System.out.println(user);
     				}
     			}
     * if
     	<select id="findByUser" resultType="user" parameterType="user">
     		select * from user where 1=1
     		<if test="username!=null and username != '' ">
     			and username like #{username}
     		</if> 
     		<if test="address != null">
     			and address like #{address}
     		</if>
     	</select>
     	注意:<if>标签的test属性中写的是对象的属性名,如果是包装类的对象要使用 OGNL 表达式的写法。
     	另外要注意 where 1=1 的作用~!
    
     	测试:
     		@Test // 按照条件查询
     		public void testFindByUser() {
     			User u = new User();
     			u.setUsername("%王%");
     			u.setAddress("%顺义%");
     			// 6.执行操作
     			List<User> users = userDao.findByUser(u);
     			for (User user : users) {
     				System.out.println(user);
     			}
     		}
     * where
     	<!-- 
     		1. 再有限定条件的情况下,拼接where 关键字
     		2. 会自动删除第一个 and 关键字
     	-->
     	<select id="findByUser" resultType="user" parameterType="com.demos.domain.User" >
     		select * from user
     		<where>
     			<if test="username!=null and username != '' ">
     				and username like #{username}
     			</if> <if test="address != null">
     				and address like #{address}
     			</if>
     		</where>
     	</select>
     * foreach
     	1. 自定义 bean 类型
     		* QueryVo.java
     			package com.demos.domain;
     			import java.io.Serializable;
     			import java.util.List;
    
     			public class QueryVo implements Serializable {
     				private User user;
     				private List<Integer> ids;
    
     				public User getUser() {
     					return user;
     				}
    
     				public void setUser(User user) {
     					this.user = user;
     				}
    
     				public List<Integer> getIds() {
     					return ids;
     				}
    
     				public void setIds(List<Integer> ids) {
     					this.ids = ids;
     				}
    
     			}
    
     		<!-- 根据 id 集合查询用户 -->
     		<sql id="defaultSql">
     			select * from user
     		</sql>
     		<select id="findInIds" resultType="user" parameterType="com.demos.domain.QueryVo">
     			<!-- select * from user
     				 collection:必须为自定义类型的集合属性名,
     			 -->
     			<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>
    
     		测试:
     			@Test // 根据集合条件查询
     			public void testFindInIds() {
     				QueryVo vo = new QueryVo();
     				List<Integer> ids = new ArrayList<Integer>();
     				ids.add(41);
     				ids.add(42);
     				ids.add(43);
     				vo.setIds(ids);
     				// 6.执行操作
     				List<User> users = userDao.findInIds(vo);
     				for (User user : users) {
     					System.out.println(user);
     				}
     			}
     	2. 数组
     		<!-- 输入参数是数组,parameterType:可以省略,不省略应为全路径java.lang.reflect.Array 
     			  item:集合里每一项的名称,
     		-->
     		<select id="findByIds1" resultType="user">
     			select * from user where id in (
     			<foreach collection="array" item="id" separator=",">
     				#{id}
     			</foreach>
     			)
     		</select>
    
     		测试:
     			/**
     			 * 通过数组批量查询
     			 */
     			@Test
     			public void findByIds1() {
     				List<User> list = userDao.findByIds1(new int[] {1,4,6});
     				for (User user : list) {
     					System.out.println(user);
     				}
     			}
     	3. List
     		<!-- 输入参数是集合List,parameterType=java.util.List:可以省略 -->
     		<select id="getByIds2" parameterType="list" resultType="user">
     	         select * from user where id in 
     	           <!--输入参数是list集合时,
     	           	   collection:必须为list ,
     	               item:集合里每一项的名称,
     				-->
     	           <foreach collection="list" item="uid" separator="," open="(" close=")">
     	              #{uid}
     	           </foreach>
     	    </select>
    
     	    测试:
     	    	/**
     			 * 通过list 集合批量查询
     			 */
     			@Test
     			public void findByIds2() {
     				List<Integer> ids=new ArrayList<>();
     				ids.add(1);
     				ids.add(3);
     				ids.add(5);
     			    List<User> ulist = userDao.getByIds2(ids);
     			    System.out.println(ulist);
     			}
    
     	SQL 语句:
     		select 字段 from user where id in (?)
     	<foreach>标签用于遍历集合,它的属性:
     		collection:代表要遍历的集合元素,注意编写时不要写#{}
     		open:代表语句的开始部分
     		close:代表结束部分
     		item:代表遍历集合的每个元素,生成的变量名
     		sperator:代表分隔符
    
     * 简化编写的 SQL 片段
     	1 定义代码片段
     		<!-- 抽取重复的语句代码片段 --> 
     		<sql id="defaultSql">
     			select * from user
     		</sql>
     	2 引用代码片段
     		<!-- 配置查询所有操作 --> 
     		<select id="findAll" resultType="user"> 
     			<include refid="defaultSql"></include>
     		</select>
    
  3. 一对一查询(多对一)

     需求
     	查询所有账户信息,关联查询下单用户信息。
     注意:
     	因为一个账户信息只能供某个用户使用,所以从查询账户信息出发关联查询用户信息为一对一查询。如
     	果从用户信息出发查询用户下的账户信息则为一对多查询,因为一个用户可以有多个账户。
    
     方式一:
     	List<AccountUser> findAll();
     	定义专门的po类作为输出类型,其中定义了sql查询结果集所有的字段。此方法简单,企业中使用普遍。
    
     方式二:
     	一对一:  一个用户只有一个身份证
     		在 User 类中 加入一个 Card 实体类 作为 User类的一个属性
     			public class User {
     				private Card card;
     			}
    
     		<!--手动映射方式1-->
     		<resultMap type="user" id="commomrs">
     		   <id property="id" column="id"/>
     		   <result column="username" property="username"/>
     	       <result column="sex" property="sex"/>
     	       <result column="birthday" property="birthday"/>
     	       <result column="address" property="address"/>
     		</resultMap>
     		<resultMap type="user" id="rsoTo" extends="commomrs">
     			<association property="card" javaType="card">
     				<result property="num" column="num"/>
     			</association>
     		</resultMap>
     		<select id="oneToOne1" resultMap="rsoTo">
     			select u.*,c.num  from user u,card c where u.id=c.per_fk
     		</select>
     		
     		<!--手动映射方式2-->
     		<resultMap type="card" id="cards">
     			<result property="num" column="num"/>
     		</resultMap>
     		<resultMap type="user" id="commomrs2">
     		   <id property="id" column="id"/>
     		   <result column="username" property="username"/>
     	       <result column="sex" property="sex"/>
     	       <result column="birthday" property="birthday"/>
     	       <result column="address" property="address"/>
     		</resultMap>
     		<resultMap type="user" id="rsoTo2" extends="commomrs2">
     			<association property="card" javaType="card" resultMap="cards">
     			</association>
     		</resultMap>
     		
     		<select id="oneToOne2" resultMap="rsoTo2">
     	       select u.*,c.num  from  user u,card c where u.id=c.per_fk
     	    </select>
     		
     		<!-- 手动映射方式3:分步查询 -->
     		<resultMap type="user" id="rsoTo3" extends="commomrs2">
     			<association property="card" javaType="card" column="id" 
     			select="com.dao.UserDao.getCardByUid">
     				
     			</association>
     		</resultMap>
     		<select id="oneToOne3" resultMap="rsoTo3">
     	       select * from user
     	    </select>
     	    
     	     <select id="getCardByUid" parameterType="int" resultType="card">
     	       select * from card where per_fk=#{uid}
     	    </select>
    
     	一对一:  一个账户信息只能供某个用户使用
     		使用 resultMap,定义专门的 resultMap 用于映射一对一查询结果。
     		通过面向对象的(has a)关系可以得知,我们可以在 Account 类中加入一个 User 
     		类的对象来代表这个账户是哪个用户的。
    
     		在 Account 类中加入 User 类的对象作为 Account 类的一个属性。
     			private User user;
    
     		重新定义 AccountDao.xml 文件	
     			<!-- 建立对应关系 --> 
     			<resultMap type="account" id="accountMap"> 
     				<id column="aid" property="id"/>
     				<result column="uid" property="uid"/>
     				<result column="money" property="money"/>
     				<!-- 它是用于指定从表方的引用实体属性的 --> 
     				<association property="user" javaType="com.demos.domain.User"> 
     					<id column="id" property="id"/>
     					<result column="username" property="username"/>
     					<result column="sex" property="sex"/>
     					<result column="birthday" property="birthday"/>
     					<result column="address" property="address"/>
     				</association>
     			</resultMap>
    
     	一对多查询: 用户信息和他的账户信息为一对多关系,显示所有用户信息,左外连接
     		User 类加入 List<Account>
     			// 一对多关系映射:主表实体类应该包含从表实体类的集合引用
     			private List<Account> accounts;
    
     		IUserDao.xml
     			<resultMap type="user" id="userMap"> 
     			<id column="id" property="id"></id> 
     			<result column="username" property="username"/>
     			<result column="address" property="address"/>
     			<result column="sex" property="sex"/>
     			<result column="birthday" property="birthday"/>
     			<!-- collection 是用于建立一对多中集合属性的对应关系
     			ofType 用于指定集合元素的数据类型
     			--> 
     			<collection property="accounts" ofType="account"> 
     				<id column="aid" property="id"/>
     				<result column="uid" property="uid"/>
     				<result column="money" property="money"/>
     			</collection>
     		</resultMap>
    
     		collection
     			部分定义了用户关联的账户信息。表示关联查询结果集
     		property="accList":
     			关联查询的结果集存储在 User 对象的上哪个属性。
     		ofType="account":
     			指定关联查询的结果集中的对象类型即List中的对象类型。可使用别名,也可以用全限定名。
     		column:
     			主信息表(当前查询的user表)和Orders表关联的字段
     	
     	一对多: 一个用户对应多个订单
     		<!-- 关系映射1-n -->
     	    <!-- 方式1 -->
     	    <resultMap type="user" id="rsoTm" extends="commomrs">
     	    	<collection property="oList" ofType="orders">
     	    	   <result column="number" property="number"/>
     	           <result column="note" property="note"/>
     	    	</collection>
     	    </resultMap>
     	    <select id="ontToMany1" resultMap="rsoTm">
     	    	select u.*,o.number,o.note from user u,orders o where u.id=o.userId
     	    </select>
     	    
     	    <!-- 方式2 -->
     	    <resultMap type="orders" id="rsorders">
     	    	<result column="number" property="number"/>
     	        <result column="note" property="note"/>
     	    </resultMap>
     	    <resultMap type="user" id="rsoTm2" extends="commomrs">
     	    	<collection property="oList" ofType="orders" resultMap="rsorders">
     	    	</collection>
     	    </resultMap>
     	    <select id="ontToMany2" resultMap="rsoTm2">
     	    	select u.*,o.number,o.note from user u,orders o where u.id=o.userId
     	    </select>
     		
     		<!-- 方式3 -->
     		<resultMap type="user" id="rsoTm3" extends="commomrs">
     			<!--collection:完成集合的映射
     		        property:实体里集合的属性名
     		        ofType:集合的泛型
     		        column:主信息表(当前查询的user表)和Orders表关联的字段
     		        select:调用另外一条sql语句(命名空间+sql语句id)-->
     		    <collection property="oList" ofType="orders" column="id" 
     		    select="com.dao.UserDao.getOrdersByUId">
     		    </collection>
     		</resultMap>
     		<select id="ontToMany3" resultMap="rsoTm3">
     	       select * from user
     	    </select>
     	    
     	    <select id="getOrdersByUId" parameterType="int" resultType="orders">
     	       select * from orders where userId=#{uid}
     	    </select>
    
  4. Role 到 User 多对多 用户与商品

     1. 编写角色实体类
     	//多对多的关系映射:一个角色可以赋予多个用户
     	private List<User> users;
     2. IRoleDao.xml
     	<!--定义 role 表的 ResultMap--> 
     	<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="id" property="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>
     		</collection>
     	</resultMap>
     3. 编写User 1 -->n Orders --> n Orderdetail --> 1 Items 实体类
     	public class User {
     		private List<Orders> oList;
     	}
    
     	public class Orders {
     		private List<Orderdetail> dList;
     	}
    
     	public class Orderdetail {
     		private Items items;
     	}
     4. IUserDao.xml
     	<!-- 多对多手动映射 -->
         <resultMap type="user" id="rsmTm">
     	     <result column="username" property="username"/>
     	     <result column="address" property="address"/>
     	     <collection property="oList" ofType="orders">
     	     	<result column="number" property="number"/>
     	     	<collection property="dList" ofType="orderdetail">
     	     		<result column="itemsNum" property="itemsNum"/>
     	     		<association property="items" javaType="items">
                        <result column="name" property="name"/>
                        <result column="price" property="price"/>
                    </association>
     	     	</collection>
     	     </collection>
         </resultMap>
         <select id="ManyToMany" resultMap="rsmTm">
            select u.username,u.address,o.number,i.name,i.price,d.itemsNum 
            from user u,orders o,orderdetail d,items i 
            where u.id=o.userId  and o.id=d.ordersId and d.itemsId=i.id
         </select>
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值