MyBatis学习

Posted Zephyr丶J

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MyBatis学习相关的知识,希望对你有一定的参考价值。

MyBatis

课程链接:https://www.bilibili.com/video/BV1wV411e76e?spm_id_from=333.999.0.0
再次感谢老师

框架概述

MVC架构

MVC:web开发中,使用MVC架构模式,m数据;v视图;c控制器
控制器:接收请求,调用service对象,显示请求的处理结果,当前使用servlet作为控制器
视图:现在使用jsp,html,css,js 显示请求的处理结果,把m中数据显示出来
数据:来着数据库mysql,来自文件、网络的数据

三层架构

界面层: 和用户打交道的, 接收用户的请求参数, 显示处理结果的。(jsp ,html ,servlet)
业务逻辑层: 接收了界面层传递的数据,计算逻辑,调用数据库,获取数据,把处理好的数据返回界面层
数据访问层: 就是访问数据库, 获取数据,执行对数据的查询,修改,删除等等的。

三层对应的包
界面层: controller包 (servlet)
业务逻辑层: service 包(XXXService类)
数据访问层: dao包(XXXDao类)

三层中类的交互
用户发起请求–>界面层–> 业务逻辑层—>数据访问层(持久层)–>数据库(mysql)

三层对应的处理框架
界面层—servlet—SpringMVC(框架)
业务逻辑层—service类–Spring(框架)
数据访问层—dao类–MyBatis(框架)

为什么要使用三层?

  1. 结构清晰、耦合度低, 各层分工明确
  2. 可维护性高,可扩展性高
  3. 有利于标准化
  4. 开发人员可以只关注整个结构中的其中某一层的功能实现
  5. 有利于各层逻辑的复用

框架(Framework)

框架是一个舞台, 一个模版

模版:
1. 规定了好一些条款,内容。
2. 加入自己的东西

框架是一个模块
1.框架中定义好了一些功能。这些功能是可用的。
2.可以加入项目中自己的功能, 这些功能可以利用框架中写好的功能。

框架是一个软件,半成品的软件,定义好了一些基础功能, 需要加入你的功能就是完整的。
基础功能是可重复使用的,可升级的。

框架特点:

  1. 框架一般不是全能的, 不能做所有事情
  2. 框架是针对某一个领域有效。 特长在某一个方面,比如mybatis做数据库操作强,但是他不能做其它的。
  3. 框架是一个软件

框架能实现技术的整合,提高开发的效率,降低难度

JDBC的优缺点

优点:直观好理解
缺点:创建很多对象 Connection Statement,ResultSet,步骤很多,sql语句和业务逻辑混合在一起

mybatis框架

一个框架,早期叫做ibatis, 代码在github。
mybatis是 MyBatis SQL Mapper Framework for Java (sql映射框架)
1)sql mapper :sql映射
可以把数据库表中的一行数据 映射为 一个java对象。
一行数据可以看做是一个java对象。操作这个对象,就相当于操作表中的数据
2) Data Access Objects(DAOs) : 数据访问 , 对数据库执行增删改查。

mybatis提供了哪些功能:

  1. 提供了创建Connection ,Statement, ResultSet的能力 ,不用开发人员创建这些对象了
  2. 提供了执行sql语句的能力, 不用你执行sql
  3. 提供了循环sql, 把sql的结果转为java对象, List集合的能力
  4. 提供了关闭资源的能力,不用你关闭Connection, Statement, ResultSet
  5. 实现java代码和sql语句解耦合

开发人员做的是: 提供sql语句
最后是: 开发人员提供sql语句–mybatis处理sql—开发人员得到List集合或java对象(表中的数据)

总结:
mybatis是一个sql映射框架,提供的数据库的操作能力。增强的JDBC,
使用mybatis让开发人员集中精神写sql就可以了,不必关心Connection,Statement,ResultSet
的创建,销毁,sql的执行。

使用入门

例子

  1. 创建student表(id, name, email, age)

  2. 新建maven项目

  3. 修改pom.xml
    1)加入mybatis依赖,mysql驱动,junit
    2)在<build>中加入资源插件

  4. 创建实体类Student,定义属性,属性名和列名保持一致

  5. 创建Dao接口,定义操作数据库的方法

  6. 创建xml文件(mapper文件),写sql语句
    mybatis创建推荐是把sql语句和java代码分开
    mapper文件:定义和dao接口在同一目录,一个表一个mapper文件

  7. 创建mybatis的主配置文件(xml文件):有一个,放在resources目录下
    1)定义创建连接实例的数据页(DataSource)对象
    2)指定其他mapper文件的位置

注意:xml文件中一些符号不能直接写,需要对应的实体对象来表示

  1. 创建测试的内容
    使用main方法,测试mybatis访问数据库,也可以使用junit访问数据库

占位符初步使用

这个#String表示写这个sql语句时传入的值

日志

在主配置文件中按照官方说明添加
STDOUT_LOGGING表示将日志打印到控制台上

执行以后打印出很多东西

自动提交、手动提交

自动提交:当sql语句执行完毕后,提交事务,数据库更新操作直接保存到数据
手动提交:在需要提交事务的位置,执行方法,提交事务或者回滚事务

添加一个学生

dao

xml

测试

但是执行以后没有添加到数据库中,是因为mybatis默认执行sql语句是手动提交的模式,在做insert,update,delete后需要提交事务
加入commit后,成功了

如果要插入一个可以改变的对象,用占位符


MyBatis的一些重要对象

  1. Resources: mybatis中的一个类, 负责读取主配置文件信息
InputStream in = Resources.getResourceAsStream("mybatis.xml");
  1. SqlSessionFactoryBuilder : 创建SqlSessionFactory对象,
	SqlSessionFactoryBuilder builder  = new SqlSessionFactoryBuilder();
    //创建SqlSessionFactory对象
    SqlSessionFactory factory = builder.build(in);
  1. SqlSessionFactory : 是重量级对象,程序创建一个对象耗时比较长,使用资源比较多。
    在整个项目中,有一个就够用了。

    SqlSessionFactory:接口,接口实现类: DefaultSqlSessionFactory
    SqlSessionFactory作用: SqlSession的工厂,获取SqlSession对象。SqlSession sqlSession = factory.openSession();

    openSession()方法说明:

    1. openSession() :无参数的, 获取是非自动提交事务的SqlSession对象,需要手动提交
    2. openSession(boolean): openSession(true) 获取自动提交事务的SqlSession.
      openSession(false) 非自动提交事务的SqlSession对象

SqlSessionFactory的实现类

  1. SqlSession:
    通过SqlSessionFactory获取,是一个接口
    SqlSession接口 :定义了操作数据的方法 例如 selectOne() ,selectList() ,insert(),update(), delete(), commit(), rollback()

selectOne():执行sql语句,最多得到一行记录,多余1行是错误的
selectList():返回多行记录
selectMap():得到一个map集合

SqlSession接口的实现类DefaultSqlSession。

使用要求: SqlSession对象不是线程安全的,使用步骤:

  1. 需要在方法内部使用, 在执行sql语句之前,使用openSession()获取SqlSession对象。
  2. 调用SqlSession的方法,执行sql语句
  3. 在执行完sql语句后,需要关闭它,执行SqlSession.close().

因为是局部变量,所以这样能保证他的使用是线程安全的。

实现类,不是线程安全的

创建mapper文件的模板

因为mapper文件格式是固定的,所以创建一个模板
先用记事本拷贝一个模板

然后新建的时候就能看到刚创建好的模板

写入语句

创建主配置文件模板

和上面基本一样

创建工具类



测试


查询多个对象

使用DAO执行SQL

crtl+O 实现接口中的方法
写一个实现类实现DAO接口

写测试类:

Dao动态代理

mybatis代理实现方式

使用SqlSession对象的方法 getMapper(dao.class)
例如:现在有StudentDao接口

SqlSession session = MyBatisUtil.getSqlSession();
StudentDao dao = session.getMapper(StudentDao.class);
Student stu = dao.selectById(1001);

//上面代码中
StudentDao dao = session.getMapper(StudentDao.class);
//等同于
StudentDao dao = new StudentDaoImpl();

简单使用

可以没有impl实现类

理解参数

理解参数是 通过java程序把数据传入到mapper文件中的sql语句。参数主要是指dao接口方法的形参

  1. 动态代理: 使用SqlSession.getMapper(dao接口.class) 获取这个dao接口的对象
  2. 传入参数: 从java代码中把数据传入到mapper文件的sql语句中。

1)parameterType : 写在mapper文件中的 一个属性。 表示dao接口中方法的参数的数据类型。
这个形参的数据类型是给mybatis使用,mybatis再给sql语句的参数赋值时使用。PreparedStatement.setXXX(位置,值)

例如StudentDao接口
public Student selectStudentById(Integer id)

或者使用别名,别名可以在官方文档查看
当然也可以不写

2) 一个简单类型的参数:
简单类型: mybatis把java的基本数据类型和String都叫简单类型。
在mapper文件获取简单类型的一个参数的值,使用 #任意字符

接口:public Student selectStudentById(Integer id)
mapper:select id,name, email,age from student where id=#studentId

3) 多个参数,使用@Param命名参数,在方法的形参前面使用,定义参数名,这个名称可以用在mapper文件中
接口 public List selectMulitParam(@Param(“myname”) String name, @Param(“myage”) Integer age)
使用 @Param(“参数名”) String name
mapper文件:

select * from student where name=#myname or age=#myage


  1. 多个参数,dao接口方法使用一个java对象作为参数
    方法的形参是一个java对象,这个java对象来表示多个参数,使用对象的属性值作为参数使用
    语法 #属性名


如果随便创建一个类,用这个对象来当做查询参数


完整的写法

5)多个简单类型的参数,使用位置传参(了解)
参数位置:dao接口中方法的形参列表,从左往右,参数位置是0 1 2…
语法格式:#arg0, #arg1

6)dao接口参数是一个Map

测试一下更新操作


# 和 $

#占位符(推荐使用)

语法:#字符

mybatis处理#使用jdbc对象是PreparedStatement

  select id,name, email,age from student where id=#studentId
  \\# 的结果: select id,name, email,age from student where id=? 

mybatis创建出PreparedStatement对象,执行sql语句

String sql = "select id,name, email,age from student where id=?";
PreparedStatement pst = conn.preparedStatement(sql);
pst.setInt(1, 1001);
ResultSet rs = pst.executeQuery();

#特点:
1)使用PreparedStatement 对象, 执行sql语句,效率高
2)使用PreparedStatement 对象,能避免sql注入,执行更安全
3)#常常作为列值来使用,位于等号的右侧,#位置的值和数据类型有关的

$占位符

语法:$
mybatis执行$占位符的sql语句

   select id,name, email,age from student where id=$studentId
  $ 的结果:select id,name, email,age from student where id=1001

$表示字符串的连接,把sql语句的其他内容和$内容使用字符串(+)连接的方式连在一起

  String sql="select id,name, email,age from student where id=" + "1001";
  Statement stmt = conn.createStatement(sql);
  ResultSet rs = stmt.executeQuery();

$的特点
1)使用的Statement对象执行sql, 效率比PreparedStatement低。
2)$占位符的值,使用字符串连接方式,有sql注入的风险,有代码安全的问题
3)$数据是原样使用的,不会区分数据类型
4)常用作表名和列名使用,在数据安全的情况下
$:可以替换表名或者列名, 你能确定数据是安全的。可以使用$

# 和 $区别
1. #使用 ?在sql语句中做占位的, 使用PreparedStatement执行sql,效率高
2. #能够避免sql注入,更安全。
3. $不使用占位符,是字符串连接方式,使用Statement对象执行sql,效率低
4. $有sql注入的风险,缺乏安全性。
5. $:可以替换表名或者列名

写了一个$的例子

但是报错了

加上注解以后,还是错误的
这里把 lisi 当做一个列名来看待,直接拼接在sql语句后面


加上了引号,才能输出正确的结果

如果这样写,会造成sql注入,查出来的是所有结果

用$占位符表示表名或者列名


封装MyBatis输出结果

封装输出结果:MyBatis执行sql语句,得到ResultSet,转为java对象

ResultType

ResultType属性:在执行select时使用,作为<select>标签的属性出现的
ResultType表示结果类型,mysql执行sql语句,得到java对象的类型

resultType结果类型, 指sql语句执行完毕后, 数据转为的java对象, java类型是任意的。
resultType结果类型的它值 1. 类型的全限定名称 2. 类型的别名, 例如 java.lang.Integer别名是int

使用java类型的全限定名称,表示的意思是mybatis执行sql,把ResultSet中的数据转为Student类型的对象,mybatis会以下面的处理方式:

  1. mybatis执行sql语句, 然后mybatis调用Student类的无参数构造方法,创建对象(使用反射机制)。
  2. mybatis把ResultSet指定列值付给同名的属性(所以创建类的时候要使属性值和列名一样)。
    student.setId(rs.getInt(“id”))
  3. 得到java对象,如果dao接口返回值是list集合,mybatis把student对象放入到List集合中
<select id="selectMultiPosition" resultType="com.bjpowernode.domain.Student">
  select id,name, email,age from student
</select>
 对等的jdbc
  ResultSet rs = executeQuery(" select id,name, email,age from student" )
  while(rs.next())
       Student  student = new Student();
	   student.setId(rs.getInt("id"));
	   student.setName(rs.getString("name"))
  

自定义别名

mybatis提供的对java类型定义的简短名称,使用步骤(声明+使用)
1)在mybatis主配置文件中定义,使<typeAliases>定义别名
2)在mapper文件中,resultType=“别名”

在mybatis的主配置文件中,标签是有顺序的,不能随便写,顺序可以进入configuration里面去看:

在mybatis主配置文件中,声明别名

在mapper文件中使用

第二种方式:

建议:不适用别名,直接使用全限定名称

resultType同名列赋值给同名的属性

现在创建一个别的类

然后让查询后变成这个java对象

这里看到结果id和name并没有被赋值,是因为不是同名的属性
从这里也能看到resultType这里是自定义对象,并不一定要在dao包下,并不一定是实体

resultType表示简单类型

resultType返回Map

输出结果:

resultMap

resultMap:结果映射, 指定列名和java对象的属性对应关系。常用在列名和属性名不同的情况
1)你自定义列值赋值给哪个属性
2)当你的列名和属性名不一样时,一定使用resultMap

用法:
1.先自定义resultMap标签,指定列名和属性名的对应关系
2.在select标签使用resultMap属性,指定上面自定义的resultMap的id值

resultMap和resultType不要一起用,二选一

还是刚刚那个查询,因为之前这个类里面的属性名称和列名不对应,所以不能赋值

然后写对应的关系

然后查询

可以看到输出结果也赋值了

列名和java对象属性名称不一样解决方式

1) 使用resultMap:自定义列名和属性名对应关系
2)使用resultType:使用列别名,使其和对象属性一样就可以了(不常用)


结果

模糊查询like

查询name包含李的记录
第一种方式:在java程序汇总,把like的内容组装好,把这个内容传入到sql语句中,比较灵活

关键是这里

第二种方式:在sql语句中,组织like内容
sql语句汇总like的格式:where name like “%“空格#name空格”%”


动态sql

动态sql: 同一个dao的方法,根据不同的条件可以表示不同的sql语句,主要是where部分有变化
sql的内容是变化的,可以根据条件获取到不同的sql语句。主要是where部分发生变化。

动态sql的实现,使用的是mybatis提供的标签, <if> ,<where>,<foreach>,sql代码片段

使用动态sql的时候,dao方法形参要使用java对象

if标签

1)<if>是判断条件的,可以同时有多个if,但是没有else
语法:

   <if test="判断java对象的属性值">
        部分sql语句
   </if>

注意这里第二个条件前面加了个or,因为是sql语句进行拼接的


但是如果没有名字,直接用age查询,很显然拼接后的sql语句是错误的,
所以一般会如下做,使得语法没有错误

另外注意,如果这里age < #age,由于在mapper文件中 < 这个符号是标签的开头,所以要用实体来表示小于号

这种多用在多条件查询中,如下面仅按照姓名或者年龄或者email查询

where标签

使用if标签时,容易引起sql语句语法错误,使用where标签解决if产生的语法问题
<where> 用来包含 多个<if>的, 当多个if有一个成立的, <where>会自动增加一个where关键字,附加到sql语句的后面,并去掉 if中紧跟着where的多余的 and ,or等,如果没有一个if条件为真,忽略where和里面的if

语法:

<where>
	<if test="条件1"> sql语句1</if>
	<if test="条件2"> sql语句1</if>
</where>

循环取出多个数据(foreach)

如果手工处理的话
需要自己拼接字符串

3)<foreach> 循环java中的数组,list集合的。 主要用在sql的in语句中。
语法:

	<foreach collection="集合类型" open="开始的字符" close=“结束的字符” 
	item=“集合中的成员” separator=“集合成员之间的分隔符”>
		#item的值
	</foreach>
	标签属性:
	collection:表示循环的对应是数组,还是list集合,如果dao接口方法形参是数组,
						collection="array",如果形参是list,那么collection=“list”
	open:循环开始的字符。sql.append("(");
	close:循环结束的字符。sql.append(")");
	item:自定义的集合成员 Integer item = idList.get(i);
	separator:集合成员之间的分隔符 sql.append(",");
	#item的值:获取集合成员的值


但是如果传入的list是null,则报错

循环list对象



sql代码片段

sql代码片段, 就是复用一些语法
表示一段sql代码,可以是表名,几个字段,where条件都可以,可以在其他地方复用sql标签的内容

步骤
1.mapper中先定义 <sql id="自定义名称唯一">  sql语句, 表名,字段等 </sql>
2.再使用, <include refid="id的值" />

定义

使用

MyBatis主配置文件

MyBatis配置文件分两类:1.mybatis主配置文件 2.mybatis的mapper文件
1.mybatis主配置文件,提供mybatis全局设置,包含日志,数据源,mapper文件位置等
2.mapper文件:写sql语句的,一个表一个mapper文件

settings部分

settings部分是mybatis是全局设置,影响整个mybatis的运行,一般使用默认值就行了

typeAliases别名

可以设置也可以不设置,前面提到过

	<!-- 声明别名 -->
    <typeAliases>
        <!-- 第一种语法格式
            type:java类型的全限定名称(自定义类型)
            alias:自定义别名

            优点:别名可以自定义
            缺点:每个类型必须单独定义
        -->
        <typeAlias type="com.jcy.entity.Student" alias="stu" />

        <!-- 第二种方式
             name包名:mybatis会把这个包中的所有类名作为别名(不用区分大小写)
             优点:使用方便,一次给多个类定义别名
             缺点:别名不能自定义,必须是类型
                  如果多个包内有同名的类,会发生错误
        -->
        <package name="com.jcy.entity"/>
    </typeAliases>

配置环境

environments 环境标签,可以配置多个环境
	属性:default,必须是某个environment的id属性值,表示mybatis默认连接的数据库
	
environment 表示一个数据库的连接信息
	属性 id 自定义的环境表示,唯一值
	
transactionManager 事务管理器
	属性:type 表示事务管理器的类型
		属性值1:jdbc:使用Connection对象,由mybatis自己完成事务的处理
		属性值2:MANAGED:管理,表示把事务的处理交给容器来实现(由其他软件完成事务的提交、回滚)
		
dataSource 数据源,创建的Connection对象,连接数据库
	属性 type 数据源的类型
		属性值1:POOLED,mybatis会在内存中创建PooledDataSource类,管理多个Connection连接对象,使用的是连接池
		属性值2:UNPOOLED,不使用连接池,mybatis创建一个UnPooledDataSource类,每次执行sql语句先创建Connection对象,再执行sql了语句,最后关闭Connection
		属性值3:JNDI java命名和目录服务,现在也一般不用
		
<environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <!-- 配置数据源:创建Connection对象 -->
            <dataSource type="POOLED">
                <!-- driver:驱动的内容 -->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <!-- 连接数据库的url -->
                <property name=

以上是关于MyBatis学习的主要内容,如果未能解决你的问题,请参考以下文章

markdown [mybatis参考]关于mybatis #mybatis的一些片段

Mybatis 学习笔记总结

Mybatis学习笔记:动态SQL

SSM-MyBatis-05:Mybatis中别名,sql片段和模糊查询加getMapper

mybatis动态sql片段与分页,排序,传参的使用

MyBatis动态SQL标签用法