Mybatis总结

Mybatis总结

mybatis基础

1、mybatis:解决数据持久化问题的框架

2、mybatis是基于java的持久层框架,它内部封装了jdbc,使开发者只需要关注sql语句的编写,无需关注加载驱动,创建链接,创建statement等过程

3、采用ORM的思想实现javabean和数据库的映射

4、映射配置xml文件目录结构和持久层接口目录结构和名称相同(不需要写持久层接口的实现类)

添加依赖:

<dependencies>
 <dependency>
 <groupId>org.mybatis</groupId>
 <artifactId>mybatis</artifactId>
 <version>3.4.5</version>
 </dependency>
 <dependency>
 <groupId>junit</groupId>
 <artifactId>junit</artifactId>
 <version>4.10</version>
 <scope>test</scope>
 </dependency>
 <!-- mysql驱动-->
 <dependency>
 <groupId>mysql</groupId>
 <artifactId>mysql-connector-java</artifactId>
 <version>5.1.6</version>
 <scope>runtime</scope>
 </dependency>
 <dependency>
 <groupId>log4j</groupId>
 <artifactId>log4j</artifactId>
 <version>1.2.12</version>
 </dependency>
 </dependencies>

编写映射配置文件

<?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">
<mapper namespace="com.wfq.dao.IUserDao">
<!-- 配置查询所有操作 -->
<select id="findAll" resultType="com.wfq.domain.User">
select * from user
</select>

5、编写 SqlMapConfig.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>
<!-- 配置 mybatis 的环境 -->
<environments default="mysql">
<!-- 配置 mysql 的环境 -->
<environment id="mysql">
<!-- 配置事务的类型 -->
<transactionManager type="JDBC"></transactionManager>
<!-- 配置连接数据库的信息:用的是数据源(连接池) -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="1234"/>
</dataSource>
</environment>
</environments>
<!-- 告知 mybatis 映射配置的位置 -->
<mappers>
<mapper resource="com/wfq/dao/IUserDao.xml"/>
</mappers>
    <!--注解配置-->
 <mappers>
<mapper class="com.wfq.dao.IUserDao"/>
</mappers>
</configuration>

6、测试类:

//1.读取配置文件
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建 SqlSessionFactory 的构建者对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//3.使用构建者创建工厂对象 SqlSessionFactory
SqlSessionFactory factory = builder.build(in);
//4.使用 SqlSessionFactory 生产 SqlSession 对象
SqlSession session = factory.openSession();
//5.使用 SqlSession 创建 dao 接口的代理对象
IUserDao userDao = session.getMapper(IUserDao.class);
//6.使用代理对象执行查询所有方法
List<User> users = userDao.findAll();
for(User user : users) {
System.out.println(user);
}
//7.释放资源
session.close();
in.close();
}

sql 语句中使用#{}字符: 它代表占位符,相当于原来 jdbc 部分所学的?,都是用于执行语句时替换实际的数据。 具体的数据是由#{}里面的内容决定的。 #{}中内容的写法: 由于数据类型是基本类型,所以此处可以随意写

新增用户后,同时还要返回当前新增用户的 id 值,因为 id 是由数据库的自动增长来实现的,所以就相 当于我们要在新增后将自动增长

<inster id="saveUser" parameterType="USER">
    <selectKey keyColumn="id" keyProperty="id" resultType="int">
        select last_inssrt_id();
    </selectKey>
    insert into user(username,birthday,sex,address) 
    values(#{username},#{birthday},#{sex},#{address})
</inster>    

聚合查询总数

<select id="findTotal" resultType="int">
select count(*) from user;
</select>

表列名和实体类属性名称不一致

type 属性:指定实体类的全限定类名
id 属性:给定一个唯一标识,是给查询 select 标签引用用的。
-->
<resultMap type="com.wfq.domain.User" id="userMap">
<id column="id" property="userId"/>
<result column="username" property="userName"/>
<result column="sex" property="userSex"/>
<result column="address" property="userAddress"/>
<result column="birthday" property="userBirthday"/>
</resultMap>
id 标签:用于指定主键字段
result 标签:用于指定非主键字段
column 属性:用于指定数据库列名
property 属性:用于指定实体类属性名称

SqlMapConfig.xml 中配置的内容和顺序

-properties(属性)
--property
-settings(全局配置参数)
--setting
-typeAliases(类型别名)
--typeAliase
--package
-typeHandlers(类型处理器)
-objectFactory(对象工厂)
-plugins(插件)
-environments(环境集合属性对象)
--environment(环境子属性对象)
---transactionManager(事务管理)
---dataSource(数据源)
-mappers(映射器)
--mapper
--package

可以使用properties标签抽出数据库的链接信息

<!-- 配置连接数据库的信息resource 属性:用于指定 properties 配置文件的位置,要求配置文件必须在类路径下resource="jdbcConfig.properties"url 属性:URL: Uniform Resource Locator 统一资源定位符http://localhost:8080/mystroe/CategoryServlet URL协议 主机 端口 URIURI:Uniform Resource Identifier 统一资源标识符/mystroe/CategoryServlet它是可以在 web 应用中唯一定位一个资源的路径--><properties url=file:///D:/IdeaProjects/resources/jdbcConfig.properties"></properties>

自定义别名

<typeAliases><!-- 单个别名定义 --><typeAlias alias="user" type="com.wfq.domain.User"/><!-- 批量别名定义,扫描整个包下的类,别名为类名(首字母大写或小写都可以) --><package name="com.wfq.domain"/><package name="其它包"/></typeAliases>
注册指定包下的所有 mapper 接口如:<package name="cn.itcast.mybatis.mapper"/>注意:此种方法要求 mapper 接口名称和 mapper 映射文件名称相同,且放在同一个目录中。

mybatis连接池与事务深入

mybatis采用的是自己的连接池技术,在 Mybatis 的 SqlMapConfig.xml 配置文件中,通过来实 现 Mybatis 中连接池的配置来配置连接池

mybatis中我们将它的数据源datasource分为三类:unpooled,pooled,jndi(使用jndi实现的数据源),

相应地,MyBatis 内部分别定义了实现了 java.sql.DataSource 接口的 UnpooledDataSource, PooledDataSource 类来表示 UNPOOLED、POOLED 类型的数据源,pooleddatasource持有一个unpooleddatasource的引用,当需要创建一个Connection实例对象时,还通过unpooleddatasource来创建,pooleddatasource只提供一种缓存链接池机制

MyBatis 在初始化时,根据的 type 属性来创建相应类型的的数据源 DataSource,即: type=”POOLED”:MyBatis 会创建 PooledDataSource; 实例 type=”UNPOOLED” : MyBatis 会创建 UnpooledDataSource 实例 ;type=”JNDI”:MyBatis 会从 JNDI 服务上查找 DataSource 实例,然后返回使用

mybatis中当执行sql语句的时候才会去调用datasource对象来创建java.sql.connection对象(可通过断点调试代码得知)

Mybatis 框架因为是对 JDBC 的封装,所以 Mybatis 框架的事务控制方式,本身也是用 JDBC 的 setAutoCommit()方法来设置事务提交方式的。

CUD 过程中必须使用 sqlSession.commit()提交事 务,主要原因就是在连接池中取出的连接,都会将调用 connection.setAutoCommit(false)方法,这样我们 就必须使用 sqlSession.commit()方法,相当于使用了 JDBC 中的 connection.commit()方法实现事务提 交。/也可以在创建 SqlSession 对象 session = factory.openSession(true)来设置自动提交;

mybatis中的动态sql

标签

<select id="findByUser" resultType="user" parameterType="user">select * from user where 1=1<if test="username!=null and username != '' ">and username like #{username}</if><if test="address != null">and address like #{address}</if></select>注意:<if>标签的 test 属性中写的是对象的属性名,如果是包装类的对象要使用 OGNL 表达式的写法。另外要注意 where 1=1 的作用~!
<!-- 根据用户信息查询  可以用where标签来简化 where 1=1--><select id="findByUser" resultType="user" parameterType="user"><include refid="defaultSql"></include><where><if test="username!=null and username != '' ">and username like #{username}</if><if test="address != null">and address like #{address}</if></where></select>

标签

传入多个 id 查询用户信息,用下边两个 sql 实现: SELECT * FROM USERS WHERE username LIKE '%张%' AND (id =10 OR id =89 OR id=16) SELECT * FROM USERS WHERE username LIKE '%张%' AND id IN (10,89,16) 这样我们在进行范围查询时,就要将一个集合中的值,作为参数动态添加进来。

<!-- 查询所有用户在 id 的集合之中 --><select id="findInIds" resultType="user" parameterType="queryvo"><!-- select * from user where id in (1,2,3,4,5); --><include refid="defaultSql"></include><where><if test="ids != null and ids.size() > 0"><foreach collection="ids" open="id in ( " close=")" item="uid" separator=",">#{uid}</foreach></if></where></select>SQL 语句:select 字段 from user where id in (?)<foreach>标签用于遍历集合,它的属性:collection:代表要遍历的集合元素,注意编写时不要写#{}open:代表语句的开始部分

Sql 中可将重复的 sql 提取出来,使用时用 include 引用即可,最终达到 sql 重用的目的。

<!-- 抽取重复的语句代码片段 --><sql id="defaultSql">select * from user</sql>

mybatis中多表查询(一对一,一对多,多对多)

账户表和用户表,主要时返回实体类不同,一种方式可以写一个类继承账户类,令一种是在账户类中声明用户变量,

<?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"><mapper namespace="com.wfq.dao.IAccountDao"><!-- 建立对应关系 --><resultMap type="account" id="accountMap"><id column="aid" property="id"/><result column="uid" property="uid"/><result column="money" property="money"/><!-- 它是用于指定从表方的引用实体属性的 --><association property="user" javaType="user"><id column="id" property="id"/><result column="username" property="username"/><result column="sex" property="sex"/><result column="birthday" property="birthday"/><result column="address" property="address"/></association></resultMap><select id="findAll" resultMap="accountMap">select u.*,a.id as aid,a.uid,a.money from account a,user u where a.uid =u.id;</select></mapper>

一对多

<?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"><mapper namespace="com.wfq.dao.IUserDao"><resultMap type="user" id="userMap"><id column="id" property="id"></id><result column="username" property="username"/><result column="address" property="address"/><result column="sex" property="sex"/><result column="birthday" property="birthday"/><!-- collection 是用于建立一对多中集合属性的对应关系ofType 用于指定集合元素的数据类型--><collection property="accounts" ofType="account"><id column="aid" property="id"/><result column="uid" property="uid"/><result column="money" property="money"/>

多对多,需要有一张中间表

mybatis中延迟加载策略

实际开发过程中很多时候我们并不需要总是在加载用户信息时就一定要加载他的账户信息。此时就是我们所说的延迟加载,

延迟加载: 就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据。延迟加载也称懒加载. 好处:先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快。坏处: 因为只有当需要用到数据时,才会进行数据库查询,这样在大批量数据查询时,因为查询工作也要消耗 时间,所以可能造成用户等待时间变长,造成用户体验下降。

现多表操作时,使用了resultMap来实现一对一,一对多,多对多关系的操作。主要 是通过 association、collection 实现一对一及一对多映射。association、collection 具备延迟加载功 能。

需要在 Mybatis 的配置文件 SqlMapConfig.xml 文件中添加延迟加载的配置。

<settings>	<setting name="lazyLoadingEnabled" value="true"/>	<setting name="aggressiveLazyLoading" value="false"/></settings>

mybatis缓存

像大多数的持久化框架一样,Mybatis 也提供了缓存策略,通过缓存策略来减少数据库的查询次数,从而提 高性能。

一级缓存是 SqlSession 级别的缓存,只要 SqlSession 没有 flush 或 close,它就存在。两次查询只会执行一次sql,一级缓存是 SqlSession 范围的缓存,当调用 SqlSession 的修改,添加,删除,commit(),close()等方法时,就会清空一级缓存

二级缓存是 mapper(namespace) 映射级别的缓存,多个 SqlSession 去操作同一个 Mapper 映射的 sql 语句,多个 SqlSession 可以共用二级缓存,二级缓存是跨 SqlSession 的。

需要在mybatis的配置文件中开启二级缓存,mybatis中默认为true,可以省略这一步

<settings>	<!-- 开启二级缓存的支持 -->	<setting name="cacheEnabled" value="true"/></settings>

第二步需要在对应的mapper中开启二级缓存,namespace的值为区分标准

<mapper namespace="com.wfq.dao.IUserDao">	<!-- 开启二级缓存的支持 -->	<cache></cache></mapper>

第三步需要在对应的statement上面配置useCache属性

<select id="findById" resultType="user" parameterType="int" useCache="true">	select * from user where id = #{uid}</select>

二级缓存的注意事项:当我们在使用二级缓存时,所缓存的类一定要实现 java.io.Serializable 接口,这种就可以使用序列化方式来保存对象。

mybatis注解开发

mybatis常用注解:

@Insert:实现新增

@Update:实现更新

@Delete:实现删除

@Select:实现查询

@Result:实现结果集封装

@Results:可以与@Result 一起使用,封装多个结果集

@ResultMap:实现引用@Results 定义的封装

@One:实现一对一结果集封装

@Many:实现一对多结果集封装

@SelectProvider: 实现动态 SQL 映射

@CacheNamespace:实现注解二级缓存的使用

posted @ 2021-11-16 20:33  做笔记很重要  阅读(283)  评论(0)    收藏  举报