MyBatis的使用

MyBatis的使用

MyBatis常用的三个查询方法

selectList

用于查询多条数据,返回值是一个List集合。若没有查到任何数据返回一个空集合,不是null。

selectOne

用于查询单条数据,返回值是一个对象。如果没有查到任何数据,返回null。

selectMap

用于查询多条数据,返回值是一个Map集合。若没有查到任何数据返回一个空集合,不是null。

MyBatis的使用步骤

  1. 加载MyBatis.xml

    InputStream is = Resources.getResourceAsStream("mybatis.xml");
    
  2. 获取SqlSessionFactory工厂对象

    SqlSessionFactoryBuilder().build(is)会对xml进行解析

    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
    
  3. 通过SqlSessionFactory工厂对象打开SqlSession

    SqlSession session = factory.openSession();
    
  4. 执行查询操作

    List<User> list = session.selectList(mapper);
    
  5. 关闭SqlSession

    session.close();
    
	static void selectAll() throws IOException {
		//加载资源
		InputStream is = Resources.getResourceAsStream("mybatis-cfg.xml");
		//工厂对象
		SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
		//Session
		SqlSession session = factory.openSession();
		//执行select: 命名空间+id
		List<User> list = session.selectList("com.trf.mapper.UserMapper.selAll");
		for (User user : list) {
			System.out.println(user);
		}
        //关闭SqlSession
		session.close();
	}

SQL参数传递

#{}使用参数

index 从0开始

param+数字:param1,param2

<select id="selById" resultType="User" parameterType="int">
	SELECT * FROM t_USER WHERE id = #{0}
</select>

DML操作

事务

  1. 事务是数据库操作的最小单元,有ACID的特性。应该保证一个事务中的SQL语句要么都成功,要么都不成功

  2. MyBatis中配置了事务管理器,type属性设置为JDBC。表示使用原生JDBC相同的事务管理机制。

  3. 在MyBatis执行的开始时,将自动提交功能关闭。所以执行DML操作时,需要手动提交事务

新增

手动提交事务

public class TestInsert {
	public static void main(String[] args) {
		 SqlSession session = MyBatisUtil.getSession(); 
		 User u = new User();
		 u.setUsername("谷七壮");
		 u.setPassword("123456");
		 int num = session.insert("com.trf.mapper.UserMapper.insUser", u);
		 if (num > 0) {
			 session.commit();
			 System.out.println("新增成功");
		 } else {
			 session.rollback();
			 System.out.println("新增失败");
		 }
		 
		 session.close();
	}
}

xml

<insert id="insUser" parameterType="user">
	INSERT INTO T_USER VALUES(default, #{username}, #{password})
</insert>

可以使用factory.openSession(true)设置自动提交事务,不建议使用自动提交事务。

删和改

	public static void testDel() {

		 SqlSession session = MyBatisUtil.getSession(); 

		 int num = session.delete("com.trf.mapper.UserMapper.delUser", 9);
		 if (num > 0) {
			 session.commit();
			 System.out.println("删除成功");
		 } else {
			 session.rollback();
			 System.out.println("删除失败");
		 }
		 
		 session.close();
	}

	public static void testUpdate() {

		 SqlSession session = MyBatisUtil.getSession(); 
		 User u = new User();
		 u.setId(9);
		 u.setUsername("车七强");
		 u.setPassword("123456");
		 int num = session.update("com.trf.mapper.UserMapper.updUser", u);
		 if (num > 0) {
			 session.commit();
			 System.out.println("更新成功");
		 } else {
			 session.rollback();
			 System.out.println("更新失败");
		 }
		 
		 session.close();
	}

接口绑定方案

MyBatis中,提供了一套接口方案。程序员可以提供一个接口,然后提供对应接口的一个mapper.xml文件。

MyBatis会自动将对应接口的一个mapper.xml文件。MyBatis会自动将接口和xml文件进行绑定。实际上就是MyBatis会根据接口和对应的xml文件创建接口的实现类。也就是说可以得到接口类型的对象,方便方法的调用。

要点

  1. xml 文件名要和接口名一致
  2. 配置文件中的命名空间要和接口名一致
  3. id和和接口中的方法名一致

当需要扫描多个接口时,可以使用package标签,扫描包下的所有接口

接口

import java.util.List;

import com.trf.pojo.User;

public interface UserMapper {
	/**
	 * 查询所有用户信息
	 * @return
	 */
	List<User> selAll();
}

配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.trf.mapper.UserMapper">
	<select id="selAll" resultType="User">
		SELECT * FROM t_user
	</select>
</mapper>

测试

public class TestBind {
	public static void main(String[] args) {
		SqlSession session = MyBatisUtil.getSession();
		UserMapper mapper = session.getMapper(UserMapper.class);
		List<User> list = mapper.selAll();
		for (User user : list) {
			System.out.println(user);
		}
		session.close();
	}
}

动态SQL

根据条件的不同, SQL 语句也会随之动态的改变. MyBatis 中,

提供了一组标签用于实现动态 SQL.

if标签和where标签

if标签,用于进行条件判断, test 属性用于指定判断条件. 为了拼接
条件, 在 SQL 语句后强行添加 1=1 的恒成立条件。

where标签用于管理 where 子句. 有如下功能:

  1. 如果没有条件, 不会生成 where 关键字
  2. 如果有条件, 会自动添加 where 关键字
  3. 去除第一个条件中的and
	<select id="selByCondition" resultType="User">
		SELECT * FROM t_user
		<where>
			<!-- if用于条件判断
				test属性用于设定判断条件
			 --> 
			<if test="username != null and username != ''">
			  AND username = #{username}
			 </if>
			 <if test="password != null and password != ''">
			  AND password = #{password}
			 </if>
		 </where>
	</select>

chose when otherwise标签组合

作用类似于switch case

	<select id="selByCondition2" resultType="User">
		SELECT * FROM t_user
		<where>
			<choose>
				<when test="username != null and username != ''">
					AND username = #{username}
				</when>
				<when test="password != null and password != ''">
					AND password = #{password}
				</when>
				<otherwise>
					AND 1 = 1
				</otherwise>
			</choose>
		 </where>
	</select>

set标签

用于维护 update 语句中的 set 子句. 功能如下:

  1. 满足条件时, 会自动添加 set 关键字
  2. 会去除 set 子句中多余的逗号
  3. 不满足条件时, 不会生成 set 关键字
	<update id="updUser" parameterType="user">
		UPDATE t_user
		<set>
			id = #{id}
			<if test="username != null and username != ''">
				username = #{username}, 
			</if>
			<if test="password != null and password != ''">
				password = #{password}, 
			 </if>
		</set>
		WHERE id = #{id}
	</update>

foreach标签

用来迭代一个集合,通常用来构建IN条件。

	<select id="selIn" parameterType="list" resultType="user">
		SELECT * FROM t_user
		<where>
			id in 
			<!-- 遍历list集合,取了到item,以'('开始,','分隔',以')'结束 -->
			<foreach collection="list" item="item" open="(" separator = "," close = ")">
				#{item}
			</foreach>
		</where>
		
	</select>

include标签

引用写好的sql

<sql id="mySql">
	id, username, password
</sql>

<select id="selAll" resultType="User">
	SELECT <include refid="mySql"/> FROM t_user
</select>

MyBaties的缓存机制

缓存机制,提高查询效率

Mybatis支技缓存,有两种缓存机制

一级缓存

线程级别的缓存,SqlSession对象缓存。

默认开启。

基于SQL的id,id不一样语句一样也不会触发缓存查询。

同 一个SqlSession对象同一个id才可以使用。

二级缓存

进程级别的缓存,SqlSessionFactory对象缓存。

在mapper配置 文件中,使用cache标签开启。

列名和属性名不一致

如果查询时使用 resultType 属性, 表示采用 MyBatis 的Auto-Mapping(自动映射)机制, 即相同的列名和属性名会自
动匹配. 因此, 当数据库表的列名和类的属性名不一致时, 会导致查不到数据. 解决该问题可以有两种方式:

1. 列别名

查询时, 可以通过列别名的方式将列名和属性名保持一致, 继续使用自动映射, 从而解决该问题. 但是较为麻烦.

2. ResultMap

用于自定义映射关系, 可以由程序员自主制定列名和属性名的映射关系. 一旦使用 resultMap, 表示不再采用自动映射机制.

	<resultMap type="user" id="umap">
		<!-- 映射主键 -->
		<id  column="id" property="id1"/>
		<!-- 映射非主键 -->
		<result column="username" property="username1"/>
		<result column="password" property="password1"/>
	</resultMap>
	<select id="selAll" resultMap="umap">
		SELECT * FROM t_user
	</select>

多表关联查询

学生表(t_student),字段 :id, name, age, gender, cid

班级表(t_class),字段:id, name, room

业务装配

在service 业务层通过组装mapper 层的单表查询的结果返回结果集合。

实体类

创建班级类(Clazz)和学生类(Student), 并在 Student 中添加一个 Clazz 类型的属性, 用于表示学生的班级信息。

mapper 层

提供StudentMapper和ClazzMapper, StudentMapper查询所有学生信息, ClazzMapper 根据编号查询班级信息.

<mapper namespace="com.trf.mapper.StudentMapper">
	<select id="selAll" resultType="student">
		SELECT * FROM t_student
	</select>
</mapper>

 

<mapper namespace="com.trf.mapper.ClazzMapper">
	<select id="selById" resultType="clazz" parameterType="int">
		SELECT * FROM t_class WHERE id = #{0};
	</select>
</mapper>
service 层
public class StudentServiceImpl implements StudentService {

	@Override
	public List<Student> selAll() {
		SqlSession session = MyBatisUtil.getSession();
		StudentMapper stuMapper = session.getMapper(StudentMapper.class);
		List<Student> stuList = stuMapper.selAll();
		//为每个Student对象组装Clazz信息
		for (Student s : stuList) {
			ClazzMapper clzMapper = session.getMapper(ClazzMapper.class);
			s.setClazz(clzMapper.selById(s.getCid()));
		}
		session.close();
		return stuList;
	}

}
测试
public class TestSel {
	public static void main(String[] args) {
		StudentService ss = new StudentServiceImpl();
		List<Student> list = ss.selAll();
		for (Student student : list) {
			System.out.println(student);
		}
	}
}

resultMap的N+1方式实现多表查询

mapper 层

提供StudentMapper和ClazzMapper, StudentMapper查询所有学生信息, ClazzMapper 根据编号查询班级信息. 在StudentMapper 中使用设置装配.

  • property: 指定要关联的属性名
  • select: 设定要继续引用的查询, namespace+id
  • column: 查询时需要传递的列
<mapper namespace="com.trf.mapper.StudentMapper">
	<resultMap type="student" id="smap">
		<result column="cid" property="cid"/>
		<!-- 关联对象 -->
		<association property="clazz" column="cid" select="com.trf.mapper.ClazzMapper.selById"></association>
	</resultMap>
	<select id="selAll" resultMap="smap">
		SELECT * FROM t_student
	</select>
</mapper>

 

<mapper namespace="com.trf.mapper.ClazzMapper">
	<select id="selById" resultType="clazz" parameterType="int">
		SELECT * FROM t_class WHERE id = #{0};
	</select>
</mapper>
service 层

由于装配已经完成, service 层只需要调用 mapper 即可, 不需要再进行装配了.

public class StudentServiceImpl implements StudentService {

	@Override
	public List<Student> selAll() {
		SqlSession session = MyBatisUtil.getSession();
		StudentMapper stuMapper = session.getMapper(StudentMapper.class);
		List<Student> stuList = stuMapper.selAll();
		session.close();
		return stuList;
	}

}

resultMap 的关联方式实现多表查询(

mapper 层
  1. 在 StudentMapper.xml 中定义多表连接查询 SQL 语句, 一次性查到需要的所有数据, 包括对应班级的信息.
  2. 通过定义映射关系, 并通过指
    定对象属性的映射关系. 可以把看成一个使用. javaType 属性表示当前对象, 可以写全限定路径或别名.
<mapper namespace="com.trf.mapper.StudentMapper">
	<resultMap type="student" id="smap">
		<id column="sid" property="id"/>
		<result column="sname" property="name"/>
		<result column="age" property="age"/>
		<result column="cid" property="cid"/>
		<result column="sname" property="name"/>
		<association property="clazz" javaType="clazz">
			<id column="cid" property="id"/>
			<result column="cname" property="name"/>
			<result column="room" property="room"/>
		</association>
	</resultMap>
	<select id="selAll" resultMap="smap">
		SELECT s.id sid, s.`name` sname, s.age, s.gender, c.id cid, c.`name` cname, c.room 
		FROM t_student s, t_class c
		WHERE s.cid = c.id
		ORDER BY s.id
	</select>
</mapper>
service层

本层不用修改。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值