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连接池。
-
事务
* Mybatis 自动提交事务 CUD 过程中必须使用 sqlSession.commit()提交事务? 主要原因就是在连接池中取出的连接,都会将调用 connection.setAutoCommit(false)方法, 就必须使用 sqlSession.commit()方法,相当于使用了 JDBC 中的 connection.commit()方法实现事务提交。 设置自动提交 // 创建 SqlSession 对象 session = factory.openSession(true);
-
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>
-
一对一查询(多对一)
需求 查询所有账户信息,关联查询下单用户信息。 注意: 因为一个账户信息只能供某个用户使用,所以从查询账户信息出发关联查询用户信息为一对一查询。如 果从用户信息出发查询用户下的账户信息则为一对多查询,因为一个用户可以有多个账户。 方式一: 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>
-
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>