Mybatis总结

  1. Mybatis配置
  • .主配置文件 mybatis.xml
<configuration>
    <!-- setting 控制mybatis 全局行为 -->
    <properties resource="jdbc.properties"/>
    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    <!-- 定义别名 -->
    <typeAliases>
<!--        <typeAlias type="com.entity.Student" alias="Student"/>-->
        <!-- 指定包 包里的所有类名就是别名 类名不区分大小写  会扫描包下所有的类 将全部的类都映射别名 如果别名相同就会出错-->
        <package name="com.entity"/>
    </typeAliases>
    <plugins>
        <!-- 添加分页插件 -->
        <plugin interceptor="com.github.pagehelper.PageInterceptor"/>
    </plugins>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
    <!--sql mapper映射文件的位置-->
    <mappers>
         <!-- mapper 标签 每次只能写一个 mapper 文件  同一个文件不能多次导入-->
<!--        <mapper resource="com/dao/StudentDao.xml"/>-->
        <!-- 第二种方式  使用package
            name: xml文件 mapper文件所在的包名 这个包中所有xml文件一次都能加载
            使用package文件的要求:
              mapper文件名称 和 接口名称一样 不区分大小写的一样
              mapper文件和 dao接口需要在同一目录
        -->
        <package name="com.dao"/>
    </mappers>
</configuration>

mybaits启动的时候会扫描到mybatis.xml 这个配置文件 ,使用 SqlSessionFactoryBuilder 将配置文件进行解析装载,得到 SqlSessionFactory 实例,然后使用的时候由 SqlSessionFactory 获取 SqlSession对象,所有的数据库操作都由这个对象进行处理。
注意 SqlSession实例并不是线程安全的,所以一般是在方法体里获取这个对象,将对象的有效域限制在局部方法中以保证多线程安全,使用完成之后需要手动执行 close 方法销毁这个对象。
sqlSessionFactory.openSession() 获取时 ,默认得到的是sqlSession 对象是关闭自动提交的,如果有DDL操作(增 删 改)则需要手动执行 sqlSession.commit();
但是如果在获取SqlSession对象时 使用的是:SqlSession sqlSession = sqlSessionFactory.openSession(true);//获取自动提交事务 则不需要再手动提交

private static SqlSessionFactory sqlSessionFactory = null;

	static{
		//定义访问 mybatis 主配置文件的名称
		String config = "mybatis.xml";
		//读取这个config配置文件
		try (InputStream resourceAsStream = Resources.getResourceAsStream(config)) {
			//创建sqlsessionFactoryBulider 对象
			SqlSessionFactoryBuilder bulider = new SqlSessionFactoryBuilder();
			//创建sqlsessionFactory对象
			sqlSessionFactory = bulider.build(resourceAsStream);
			//获取 sqlsession对象 ,从sqlsessionFactory 中 获取sqlSession
			SqlSession sqlSession = sqlSessionFactory.openSession();//获取非自动提交事务
			//SqlSession sqlSession = sqlSessionFactory.openSession(true);//获取自动提交事务

			}catch(Exception e) {

			}

		}
//执行数据库操作

			String sqlId = "com.dao.StudentDao" + "." + "selectStudentList";
			//执行语句 通过sqlId找到语句
			List<Student> studentList = sqlSession.selectList("selectStudentList");
			//如果 selectStudentList 是唯一的,那么上面和下面的都是可以正常执行的
			//List<Student> studentList = sqlSession.selectList(sqlId );

			studentList.forEach(stu-> System.out.println(stu));

mybatis 在执行sql 时 是根据命名空间 + id 的方式来查找到指定的sql,同时如果id 在全局里是唯一的,是可以直接使用 id 来执行sql的。

  • Mapper配置文件 xx-mapper.xm
<mapper namespace="com.dao.StudentDao">
    <select id="selectStudentList" resultType="Student">
        select id,name,email,age from mstudent order by id desc
    </select>

    <select id="selectNextId" resultType="Integer">
        select max(id)+1 from mstudent
    </select>

</mapper>
  1. Mybatis执行数据库操作 和 动态代理原理

    很多人会好奇为什么mybaits 需要配置一个接口 和 一个同名的mapper文件 ? 这个要跟mybaits执行sql的流程说起

    mybatis在启动之初会将 namespace 命名空间 和 所有sql的id 全部进行注册 。 在具体执行sql的时候是使用 命名空间 + id 的方法寻找到指定的sql , 然后根据把命名空间当做一个接口/类A 使用JDK自动代理的方式生成类A的实现类的一个实例,由这个实例来执行sql。
    执行sql 时 根据mapper文件中的sql 的标签是 select 还是 update insert delete 来确定执行的是哪一种操作 ,比如
    <select id="selectStudentList" resultType="Student"> select id,name,email,age from mstudent order by id desc </select>
    mybatis 知道这是一个查询操作 ,但是具体是使用 selectOne 还是使用 selectList 哪一种方法呢?
    这个时候返回值类型 resultType 就派上用场了,如果 resultType 是java基本类型 和 String 类型 ,那么mybaits 就知道了这是查询单条记录 ,如果是list类型(实际上resultType 是具体的对象类型)这时候就知道调用 selectList 了。
    从上面的过程是可以看出来实际上执行sql 完全可以就靠mapper 文件就行了,**不需要接口 **。
    使用接口是为了符合java的使用规范,使用接口的时候

--//使用接口执行sql
    StudentDao mapper = sqlSession.getMapper(StudentDao.class);
    List<Student> students = mapper.selectStudentList();
 //   StudentDao 的全限量名 com.dao.StudentDao 就是 mapper文件的命名空间
     //接口的方法 selectStudentList 就是sql 的id ,获取到sql的信息后 通过动态代理生成 StudentDao 的一个实现类的对象来执行sql
      //打印出 mapper对象的类名,发现就是一个jdk代理生成的对象
   System.out.println(mapper.getClass().getName());  com.sun.proxy.$Proxy5
  1. Mybatis 传参

    mybatis获取参数有两种办法:一种使用占位符: # , 一种使用 $ 替换符
    比如执行 select id , name, email, age from mstudent where id= #{id} 时,实际上过程是

 select id , name, email, age  from mstudent where id= #{id}` 
//先获取一个 preparedStatement 对象
PreparedStatement pst = conn.preparedStatement();
String sql = "select id , name, email, age  from mstudent where id= ? ";
//设置参数
pst.setInt(1, id);
//执行sql 获取结果
ResultSet rs = pst.executeQuery();
while (rs.hasNext){
     Object obj =  rs.next();
     //如果有无参构造器
     Student student = new Student();
     student.setName(obj.getString("Name"));
     。。。
     //如果没有无参构造器
      Student student = new Student(a,b,c,d);
      //将返回结果中的字段按顺序 id , name, email, age 往 a b c d 上塞
}

  • 单个参数传参
    单个参数时,使用 # 取参数值时,参数名随便写,从现实逻辑来讲,反正就一个参数直接用就行了
Student selectStudentById(int id);
//mapper 文件中
<!-- paremeterType 是java的数据类型全限量名称或者是mybatis定义的别名 java.lang.Integer 或者  int (别名)
      patemeterType 不是强制的,mybatis通过反射机制能够发现接口参数的类型-->
    <select id="selectStudentById" resultType="com.entity.Student" parameterType="java.lang.Integer">
        select id , name, email, age  from mstudent where id= #{id}
    </select>

或者

 select id , name, email, age  from mstudent where id= #{ajdj}

都是可以的

  • 多个参数传参
//取值的时候 使用 arg0 arg1 或者 param1 param2 即可 3.4以前的版本可以直接只用 #{0} #{1}
List<Student> selectStudentByIdAndName(int id, String name);
//可以使用 #{myId} #{myName} 取值
List<Student> selectStudentByIdAndName2(@Param("myId") int id, @Param("myName") String name);

 <!--多个参数传递 -->
    <select id="selectStudentByIdAndName" resultType="student" >
        select id , name, email, age  from mstudent where id= #{arg0} or name = #{arg1}
    </select>

    <select id="selectStudentByIdAndName2" resultType="com.entity.Student" >
        select id , name, email, age  from mstudent where id= #{myId} or name = #{myName}
    </select>
  • 对象传参
// 直接使用 属性名  即可
// javaType=string, jdbcType=VARCHAR  可写 可不写,但是如果是进行插入操作,字段有可能null时,**必须写上 否则会报类型转换错误**
private String queryName;
private int queryId;

List<Student> selectStudentByObj(QueryEntity entity);
 <select id="selectStudentByObj" resultType="com.entity.Student" >
        select id , name, email, age  from mstudent where id= #{queryId,javaType=int, jdbcType=INTEGER}
            or name = #{queryName,javaType=string, jdbcType=VARCHAR}
    </select>

<select id="selectStudentByObj" resultType="com.entity.Student" >
        select id , name, email, age  from mstudent where id= #{queryId} or name = #{queryName}
    </select>
  • Map传参 (不建议使用)

//使用Map 传参数 只能使用 Map<String,Object> 类型 ,xml文件中只能使用 #{key}
//不能使用  Map<String,String> 哪怕参数只有String 类型的也不行,会报类型错误
//因为这种参数不可控 不建议使用,在阿里的开发规范中明确建议禁止
/** 不建议使用
	* @Description:
	* @Param: [paramMap]
	* @return: java.util.List<com.entity.Student>
	* @Author: Administrator
	* @Date: 2021/8/14
	*/
	List<Student> selectStudentByMap(Map<String,Object> paramMap);

	
  1. 条件和动态sql
    主要是 if where foreach 这3个 和 sql片段
   <!-- 动态 sql  if where foreach
        <if test="java 对象的属性" >
    -->
    <select id="selectStudentIf" resultType="student">
        select id,  name, email ,age  from mstudent
        where 1=1
        <if test="name !=null and name !=''">
           and  name= #{name}
        </if>
        <if test="age>0">
            and age > #{age}
        </if>
    </select>

    <select id="selectStudentWhere" resultType="student">
        select id,  name, email ,age  from mstudent
        <where>
            <if test="name !=null and name !=''">
                and  name= #{name}
            </if>
            <if test="age>10">
                and age > #{age}
            </if>
        </where>
    </select>

    <select id="selectStudentForeach" resultType="student">
        select id,  name, email ,age  from mstudent
        where id in
        <foreach collection="list" item="myId" open="(" close=")" separator=",">
            #{myId}
        </foreach>
    </select>

    <select id="selectStudentForeachEntity" resultType="student">
        select id,  name, email ,age  from mstudent
        where id in
        <foreach collection="array" item="stu" open="(" close=")" separator=",">
              <if test="stu.id != null">
                  #{stu.id}
              </if>
        </foreach>
    </select>

最后提一下 like 查询 和 $ 替换符号,
$ 是使用拼接sql的方式,所以执行效率低,还有sql 注入风险。
实际上的主要用途是用来替换列名 和 表名,比如排序的时候 根据不同的字段进行排序

<select id="selectStudentOrder" resultType="com.entity.Student" >
        select id , name, email, age  from mstudent where id >=#{id} order by ${colname} asc
    </select>

like 查询有2 种方式, 一种是将 查询条件在 java 中写好,直接送进去,这种最简单易懂

String nameLike = "%an%";
<select id="selectLikeName" resultType="student">
        select id,  name, email ,age  from mstudent where name like #{nameLike }
    </select>

一种是由mybatis 利用 concat 函数进行拼接

      <!-- like 查询 使用字符串拼接函数 -->
    <select id="selectLikeName2" resultType="student">
        select id,  name, email ,age  from mstudent where name like concat(concat('%',#{likeName}),'%')

    </select>
  1. 参数映射
    主要用于解决数据库列名 和 实体对象属性名不一致的问题
    其中 id 列的话 使用 id 标签, 一般列使用 result 标签
 <!-- 返回结果中的列 如果在 resultMap 中没有指定映射则会使用默认字段映射-->
    <resultMap id="studentInfo" type="com.entity.Student">
        <id column="id" property="id"/>
        <result column="name" property="email"/>
        <result column="email" property="name"/>
    </resultMap>
    
<select id="selectAllStudent" resultMap="studentInfo">
        select id,  name, email ,age  from mstudent
    </select>
 mybatis 在映射时,如果 student对象中有个 age 属性,但resultMap 没有写aga的映射关系,则会使用默认的映射关系 如上图虽然没有指定age 映射到student对象上哪个属性,依然会赋值给student 对象上的 age属性
  1. 分页插件 PageHelper
    这个比较简单,其实就是在原有的sql 再套一层。执行查询时先查出总记录数, 再确定 记录数的 beginNo 和 endNo

导入依赖包 和 配置 mybatis 主文件

<dependency>
      <groupId>com.github.pagehelper</groupId>
      <artifactId>pagehelper</artifactId>
      <version>5.2.0</version>
    </dependency>

plugins 插件要写在 environments 标签之前

  <plugins>
        <!-- 添加分页插件 -->
        <plugin interceptor="com.github.pagehelper.PageInterceptor"/>
    </plugins>
//获取第几页 一页中有多少记录
		PageHelper.startPage(1, 3);
		List<Student> students = studentDao.selectAll();
		students.forEach(stu-> System.out.println(stu));
<select id="selectAll" resultType="student">
        select * from mstudent order by id
    </select>

执行过程如下:

==>  Preparing: SELECT count(0) FROM mstudent 
==> Parameters: 
<==    Columns: COUNT(0)
<==        Row: 17
<==      Total: 1
==>  Preparing: SELECT * FROM ( SELECT TMP_PAGE.*, ROWNUM PAGEHELPER_ROW_ID FROM ( select * from mstudent order by id ) TMP_PAGE) WHERE PAGEHELPER_ROW_ID <= ? AND PAGEHELPER_ROW_ID > ? 
==> Parameters: 3(Long), 0(Long)
<==    Columns: ID, NAME, EMAIL, AGE, PAGEHELPER_ROW_ID
<==        Row: 1, xiao, 123@qq.com, 10, 1
<==        Row: 2, liu, 124@qq.com, 11, 2
<==        Row: 3, 安安, 1235@qq.com, 25, 3
<==      Total: 3
Student{id=1, name='xiao', email='123@qq.com', age=10}
Student{id=2, name='liu', email='124@qq.com', age=11}
Student{id=3, name='安安', email='1235@qq.com', age=25}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值