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(框架)
为什么要使用三层?
- 结构清晰、耦合度低, 各层分工明确
- 可维护性高,可扩展性高
- 有利于标准化
- 开发人员可以只关注整个结构中的其中某一层的功能实现
- 有利于各层逻辑的复用
框架(Framework)
框架是一个舞台, 一个模版
模版:
1. 规定了好一些条款,内容。
2. 加入自己的东西
框架是一个模块
1.框架中定义好了一些功能。这些功能是可用的。
2.可以加入项目中自己的功能, 这些功能可以利用框架中写好的功能。
框架是一个软件,半成品的软件,定义好了一些基础功能, 需要加入你的功能就是完整的。
基础功能是可重复使用的,可升级的。
框架特点:
- 框架一般不是全能的, 不能做所有事情
- 框架是针对某一个领域有效。 特长在某一个方面,比如mybatis做数据库操作强,但是他不能做其它的。
- 框架是一个软件
框架能实现技术的整合,提高开发的效率,降低难度
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提供了哪些功能:
- 提供了创建Connection ,Statement, ResultSet的能力 ,不用开发人员创建这些对象了
- 提供了执行sql语句的能力, 不用你执行sql
- 提供了循环sql, 把sql的结果转为java对象, List集合的能力
- 提供了关闭资源的能力,不用你关闭Connection, Statement, ResultSet
- 实现java代码和sql语句解耦合
开发人员做的是: 提供sql语句
最后是: 开发人员提供sql语句–mybatis处理sql—开发人员得到List集合或java对象(表中的数据)
总结:
mybatis是一个sql映射框架,提供的数据库的操作能力。增强的JDBC,
使用mybatis让开发人员集中精神写sql就可以了,不必关心Connection,Statement,ResultSet
的创建,销毁,sql的执行。
使用入门
例子
-
创建student表(id, name, email, age)
-
新建maven项目
-
修改pom.xml
1)加入mybatis依赖,mysql驱动,junit
2)在<build>中加入资源插件
-
创建实体类Student,定义属性,属性名和列名保持一致
-
创建Dao接口,定义操作数据库的方法
-
创建xml文件(mapper文件),写sql语句
mybatis创建推荐是把sql语句和java代码分开
mapper文件:定义和dao接口在同一目录,一个表一个mapper文件
-
创建mybatis的主配置文件(xml文件):有一个,放在resources目录下
1)定义创建连接实例的数据页(DataSource)对象
2)指定其他mapper文件的位置
注意:xml文件中一些符号不能直接写,需要对应的实体对象来表示
- 创建测试的内容
使用main方法,测试mybatis访问数据库,也可以使用junit访问数据库
占位符初步使用
这个#String表示写这个sql语句时传入的值
日志
在主配置文件中按照官方说明添加
STDOUT_LOGGING表示将日志打印到控制台上
执行以后打印出很多东西
自动提交、手动提交
自动提交:当sql语句执行完毕后,提交事务,数据库更新操作直接保存到数据
手动提交:在需要提交事务的位置,执行方法,提交事务或者回滚事务
添加一个学生
dao
xml
测试
但是执行以后没有添加到数据库中,是因为mybatis默认执行sql语句是手动提交的模式,在做insert,update,delete后需要提交事务
加入commit后,成功了
如果要插入一个可以改变的对象,用占位符
MyBatis的一些重要对象
- Resources: mybatis中的一个类, 负责读取主配置文件信息
InputStream in = Resources.getResourceAsStream("mybatis.xml");
- SqlSessionFactoryBuilder : 创建SqlSessionFactory对象,
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//创建SqlSessionFactory对象
SqlSessionFactory factory = builder.build(in);
-
SqlSessionFactory : 是重量级对象,程序创建一个对象耗时比较长,使用资源比较多。
在整个项目中,有一个就够用了。SqlSessionFactory:接口,接口实现类: DefaultSqlSessionFactory
SqlSessionFactory作用: SqlSession的工厂,获取SqlSession对象。SqlSession sqlSession = factory.openSession();openSession()方法说明:
- openSession() :无参数的, 获取是非自动提交事务的SqlSession对象,需要手动提交
- openSession(boolean): openSession(true) 获取自动提交事务的SqlSession.
openSession(false) 非自动提交事务的SqlSession对象
SqlSessionFactory的实现类
- SqlSession:
通过SqlSessionFactory获取,是一个接口
SqlSession接口 :定义了操作数据的方法 例如 selectOne() ,selectList() ,insert(),update(), delete(), commit(), rollback()
selectOne():执行sql语句,最多得到一行记录,多余1行是错误的
selectList():返回多行记录
selectMap():得到一个map集合
SqlSession接口的实现类DefaultSqlSession。
使用要求: SqlSession对象不是线程安全的,使用步骤:
- 需要在方法内部使用, 在执行sql语句之前,使用openSession()获取SqlSession对象。
- 调用SqlSession的方法,执行sql语句
- 在执行完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接口方法的形参
- 动态代理: 使用SqlSession.getMapper(dao接口.class) 获取这个dao接口的对象
- 传入参数: 从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
- 多个参数,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会以下面的处理方式:
- mybatis执行sql语句, 然后mybatis调用Student类的无参数构造方法,创建对象(使用反射机制)。
- mybatis把ResultSet指定列值付给同名的属性(所以创建类的时候要使属性值和列名一样)。
student.setId(rs.getInt(“id”)) - 得到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的一些片段