MyBatis本是apache的一个开源项目iBatis,2010年这个项目由apachesoftware foundation迁移到了google code,并且改名为MyBatis 。2013年11日转移到Github。
可以看作是jdbc的一个高级封装
减轻使用JDBC的复杂性,不用编写重复的创建Connetion ,Statement ;不用编写关闭资源代码。
直接使用java对象,表示结果数据。让开发者专注SQL的处理。其他分心的工作由MyBatis代劳。
SQL写在XML里,解除sql与程序代码的耦合,便于统一管理;提供XML标签,支持编写动态SQL语句,并可重用。
提供映射标签,支持对象与数据库的ORM字段关系映射;提供对象关系映射标签,支持对象关系组件维护。
org.mybatis
mybatis
3.5.1
mysql
mysql-connector-java
5.1.46
src/main/java
**/*.properties
**/*.xml
false
Mybatis框架推荐是把sql语句和java代码分开
推荐mapper文件:定义和dao接口在同一目录下,并且名字和dao接口的名字一致,一个表对应一个mappper文件
mapper文件内部主要介绍:
mapper文件中直接写sql语句即可
表示查询操作,里面是select语句
id:要执行的sql语句的唯一标识,是一个自定义宁符串。推荐使用dao接口中的方法名称
resultType:告诉mybatis,执行sql语句,把数据赋值给哪个类型的java对象。
resultType的值现在使用的java对象的全限定名称
1)定义创建连接实例的数据源对象(DataSource)
2)引入mapper文件
public class TestFindOne {
public static void main(String[] args) throws IOException {
//mybatis核心类
//1 定义mybatis配置文件的位置,从类路径开始的相对路径
String config="mybatis.xml";
//2 读取主配置文件,使用mybatis中的Resources类
InputStream inputStream = Resources.getResourceAsStream(config);
//3 创建SqlSessionFactory对象,使用SqlSessionFactoryBuilder类
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
//4 获取SqlSession对象
SqlSession sqlSession = factory.openSession();
//5 指定要执行的sql语句的id
//sql的id= namespace+"."+select等标签内的id属性值
String sqlId="com.zhiyou.mybatis.dao.StudentDao"+"."+"findStudentById";
//6 通过sqlSession的方法执行sql语句
Student student=sqlSession.selectOne(sqlId);
System.out.println(student);
//7 关闭sqlSession
sqlSession.close();
}
}
设置日志,运行代码时可以看到sql语句和sql的执行结果
mybatis默认执行sql语句是手动提交事务,在 insetrt update delete 操作后要手动进行事务的提交
方式1:手动提交
方式2:创建sqlsession对象时,设置自动提交
首先设置mapper的文件模板
同样主配置文件的模板也是这样创建的
创建工具类,新创建一个包util,然后再在包里创建一个类
代理技术:由mybatis创建dao接口的实现类Proxy(DaoImpl)
使用框架创建的实现类代替你自己手动创建的实现类的功能,不用开发人员写dao接口的实现类
使用要求:mapper标签中的namespace必须设置为dao的全限定名称
标签内的id 必须为dao接口中的方法名称
使用sqlSession对象的方法getmapper(dao.class)
使用代理模式后,在主配置文件中引入mapper文件的方式可以用以下方式
直接写mapper文件所在的包的全限定名称,但是必须要求mapper文件的名字和mapper接口名字一致
1 Resource:mybatis框架中的对象,一个作用就是读取配置文件的信息
2 SqlSessionFactoryBuilder:负责创建SqlSessionFatory对象
3 SqlSessionFatory:它的对象是一个重要的对象
它是一个重量级的对象,创建此对象需要更多的时间和资源。因此在项目中有一个就够了
其实它是一个接口:作用是SqlFactory的工厂,就是创建SqlSession对象
他的真正实现类是DefaultSqlSessionFactory
SqlSessionFatory的方法
OpenSession()获取一个默认的SqlSession对象,默认是需要手动提交事务的
OpenSession(boolean)boolean参数表示是否需要自动提交
True 为自动提交,false为手动提交
4 SqlSession对象 :是通过SqlSessionFatory获取的,SqlSession本身就是一个接口
DefaultSqlSession:实现类
SqlSession作用是提供了大量的执行sql语句的方法
表示参数的类型,指dao方法的形参数据类型。这个参数的数据类型是给mybatis使用,mybatis在给sql语句的参数赋值时使用。
第一个用法:Java类型的全限定名称 paramType="java.lang.Integer"
第二个用法:mybatis定义的java类型的别名 paramType="int"
paramType:mybatis可通过反射机制获取dao接口方法参数的类型,可以不写
方式1:需要使用 @Param:命名参数,在方法的形参前面使用,定义参数名,这个名称可以用在mapper文件中
一个Java对象作为方法的参数时,使用该对象的属性作为参数值使用
简单的语法:#{ 属性名}
Mybatis内部是这样工作的: 他会去调用此属性的getXxx()方法获取属性值
mybatis的占位符有 #{} 和 ${} 两种
#{} 语法:#{字符}
Mybatis处理 #{ } 占位符使用的对象是PrepareStatement对象
#{}占位符处理后的sql语句为: insert into student values (?,?,?,?,?)
特点:
${} 语法:${字符}
${}表示字符串连接,把sql语句的其他内容和${}内容使用字符串(+)连接方式连在一起
特点
1)使用Statement对象,执行sql语句,效率低
2)${}占位符的值,使用的字符串连接方式,有sql注入的风险。有代码安全的问题
3)${}数据是原样使用的,不会区分数据类型。
4)${}常用作表名或者列名,在能保证数据安全的情况下使用${}
Ps:使用该占位符时 1 方法形参处要用@Param注解 2 如果传参为字符串类型的数据时要手动加上引号
主要有resultType和resultMap两个
resultType属性:在执行select时使用,作为
1) java 的全限定名称
resultType :现在使用java类型的全限定名称。表示的意思mybatis执行sq1,把ResultSet中的数据转为student类型的对象。 mybatis会做以下操作: 1.调用com.zhiyou.mybatis.entity.Student的无参数构造方法,创建对象。 Student student = new student(); //使用反射创建对象 2.同名的列赋值给同名的属性。 student.setId( rs.getInt("id")); student.setName(rs.getString("name")); 3.得到iava对象,如果dao接口返回值是List集合,mybatis把student对象放入到List集合。 所以执行Student mystudent = dao.selectById(1001);得到数据库中 id=1001这行数据, 这行数据的列值,赋给了mystudent对象的属性。你能得到mystudent对象。就相当于是id=1001这行数据。 |
2)使用别名
mybatis提供的对java类型定义简短,好记名称。
自定义别名的步骤:
1) 在mybatis主配置文件,使用typeAliase标签声明别名
2)在mapper文件中, resultType="别名"
也可以使用
常用于列名和属性不同的情况,列名和属性名相同也可以使用
现有两张表,学生表和班级表,学生表与班级表的对应关系是多个学生对应一个班级,或者也可以说一个学生对应一个班级
实体类
方式1:类似子查询方式
方式2:联合查询方式
现有两张表,班级表和学生表,一个班级可以对应多个学生,因此结果集需要映射封装
实体类
方式1 类似子查询方式
方式2 联合查询方式
什么是动态sql:同一个dao方法,根据不同的条件可以表示不同的sql语句,主要是where部分有变化,使用mybatis提供的标签,实现动态sql的能力,主要讲if,where,foreach,sql
语法如下:
使用if标签时,容易引起sql语句语法错误。使用where标签解决if产生的语法问题。
使用where时 ,里面是一个或多个if标签,当有一个if标签判断条件为true,where标签会转为WHERE关键字附加到sql语句的后面。如果if 没有一个条件为true ,忽略where和里面的if
语法格式:
使用foreach可以遍历集合和数组,一般用在in语句中
用于更新操作,可以自动判断是否去除最后一个逗号
update student
sname=#{sname},
sex=#{sex},
score=#{score},
sdy=#{sdy},
where sid = #{sid}
sql标签标示一段sql代码,可以是表名,几个字段, where条件都可以,可以在其他地方复用sql标签的内容。
使用方式:
2)在其他的位置,使用include标签引用某个代码片段
当对数据库进行查询时 如果两次的sql语句一致 不再重复去服务数据库 直接使用上一次的查询结果
作用:提高程序效率+降低数据库服务器的压力
Mybatis对缓存提供支持,但是在没有配置的默认情况下,它只开启一级缓存,一级缓存只是相对于同一个SqlSession而言。
所以在参数和SQL完全一样的情况下,我们使用同一个SqlSession对象调用一个Mapper方法,往往只执行一次SQL,因为使用SelSession第一次查询后,MyBatis会将其放在缓存中,以后再查询的时候,如果没有声明需要刷新的情况下,SqlSession都会取出当前缓存的数据,而不会再次发送SQL到数据库。
一级缓存默认是开启的
一级缓存针对于同一个sqSession
一级缓存使用前提:缓存不能刷新
期间不能执行dml
一级缓存生命周期
a、MyBatis在开启一个数据库会话时,会 创建一个新的SqlSession对象,SqlSession对象中会有一个新的Executor对象。Executor对象中持有一个新的PerpetualCache对象;当会话结束时,SqlSession对象及其内部的Executor对象还有PerpetualCache对象也一并释放掉。
b、如果SqlSession调用了close()方法,会释放掉一级缓存PerpetualCache对象,一级缓存将不可用。
c、如果SqlSession调用了clearCache(),会清空PerpetualCache对象中的数据,但是该对象仍可使用。
d、SqlSession中执行了任何一个update操作(update()、delete()、insert()) ,都会清空PerpetualCache对象的数据,但是该对象可以继续使用
二级缓存是application级别的缓存/SqlSessionFactory级别的缓存
mybatis的二级缓存默认是关闭的
二级缓存的数据会存储在硬盘上
在使用缓存的mapper映射文件中添加配置
在使用缓存的mapper映射文件的sql标签中添加配置:(默认是true:可以不用配置)
在核心配置文件中添加配置
....