操作数据库,在之前我们使用的是JDBC,
jdbc优势:
1.操作简单,容易理解。
2.操作性能最佳,因为其他框架都是基于JDBC来实现的,所以在更多配置和更多代码时会有一定的性能牺牲掉。
JDBC劣势:
1.如果我们要实现一个复杂的数据库操作的时候需要编写大量代码才能实现业务,如果需要使用事务则会更复杂。
2.不能快速实现更好的共用型。
3.实现更多配置时需要复杂的硬编码才能实现。
MyBatis框架:开源,免费,轻量级(依赖较少)
在之前servlet时,dao层就是操作数据库的,那么我们的Mybatis封装的就是jdbc模板代码。
优点:
1.可以将一行数据缝扎黄为一个实体类对象
2.sql语句外部化,参数传递外部化
MyBatis使用步骤
1.导包,在项目上创建lib文件夹,将依赖放入,并bulidpath
2.准备工作:创建数据库和实体类(实体类属性对应数据库字段)
3.创建并编写mybatis的配置文件,创建位置在src下,文件名mybatis-config.xml(需要下载文档约束)
文档约束
<?xml version="1.0" encoding="UTF-8"?>
<!-- 约束信息 -->
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
4.创建映射文件(表和实体类的映射关系 xxxMapper.xml )注意:将映射文件添加到配置文件中
注意:
将mapper文件映射为接口需要满足
1.接口名必须和mapper文件名一致
2.接口路径必须和mapper文件一致
3.mapper文件中namespace必须是接口完整路径
4.增删改查标签中id指必须映射为接口中的方法名
<?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">
5.测试
那么在mybatis-config.xml中
<?xml version="1.0" encoding="UTF-8"?>
<!-- 约束信息 -->
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<!-- 配置信息 -->
<configuration>
<!-- 将共有属性提取到properties标签中 -->
<properties>
<!--设置属性-->
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/stu" />
<property name="username" value="jf" />
<property name="password" value="121" />
</properties>
<!-- mybatis日志功能 -->
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"></setting>
<!-- 在配置文件中开启二级缓存 -->
<setting name="cacheEnabled" value="true"/>
</settings>
<!--别名设置,方便我们对返回值类型的引用-->
<typeAliases>
<!--单一修改-->
<typeAlias type="具体的实体类" alias="别名" />
<!--批量修改,别名统一为类名小写-->
<package name="实体类所在的包"/>
</typeAliases>
<!--数据库环境,可以配置多种数据库,默认指定一种-->
<environments default="mysql">
<!--某一种数据库的环境信息-->
<environments id="mysql">
<!--事务管理器-->
<transactionManager type="JDBC" />
<!-- 连接池信息 -->
<dataSource type="POOLED">
<!-- 设置属性 值用EL表达式获取-->
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<!--配置映射文件-->
<mappers>
<mapper resource="映射文件的包全路径">
</mappers>
</configuration>
缓存:
一级缓存:
mybatis默认开启的
作用范围:一个SqlSession
开启:openSession
结束:close(),clearCache(),执行增删改
二级缓存:
作用范围:一个mapper
配置:
1.在配置文件中的settings标签中添加:
<sessting name="cacheEnable" value="true"/>
2.在所需的映射文件中添加:
<cache/>
3.在所需映射文件对应的实体类实现序列化
implements Serialzable
映射文件中所有的select语句将被缓存
映射文件中所有的insert、update和delete语句将刷新缓存
编写配置文件后要在src下编写映射文件,对应到dao层接口
<?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">
<!--namespace名称空间对应到dao接口-->
<mapper namespace="dao层接口路径">
<!-- 对该映射文件开启二级缓存 -->
<cache type="org.mybatis.caches.ehcache.LoggingEhcache"/>
<!-- <cache/> -->
<!-- 结果集映射 type:对应的实体类 id:唯一标识-->
<resultMap type="com.mybatis.day05.Stu_s1" id="stu_s1_mapper">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="age" property="age"/>
</resultMap>
<!-- select 操作 id:唯一标识,映射为对应的方法
resultmap:定义的结果集映射
paramtertype:传递的参数类型
-->
<select id="select1" resultMap="stu_s1_mapper" parameterType="list">
select * from stu
<!-- 智能判断是否加where -->
<where>
<!-- 简单的if判断是否传入值 -->
<if test="list != null and list.size() != 0">
<!-- foreach迭代 多用在in条件中
item:每一个元素的别名 separator:每个元素以什么分割
open:以什么开始 close:以什么结尾
collection:传入的参数类型
如果是数组则写为:array
如果是集合则写为:list
-->
<foreach collection="list" item="myid" open=" id in (" separator="," close=")">
#{myid}
</foreach>
</if>
</where>
</select>
<select id="select2" resultMap="stu_s1_mapper" parameterType="Integer">
select * from stu
<where>
<if test="array != null and array.length != 0">
<foreach collection="array" item="myid" open=" id in (" separator="," close=")">
#{myid}
</foreach>
</if>
</where>
</select>
<!-- update操作 -->
<update id="update">
update stu
<set>
<if test="name != null">
name = #{name},
</if>
<if test="age != null">
age = #{age},
</if>
</set>
<where>
id = #{id}
</where>
</update>
</mapper>
动态sql:
可以方便的在sql语句中实现某些简单的逻辑判断
1.if语句(简单的条件判断)
2.choose(when otherwise),相当于java语言的switch,与jstl中的choose很像
3.trim(对包含内容加上prefix前缀,suffix后缀)
4.where(主要用来简化sql语句中where条件判断,能职能的处理and|or不必担心多余导致语法错误)
5.set(用于数据更新时,会处理掉最后一个语句末尾的“,”)
6.foreach(在条件查询时的in处理中)
foreach可以在sql语句中进行迭代一个集合
foreach元素的属性主要有item,index,collection,open,separator,close
item:迭代时的每一个元素的别名 index:指定一个名字,表示在迭代过程中,每次迭代到的位置
open:该语句以什么开始 separato:表示每次进行迭代之间以什么符号作为分隔符 close:表示以什么结束
collection:根据传入参数的类型 值为别名(内置)
测试:使用mybatis读取配置文件并执行sql
//读取配置文件
InputStream ips = Resources.getResourceAsStream("mybatis-config.xml");
//创建会话工厂
SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(ips);
//开启会话
SqlSession ss = ssf.openSession();
//直接获取接口对象
xxxMapper xx = ss.xxxMethod(xxxMapper.class);
要执行哪个方法调用对应的方法即可。
这里说一下缓存
一级缓存
<select id="select2" resultMap="stu_s1_mapper" parameterType="Integer"> select * from stu <where> <if test="array != null and array.length != 0"> <foreach collection="array" item="myid" open=" id in (" separator="," close=")"> #{myid} </foreach> </if> </where> </select>
//传入一个空数组
//创建数组 int[] array = null; //调用方法 List<XXX> ls = xx.select2(array); /* * 结束一个sqlSession缓存 * close() clearCache() 执行增删改操作 */ //执行clearCache()会结束一个sqlSESSION的缓存 //ss.clearCache(); /** 执行增删改操作 */ Stu_s1 ss1 = new Stu_s1(); ss1.setName("小儿"); ss1.setAge(26); ss1.setId(2); int row = sm.update(ss1); //执行增删改操作后关闭了一级缓存 int[] array1 = null; List<Stu_s1> ls1 = sm.select2(array1); System.out.println("一个SQLSESSION中两次查询比对:"+ls1.equals(ls)); /* * 结果为true * 在一个sqlSession中默认开启了缓存 * 第二次查询从缓存中拿到数据, * 并没有执行sql * */ //提交 //关流 ss.close();
二级缓存
作用范围一个mapper
配置
1.在配置文件的settings标签中添加:<setting name="cacheEnabled" value="true"/>
2.在所需的映射文件中添加<cache/>
*3.在所需映射文件对应的实体类实现序列化 implements Serializable
//创建数组
int[] array1 = null;
//调用方法
List<Stu_s1> ls1 = sm1.select2(array1);
System.out.println(ls1);
//提交
//关流
ss1.close();
//开启会话2
SqlSession ss2 = ssf.openSession();
//值接获取接口对象
Stu_s1_mapper sm2 = ss2.getMapper(Stu_s1_mapper.class);
//创建数组
int[] array2 = null;
//调用方法
List<Stu_s1> ls2 = sm2.select2(array2);
System.out.println(ls2==ls1);
//提交
//ss2.commit();
//关流
ss2.close();
}