mybatis概述:
框架:框架的重要性在于它实现了部分功能,并且能够很好的将低层应用平台和高层业务逻辑进行了缓和。为了实现软件工程中的“高内聚、低耦合”。把问题划分开来各个解决,易于控制,易于延展,易于分配资源。我们常见的 MVC 软件设计思想就是很好的分层思想。
mybatis:mybatis是一个优秀的基于 java 的持久层框架,它内部封装了 jdbc,使开发者只需要关注 sql语句本身, 而不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程。 mybatis通过xml 或注解的方式将要执行的各种statement配置起来,并通过java对象和statement 中 sql 的动态参数进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行 sql 并将结果映射为 java 对象并 返回。 采用 ORM 思想解决了实体和数据库映射的问题,对 jdbc进行了封装,屏蔽了 jdbc api 底层访问细节,使我 们不用与 jdbc api 打交道,就可以完成对数据库的持久化操作。
mybatis的使用
- mybatis下载
mybatis下载地址
将下面的 dependency 代码置于使用 Maven 构建项目的 pom.xml 文件中,完成jar包导入
- 在工程中导好相应jar包后
在resource目录下编写SqlMapConfig文件
<?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>
<typeAliases>
<package name="cn.tu.domain"></package>
</typeAliases>
<!--配置环境-->
<environments default="mysql">
<!--配置mysql环境-->
<environment id="mysql">
<!--配置事务类型-->
<transactionManager type="JDBC"></transactionManager>
<!--配置连接池-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/mybatisd"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</dataSource>
</environment>
</environments>
<!--配置映射文件位置-->
<mappers>
<!-- <mapper resource="cn/tu/dao/UserDao.xml"></mapper>
<mapper resource="cn/tu/dao/AccountDao.xml"></mapper>-->
<package name="cn.tu.dao"></package>
</mappers>
</configuration>
使用mybatis的步骤:
//获取配置文件的字节输入流
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
//创建sqlSessionFactory工厂对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
//生产sqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//获取代理对象
UserDao dao = sqlSession.getMapper(UserDao.class);
//使用dao里的方法完成操作
List<User> list = dao.findAll();
mybatis中的curd操作
查询操作:
通过配置文件完成:
<select id="findAll" resultMap="userMap">
select * from user
</select>
通过注解完成:
@Select("select * from user")
//通过@result可以指定一对多 多对多之间的结果的映射关系
@Results(id = "userMap",value = {
@Result(id = true,property = "id",column = "id"),
@Result(property = "username",column = "username"),
@Result(property = "sex",column = "sex"),
@Result(property = "address",column = "address"),
@Result(property = "birthday",column = "birthday"),
@Result(property = "accounts", column = "id", many=@Many(select = "cn.tu.dao.AccountDao.findByUid",fetchType = FetchType.LAZY))
})
插入操作
通过配置文件完成
<insert id="saveUser" parameterType="user">
<!--通过selecKey 标签返回执行插入后的结果-->
<selectKey keyProperty="userId" keyColumn="id" resultType="int" order="AFTER">
select last_insert_id();
</selectKey>
insert into user(username,birthday,sex,address)
values (#{userName},#{userBirthday},#{userSex},#{userAddress});
</insert>
通过注解完成
@Insert("insert into user(username,sex,address,birthday) values(#{username},#{sex},#{address},#{birthday})")
删除操作
通过配置文件完成
<delete id="deleteUser" parameterType="java.lang.Integer">
delete from user where id = #{uid};
</delete>
通过注解完成
@Delete("delete from user where id = #{id} ")
修改操作
通过配置文件完成
<update id="updateUser" parameterType="user">
update user set username=#{userName},birthday=#{userBirthday},sex=#{userSex},address=#{userAddress} where id = #{userId};
</update>
通过注解完成
@Update("update user set username=#{username},sex=#{sex},birthday=#{birthday},address=#{address} where id=#{id}")
根据QueryVo查询一个集合的用户
<!--根据QueryVo查询用户-->
<select id="findUserByQueryVo" resultMap="userMap" parameterType="cn.tu.domain.QueryVo">
<include refid="select"></include>
<where>
<foreach collection="ids" open=" and id in (" close=")" separator="," item="id">
#{id}
</foreach>
</where>
</select>
QueryVo的定义
public class QueryVo {
List<Integer> ids;
public List<Integer> getIds() {
return ids;
}
public void setIds(List<Integer> ids) {
this.ids = ids;
}
}
mybatis中的延迟加载:
延迟加载:真正使用数据时才发起查询,不用的时候不查询,按需加载(懒加载)
立即加载:不管用不用,只要一调用方法,马上发起加载
在四种表关系中:
一对多,多对多:通常使用延迟加载
多对一,一对一:通常使用立即加载
延迟加载的使用:
在mybatis中配置
<!--配置参数-->
<settings>
<!--配置延迟加载-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--配置立即加载-->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
配置前执行:一次查询执行了三条sql语句
配置后执行:一次查询只执行了一条sql语句,当需要使用时再调用其他sql语句
mybatis中的一级缓存和二级缓存
- 一级缓存:存在于SqlSession对象中,SqlSession被释放时,缓存也就消失了。当我们执行查询时,查询结果会同时存入到SQLSession为我们提供的区域中。该区域的结构是一个Map,当我们下次执行查询,会先查看该区域中是否存在相应数据,如果没有就执行查询,如果有就直接调用。
- 在执行增、删、改操作后,会清空一级缓存
测试代码
List<User> user1 = userDao.findAll();
System.out.println(user1);
UserDao userDao1 = sqlSession.getMapper(UserDao.class);
List<User> user2 = userDao1.findAll();
System.out.println(user2);
System.out.println(user1==user2);
结果:
- 二级缓存:存在于SqlSessionFactory中,存储的是查询结果的数据(不是对象)
- 使用二级缓存的步骤:
- 让mybatis支持二级缓存(在SqlMapConfig中配置)
<settings>
<!--配置二级缓存-->
<setting name="cacheEnabled" value="true"></setting>
- 让当前映射文件支持二级缓存(在UserDao.xml中配置)
<cache/>
- 让当前操作支持二级缓存(在select标签中配置)
<!--查询所有-->
<select id="findAll" resultMap="userAccountMap" useCache="true">
select * from user ;
</select>
测试
List<User> user1 = userDao.findAll();
System.out.println(user1);
sqlSession.close();
sqlSession = factory.openSession();
UserDao userDao1 = sqlSession.getMapper(UserDao.class);
List<User> user2 = userDao1.findAll();
System.out.println(user2);
System.out.println(user1==user2);
返回false的主要原因是:二级缓存中存放的是数据而不是对象!!!
基于注解开发的二级缓存,只需要在相应的接口中添加
@CacheNamespace(blocking = true)