一、Mybaits 连接池技术
在 Mybatis 的 SqlMapConfig.xml 配置文件中,通过<dataSource type=”pooled”>
来实现 Mybatis 中连接池的配置
1.1 Mybaits连接池的分类
Mybatis 将它自己的数据源分为三类:
- UNPOOLED 不使用连接池的数据源
- POOLED 使用连接池的数据源
- JNDI 使用 JNDI 实现的数据源
如下图:
MyBatis 内部分别定义了实现了 java.sql.DataSource 接口的 UnpooledDataSource,PooledDataSource 类来表示 UNPOOLED、POOLED 类型的数据源。
在这三种数据源中,我们一般采用的是 POOLED 数据源(很多时候我们所说的数据源就是为了更好的管理数据库连接,也就是我们所说的连接池技术)。
1.2 Mybatis中数据源的配置
我们的数据源配置就是在 SqlMapConfig.xml 文件中,具体配置如下:
<!-- 配置数据源(连接池)信息 -->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
MyBatis 在初始化时,根据<dataSource>的 type 属性来创建相应类型的的数据源 DataSource,即:
type=”POOLED”:MyBatis 会创建 PooledDataSource 实例
type=”UNPOOLED” : MyBatis 会创建 UnpooledDataSource 实例
type=”JNDI”:MyBatis 会从 JNDI 服务上查找 DataSource 实例,然后返回使用
1.3 Mybatis 中连接的获取过程
当我们需要创建 SqlSession 对象并需要执行 SQL 语句时,这时候 MyBatis 才会去调用 dataSource 对象
来创建java.sql.Connection对象。也就是说,java.sql.Connection对象的创建一直延迟到执行
SQL语句
的时候。
@Test
public void testSql() throws Exception {
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
SqlSession sqlSession = factory.openSession();
List<User> list = sqlSession.selectList("findUserById",41);
System.out.println(list.size());
}
只有当第 4 句sqlSession.selectList("findUserById"),才会触发 MyBatis 在底层执行下面这个方
法来创建 java.sql.Connection 对象。
二、Mybaits的事务控制
对数据库记录进行增删改的时候必须进行事务的提交才可以,但是可以实现不用写session.commit()进行提交事务,就是在创建SqlSession对象的时候sqlSession工厂对象调用openSession()方法时,给一个参数true。不写默认时false。false默认不提交事务,当加上参数true时就可以不用写提交事务的操作了。
三、动态sql
1 、< if > 标签
if标签:见名思意,就是说if某个条件成立,就执行条件里面的
示例:
dao层:
//dao层
/**
* 根据用户信息,查询用户列表
* @param user
* @return
*/
List<User> findByUser(User user);
mapper.xml:
<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 的作用~!
测试类:
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);
}
}
2、< where >标签
当sql语句where后面要跟条件的时候么可以动态生成后面的语句
<!-- 根据用户信息查询 -->
<select id="findByUser" resultType="user" parameterType="user">
<include refid="defaultSql"></include>
<where>
<if test="username!=null and username != '' ">
and username like #{username}
</if>
<if test="address != null">
and address like #{address}
</if>
</where>
</select>
3、< foreach >标签
当我们where后面有条件跟的是一个集合的时候该怎么办呢?
传统的sql语句如下:
SELECT * FROM USERS WHERE username LIKE '%张%' AND (id =10 OR id =89 OR id=16)
SELECT * FROM USERS WHERE username LIKE '%张%' AND id IN (10,89,16)
示例:
pojo类对象
/**
*
* <p>Title: QueryVo</p>
* <p>Description: 查询的条件</p>
* <p>Company: http://www.itheima.com/ </p>
*/
public class QueryVo implements Serializable {
private List<Integer> ids;
public List<Integer> getIds() {
return ids;
}
public void setIds(List<Integer> ids) {
this.ids = ids;
}
}
dao层:
**
* 根据 id 集合查询用户
* @param vo
* @return
*/
List<User> findInIds(QueryVo vo);
mapper.xml:
<!-- 查询所有用户在 id 的集合之中 -->
<select id="findInIds" resultType="user" parameterType="queryvo">
<!-- select * from user where id in (1,2,3,4,5); -->
<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>
SQL 语句:
select 字段 from user where id in (?)
<foreach>标签用于遍历集合,它的属性:
collection:代表要遍历的集合元素,注意编写时不要写#{}
open:代表语句的开始部分
close:代表结束部分
item:代表遍历集合的每个元素,生成的变量名
sperator:代表分隔符
测试方法:
@Test
public void testFindInIds() {
QueryVo vo = new QueryVo();
List<Integer> ids = new ArrayList<Integer>();
ids.add(41);
ids.add(42);
ids.add(43);
ids.add(46);
ids.add(57);
vo.setIds(ids);
//6.执行操作
List<User> users = userDao.findInIds(vo);
for(User user : users) {
System.out.println(user);
}
}
三、多表查询
使用多表查询时,要根据对应关系,在映射的pojo类中添加对象。
有三种对应关系(直接贴mapper.xml代码):
一对一:在一个实体类中创建一个实体类对象
<!-- 自定义返回值类型 映射-->
<resultMap type="User" id="UserAndRole">
<id property="id" column="ID"/>
<result property="userCode" column="USERCODE"/>
<result property="userName" column="USERNAME"/>
<result property="userPassword" column="USERPASSWORD"/>
<!-- 一对一关系 -->
<association property="role" javaType="com.zhiyou.pojo.Role">
<id property="id" column="ID"/>
<result property="roleCode" column="ROLECODE"/>
<result property="roleName" column="ROLENAME"/>
</association>
</resultMap>
一对多:在实体类中创建对象集合
<resultMap type="Role" id="RoleAndUser">
<id property="id" column="ID"/>
<result property="roleName" column="roleName"/>
<result property="createBy" column="createBy"/>
<!-- 继续写 有几个属性写几个对应关系 -->
<!-- 用于一对多 -->
<collection property="list" ofType="User">
<id property="id" column="ID"/>
<result property="userCode" column="userCode"/>
<result property="userName" column="userName"/>
<result property="birthday" column="birthday"/>
</collection>
</resultMap>
多对多:就需要一张中间表,中间表实体类分别有两边对象集合。
实现从一张表到另一张表的多对多。
示例:
<!--定义 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>
<!--查询所有-->
<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>