一.Mybatis的快速入门
1.引入mybatis的坐标,mybatis下载地址:https://github.com/mybatis/mybatis-3
<dependencies> <!--mysql驱动坐标--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.32</version> </dependency> <!--mybatis的核心坐标--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.6</version> </dependency> <!--测试的坐标--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <!--日志功能--> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <!--lombok--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.10</version> </dependency> </dependencies>
2.编写实体类(例子中用User),并且在数据库中建表
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private String username;
private int id;
private String password;
}
Mybatis技术一.Mybatis的快速入门二.MapConfig.xml配置文件和mapper.xml映射文件详细解释:3.动态SQL4.mybatis的缓存 5.MyBatis的逆向工程
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnLjVTO2I2YxUGZ0UjNlJGO4IjNxQTMyAjMkVzY2QjM3czLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
后面还要用到物品表,顺便加上:
3.编写MapConfig.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 resource="jdbc.properties"></properties>
<!--定义别名,注意放置的顺序,不区分大小写,如果不写alias默认别名为类名-->
<typeAliases>
<typeAlias type="com.itheima.domain.User" alias="user"></typeAlias>
</typeAliases>
<!--配置数据源的环境-->
<environments default="development"> <!--目前使用某一个环境-->
<environment id="development"> <!--某一个环境的id-->
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED"> <!--表明数据源使用连接池技术-->
<property name="driver" value="${jdbc.driver}"></property><!--配置数据源-->
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</dataSource>
</environment>
</environments>
<!--加载映射文件-->
<mappers>
<!--mapper接口所在的包要和映射文件所在的包一致-->
<!--mapper要和映射文件的名字一样-->
<mapper resource="com.itheima.mapper\UserMapper.xml"></mapper>
</mappers>
</configuration>
4.编写mapper.xml映射文件和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">
<!--配置映射sql语句,namespace要写全类名-->
<mapper namespace="mapper.Usermapper">
<select id="findUserById" resultType="User">
select * from user where id= #{id}
</select>
</mapper>
import domin.User;
public interface Usermapper {
User findUserById(int id);
}
5.测试代码:
@Test//简单查询
public void test1() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis_config.xml");
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = build.openSession();
Usermapper usermapper = sqlSession.getMapper(Usermapper.class);
User user = usermapper.findUserById(4);
System.out.println(user);
sqlSession.commit();
}
6.【拓展】:reasourses目录下添加log4j.xml的配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
<param name="Encoding" value="UTF-8" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS} %m (%F:%L) \n" />
</layout>
</appender>
<logger name="java.sql">
<level value="debug" />
</logger>
<logger name="org.apache.ibatis">
<level value="info" />
</logger>
<root>
<level value="debug" />
<appender-ref ref="STDOUT" />
</root>
</log4j:configuration>
7.【拓展】封装工具类
public class SqlSessionUtil {
public static SqlSession getSqlSession(){
InputStream resourceAsStream = null;
SqlSession sqlSession=null;
try {
resourceAsStream = Resources.getResourceAsStream("mybatis_config.xml");
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);
sqlSession = build.openSession(true);//自动提交事务
} catch (IOException e) {
e.printStackTrace();
}
return sqlSession;
}
}
二.MapConfig.xml配置文件和mapper.xml映射文件详细解释:
1.MapConfig.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 resource="jdbc.properties"></properties>
<!--定义别名,注意放置的顺序,不区分大小写;如果不写alias默认别名为类名,且不区分大小写-->
<typeAliases>
<typeAlias type="com.itheima.domain.User" alias="user"></typeAlias>
<!--给整个包设置别名 -->
<package name=" com.itheima.domain "></package >
</typeAliases>
<!--配置数据源的环境-->
<environments default="development"><!--使用某一个环境-->
<environment id="development"> <!--某一个环境的id-->
<transactionManager type="JDBC"></transactionManager>
<!--JDBC/MANAGED-->
<!--JDBC:表示使用原生的事务管理方式,事务的提交靠手动 -->
<!--MANAGED:被管理,例如Spring -->
<dataSource type="POOLED"> <!--POOLED/UNPOOLED/JNDI -->
<!--POOLED:表明使用连接池技术-->
<!--UNPOOLED:表明不使用连接池技术-->
<!-- JNDI:表明使用上下文中的数据源-->
<property name="driver" value="${jdbc.driver}"></property><!--配置数据源-->
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</dataSource>
</environment>
</environments>
<!--加载映射文件-->
<mappers>
<mapper resource="com.itheima.mapper\UserMapper.xml"></mapper>
</mappers>
</configuration>
2.mapper.xml
<?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">
<!--1.这个命名空间的名字要和接口的全限定名相同-->
<!--2.id要和接口的方法名字相同-->
<!--3.parameterType要和接口的输入参数类型一样-->
<!--4.resultType要和接口的输出类型一样-->
<mapper namespace="com.itheima.mapper.myMapper">
<!--普通查询操作-->
<select id="search" resultType="user">
select * from user where id=#{id}
</select>
</mapper>
五种传参数方式:
1.单个字面量参数
2.多个字面量参数
3.自定义的map集合
4.实体类型参数
5.加了注解(@Param)的参数
<!--下面是五种传递参数的方式-->
<!--第1种,单个字面量类型的参数:User getUserByUsername(String username)-->
<select id="getUserByUsername" resultType="User">
select * from user where username= #{username} <!--这里#{}里面的id可以随便写,写aaa都行-->
</select>
<!--第2种,多个字面量类型的参数:User getUser(String username,String password);-->
<select id="getUser" resultType="User">
<!--这个是框架进行封装到map集合中,username和password分别封装到arg0和arg1中,或者用param1和param2也能提取到-->
select * from user where username= #{arg0} and password=#{arg1}
</select>
<!--第3种,多个字面量类型的参数:User getUserByMap(Map<String,Object> map);-->
<select id="getUserByMap" resultType="User">
<!--自己创建map集合传进参数里,map.put("usermane","admin");map.put("password","123456");-->
select * from user where username = #{username} and password = #{password}
</select>
<!--第4种,实体类型的参数:User getUserByPojo(User user);-->
<select id="getUserByPojo" resultType="User">
<!--传一个实体类对象,可以将实体类对象的属性取出来-->
select * from user where username = #{username} and password = #{password}
</select>
<!--第5种,使用注解标识方法中的参数:getUserByParam(@Param("username") String username, @Param("password") String password);-->
<!--mapper.getUserByParam("admin","123456");-->
<select id="getUserByParam" resultType="User">
select * from user where username = #{username} and password = #{password}
</select>
@Test
public void test3() throws IOException {
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
Usermapper usermapper = sqlSession.getMapper(Usermapper.class);
//第一种
User user1 = usermapper.getUserByUsername("xueyimeng");
System.out.println(user1);
//第二种
User user2 = usermapper.getUser("xueyimeng","123");
System.out.println(user2);
//第三种
Map<String,Object> map=new HashMap<>();
map.put("username","lisi");
map.put("password","123");
User user3 = usermapper.getUserByMap(map);
System.out.println(user3);
//第四种
User user4 = usermapper.getUserByPojo(new User(4, "xueyimeng", "123"));
System.out.println(user4);
//第五种
User user5 = usermapper.getUserByParam("xueyimeng", "123");
System.out.println(user5);
}
五种返回结果:
1.返回单个对象
2.返回多个对象(实体类的List集合)
3.返回单个数据
4.一条数据返回map集合
5.多条数据返回map集合(map集合的map集合)
<!--第1种 返回值为单个对象:User getUserByUsername(String username)-->
<select id="getUserByUsername" resultType="User">
select * from user where username= #{username}
</select>
<!--第2种 返回对象集合 List<User> getUsers();-->
<select id="getUsers" resultType="User">
select * from user
</select>
<!--第3种 返回单个数据 int getCount();-->
<select id="getCount" resultType="_integer">
select count(id) from user
</select>
<!--第4种 查一条数据返回map集合 Map<String,Object> getUserToMap(@Param("id") int id);-->
<select id="getUserToMap" resultType="map">
select * from user where id=#{id}
</select>
<!--第5种 查多条数据返回map集合 -->
<!--第一种方式 Map<String,Object> Map<String,Object> getUsersToMapOne();-->
<!--一条数据对应一个map;若有多条数据,就会产生多个map集合,此时可以将这些map放在一个list集合中获取-->
<select id="getUsersToMapOne" resultType="map">
select * from user
</select>
<!--第二种方式 @MapKey("id") Map<String,Object> getUsersToMapTwo();-->
<!--相当于在map外面又套了一个map,最外面的map是用id(主键)作为键的-->
<select id="getUsersToMapTwo" resultType="map">
select * from user
</select>
@Test//五种返回结果
public void test4() throws IOException {
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
Usermapper usermapper = sqlSession.getMapper(Usermapper.class);
//第一种 返回一个对象
User user1 = usermapper.getUserByUsername("xueyimeng");
System.out.println(user1);
//第二种 返回对象集合
List<User> users = usermapper.getUsers();
System.out.println(users);
//第三种 返回单个数据
int count = usermapper.getCount();
System.out.println(count);
//第四种 查一条数据返回map集合
Map<String, Object> map = usermapper.getUserToMap(4);
System.out.println(map);
//第五种 查多条数据返回map集合
//5.1
List<Map<String, Object>> mapsOne = usermapper.getUsersToMapOne();
System.out.println(mapsOne);
//5.2
Map<String, Object> mapsTwo = usermapper.getUsersToMapTwo();
System.out.println(mapsTwo);
}
特殊的SQL执行:
1.模糊查询
2.批量删除
3.动态获取表名
4.添加功能获取自增的主键
<!--特殊SQL-->
<!--模糊查询 List<User> getUserByLike(@Param("username") String username);-->
<select id="getUserByLike" resultType="User">
<!--select * from t_user where username like '%${username}%'-->
<!--select * from t_user where username like concat('%',#{username},'%')-->
select * from user where username like "%"#{username}"%"
</select>
<!--批量删除 int deleteMore(@Param("ids") String ids);-->
<delete id="deleteMore" >
delete from user where id in (${ids})
</delete>
<!--动态获取表名 getUserByTable(@Param("tableName") String tableName)-->
<select id="getUserByTable" resultType="User">
select * from ${tableName}
</select>
<!--添加功能获取自增的主键 void insertUser(User user);-->
<!--useGeneratedKeys:设置使用自增的主键;keyProperty:因为增删改有统一的返回值是受影响的行数,
因此只能将获取的自增的主键放在传输的参数user对象的某个属性中-->
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
insert into user values (null,#{username},#{password})
</insert>
@Test//特殊Sql
public void test5() throws IOException {
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
Usermapper usermapper = sqlSession.getMapper(Usermapper.class);
//第一种 模糊查询
List<User> users = usermapper.getUserByLike("梨");
System.out.println(users);
//第二种 批量删除
int count = usermapper.deleteMore("1,2");
System.out.println(count);
//第三种 动态获取表名
List<User> users2 = usermapper.getUserByTable("user");
System.out.println(users2);
//第四种 添加功能获取自增的主键
User user = new User("lisi", "123");
usermapper.insertUser(user);
System.out.println(user);
}
resultMap的映射
1.普通的映射:
<!-- resultMap处理映射 List<Goods> getAllgoods();-->
<resultMap id="AllgoodsMap" type="Goods"><!--type:查询的数据要映射的实体类的类型-->
<id property="id" column="id"></id><!--id:设置主键的映射关系;result:设置普通字段的映射关系-->
<result property="userId" column="user_id"></result><!--property:设置映射关系中实体类中的属性名-->
<result property="name" column="name"></result><!--column:设置映射关系中表中的字段名-->
</resultMap>
<select id="getAllgoods" resultMap="AllgoodsMap">
select * from goods
</select>
@Test//resultMap
public void test6() throws IOException {
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
goodsMapper goodsMapper = sqlSession.getMapper(goodsMapper.class);
List<Goods> allgoods = goodsMapper.getAllgoods();
System.out.println(allgoods);
}
2.多对一映射(物品类里加唯一主人对象,三种解决方式)
@Test//resultMap
public void test6() throws IOException {
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
goodsMapper goodsMapper = sqlSession.getMapper(goodsMapper.class);
List<Goods> allgoodsByMap = goodsMapper.getAllgoodsByMap();
System.out.println(allgoodsByMap);
}
<!--多表联查映射,级联方式处理 List<Goods> getAllgoodsByMap();-->
<resultMap id="jilian" type="Goods">
<id property="id" column="goods_id"></id>
<result property="userId" column="user_id"></result>
<result property="name" column="name"></result>
<result property="user.id" column="user_id"></result>
<result property="user.username" column="username"></result>
<result property="user.password" column="password"></result>
</resultMap>
<select id="getAllgoodsByMap" resultMap="jilian">
SELECT *,goods.`id` goods_id FROM goods,USER WHERE goods.`user_id`=user.`id`
</select>
<!--多表联查映射,association方式处理 List<Goods> getAllgoodsByMap();-->
<resultMap id="jilian" type="Goods">
<id property="id" column="goods_id"></id>
<result property="userId" column="user_id"></result>
<result property="name" column="name"></result>
<association property="user" javaType="User">
<!--association:处理多对一的映射关系;property:需要处理多对的映射关系的属性名;javaType:该属性的类型-->
<id property="id" column="user_id"></id>
<result property="username" column="username"></result>
<result property="password" column="password"></result>
</association>
</resultMap>
<select id="getAllgoodsByMap" resultMap="jilian">
SELECT *,goods.`id` goods_id FROM goods,USER WHERE goods.`user_id`=user.`id`
</select>
<!--多表联查,第一步就是根据物品的id查物品的信息多表分步联查 Goods getGoodsAndUserByStepOne(@Param("id") Integer id);-->
<resultMap id="StepOnetest" type="Goods">
<id property="id" column="id"></id><!--id:设置主键的映射关系;result:设置普通字段的映射关系-->
<result property="userId" column="user_id"></result><!--property:设置映射关系中实体类中的属性名-->
<result property="name" column="name"></result><!--column:设置映射关系中表中的字段名-->
<!--select:设置分布查询的sql的唯一标识(namespace.SQLId或mapper接口的全类名.方法名)-->
<!--column:设置分步查询的条件,将查到的物品对应的使用者id的字段名填进第二个方法的参数里-->
<association property="user"
select="mapper.goodsMapper.getGoodsAndUserByStepTwo"
column="user_id" ></association>
</resultMap>
<select id="getGoodsAndUserByStepOne" resultMap="StepOnetest">
select * from goods where id=#{id}
</select>
<!--多表联查,第二步查物品里的user属性 User getGoodsAndUserByStepTwo(@Param("id") Integer id);-->
<resultMap id="StepTwotest" type="User">
<id property="id" column="id"></id>
<result property="username" column="username"></result>
<result property="password" column="password"></result>
</resultMap>
<select id="getGoodsAndUserByStepTwo" resultMap="StepTwotest">
select * from user where id=#{id}
</select>
3.一对多映射
@Test//一对多映射
public void test6() throws IOException {
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
Usermapper mapper = sqlSession.getMapper(Usermapper.class);
User goodsAndUser = mapper.getGoodsAndUser(5);
System.out.println(goodsAndUser);
}
<!--第一种方式:用collection-->
<resultMap id="GoodsAndUserMap" type="User">
<id property="id" column="user_id"></id>
<result property="username" column="username"></result>
<result property="password" column="password"></result>
<collection property="goodsList" ofType="Goods">
<id property="id" column="goods_id"></id><!--前面的是属性,后面的是数据库字段-->
<result property="userId" column="user_id"></result>
<result property="name" column="name"></result>
</collection>
</resultMap>
<!--User getGoodsAndUser(@Param("id") int id);-->
<select id="getGoodsAndUser" resultMap="GoodsAndUserMap">
SELECT *,goods.`id` goods_id FROM USER,goods WHERE goods.`user_id`=user.`id` AND user.`id`=#{id}
</select>
<!--第2种方式:分布查询,第一步首先根据id查到某个使用者-->
<resultMap id="GoodsAndUserByStepFirstMap" type="User">
<id property="id" column="id"></id>
<result property="username" column="username"></result>
<result property="password" column="password"></result>
<collection property="goodsList"
select="mapper.Usermapper.getGoodsAndUserByStepSecond"
column="id"></collection>
</resultMap>
<!--User getGoodsAndUserByStepFirst(@Param("id") int id);-->
<select id="getGoodsAndUserByStepFirst" resultMap="GoodsAndUserByStepFirstMap">
select * from user where id = #{id}
</select>
<!--第二步,将第一步查到的使用者的id字段值填进第二个sql语句里-->
<!--List<Goods> getGoodsAndUserByStepSecond(@Param("id") int id);-->
<select id="getGoodsAndUserByStepSecond" resultType="Goods">
select * from goods where user_id = #{id}
</select>
延迟加载
3.动态SQL
if:
@Test//动态sql_if
public void test() throws IOException {
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
Usermapper mapper = sqlSession.getMapper(Usermapper.class);
List<User> userByCondition = mapper.getUserByCondition(new User());
System.out.println(userByCondition);
}
<!--if User getUserByCondition(User user);-->
<select id="getUserByCondition" resultType="User"><!--这里的1=1相当于select * from user where 1=1 and id = ? -->
select * from user where 1=1
<if test="username != null and username !=''"><!--通过test属性的表达式进行判断,若表达式的结果为true,则标签中的内容会执行;-->
and username = #{username}
</if>
<if test="password != null and password !=''">
and password = #{password}
</if>
<if test="id != null and id !=''">
and id = #{id}
</if>
</select>
where:
@Test//动态sql_where
public void test() throws IOException {
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
Usermapper mapper = sqlSession.getMapper(Usermapper.class);
List<User> userByCondition = mapper.getUserByCondition(new User(5));
System.out.println(userByCondition);
}
<!--where关键字 List<User> getUserByCondition(User user);-->
<select id="getUserByCondition" resultType="User"> <!--该关键字一般和if连用,用了之后就不用1=1了-->
select * from user
<where>
<if test="username != null and username !=''">
and username = #{username}
</if>
<if test="password != null and password !=''">
and password = #{password}
</if>
<if test="id != null and id !=''">
and id = #{id}
</if>
</where>
</select>
trim:
@Test//动态sql_trim
public void test() throws IOException {
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
Usermapper mapper = sqlSession.getMapper(Usermapper.class);
List<User> userByCondition = mapper.getUserByCondition(new User(5));
System.out.println(userByCondition);
}
<!--trim关键字用于去掉或添加标签中的内容 List<User> getUserByCondition(User user);-->
<select id="getUserByCondition" resultType="User">
<!--prefix:在trim标签中的内容的前面添加某些内容-->
<!--suffix:在trim标签中的内容的后面添加某些内容-->
<!--prefixOverrides:在trim标签中的内容的前面去掉某些内容-->
<!--suffixOverrides:在trim标签中的内容的后面去掉某些内容-->
select * from user
<trim prefix="where" suffixOverrides="and|or">
<if test="username != null and username !=''">
username = #{username} and
</if>
<if test="password != null and password !=''">
password = #{password} and
</if>
<if test="id != null and id !=''">
id = #{id}
</if>
</trim>
choose otherwise when
@Test//动态sql_choose
public void test() throws IOException {
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
Usermapper mapper = sqlSession.getMapper(Usermapper.class);
List<User> userByCondition = mapper.getUserByChoose(null);
System.out.println(userByCondition);
}
<select id="getUserByChoose" resultType="User">
<!--这个相当于if else,一旦满足其中的一个条件就不会看别的条件了,otherwise是在所有的条件都不满足时候会执行的条件-->
select * from user
<where>
<choose>
<when test="username != null and username != ''">
username = #{username}
</when>
<when test="password != null and password != ''">
password = #{password}
</when>
<when test="id != null and id != ''">
id = #{id}
</when>
<otherwise>
username="xueyimeng"
</otherwise>
</choose>
</where>
</select>
foreach
@Test//动态sql_foreach
public void test() throws IOException {
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
Usermapper mapper = sqlSession.getMapper(Usermapper.class);
int[] ids={3,7};
int deleteMoreByArray = mapper.deleteMoreByArray(ids);
System.out.println(deleteMoreByArray);
}
<!--int deleteMoreByArray(int[] ids);-->
<!--collection:设置要循环的数组或集合array是数组,list是集合
item:表示集合或数组中的每一个数据
separator:设置循环体之间的分隔符,分隔符前后默认有一个空格,如,
open:设置foreach标签中的内容的开始符
close:设置foreach标签中的内容的结束符-->
<delete id="deleteMoreByArray">
delete from user where id in
<foreach collection="array" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</delete>
SQL片段
<!--List<User> search();-->
<sql id="select">select * from user </sql><!--这是声明,下面的是引用-->
<select id="search" resultType="User">
<include refid="select"></include>
</select>
4.mybatis的缓存
一级缓存
一级缓存是SqlSession级别的,通过同一个SqlSession查询的数据会被缓存,下次查询相同的数据,就会从缓存中直接获取,不会从数据库重新访问
使一级缓存失效的四种情况:
1.不同的SqlSession对应不同的一级缓存
2.同一个SqlSession但是查询条件不同
3.同一个SqlSession两次查询期间执行了任何一次增删改操作
4.同一个SqlSession两次查询期间手动清空了缓存
二级缓存
二级缓存是SqlSessionFactory级别,通过同一个SqlSessionFactory创建的SqlSession查询的结果会被缓存;此后若再次执行相同的查询语句,结果就会从缓存中获取
二级缓存开启的条件:
1.在核心配置文件中,设置全局配置属性cacheEnabled=“true”,默认为true,不需要设置
2.在映射文件中设置标签
3.二级缓存必须在SqlSession关闭或提交之后有效
4.查询的数据所转换的实体类类型必须实现序列化的接口
使二级缓存失效的情况:两次查询之间执行了任意的增删改,会使一级和二级缓存同时失效
二级缓存的相关配置
在mapper配置文件中添加的cache标签可以设置一些属性
eviction属性:缓存回收策略
LRU(Least Recently Used) – 最近最少使用的:移除最长时间不被使用的对象。
FIFO(First in First out) – 先进先出:按对象进入缓存的顺序来移除它们。
SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
默认的是 LRU
flushInterval属性:刷新间隔,单位毫秒
默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句(增删改)时刷新
size属性:引用数目,正整数
代表缓存最多可以存储多少个对象,太大容易导致内存溢出
readOnly属性:只读,true/false
true:只读缓存;会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这
提供了很重要的性能优势。
false:读写缓存;会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默
认是false
整合EHCache
5.MyBatis的逆向工程
逆向工程:先创建数据库表,由框架负责根据数据库表,反向生成如下资源:
(1)导入Maven依赖
<dependencies>
<!--mysql驱动坐标-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.32</version>
</dependency>
<!--mybatis的核心坐标-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<!--测试的坐标-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!--日志功能-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
</dependency>
</dependencies>
<!-- 控制Maven在构建过程中相关配置 -->
<build>
<!-- 构建过程中用到的插件 -->
<plugins>
<!-- 具体插件,逆向工程的操作是以构建过程中插件形式出现的 -->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.0</version>
<!-- 插件的依赖 -->
<dependencies>
<!-- 逆向工程的核心依赖 -->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.2</version>
</dependency>
<!-- 数据库连接池 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.2</version>
</dependency>
<!-- MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
(2)创建核心配置文件mybatis_config.xml,上面有我就不写了
(3)创建逆向工程的配置文件,名字必须是 generatorConfig.xml
generatorConfig.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!--
targetRuntime: 执行生成的逆向工程的版本
MyBatis3Simple: 生成基本的CRUD(清新简洁版)
MyBatis3: 生成带条件的CRUD(奢华尊享版)
-->
<context id="DB2Tables" targetRuntime="MyBatis3Simple">
<!-- 数据库的连接信息 -->
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/student"
userId="root"
password="123456">
</jdbcConnection>
<!-- javaBean的生成策略-->
<javaModelGenerator targetPackage="com.atguigu.mybatis.pojo" targetProject=".\src\main\java">
<property name="enableSubPackages" value="true" /><!--如果是true上面的com.atguigu就会创建出层级关系-->
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!-- SQL映射文件的生成策略 -->
<sqlMapGenerator targetPackage="com.atguigu.mybatis.mymapper"
targetProject=".\src\main\resources">
<property name="enableSubPackages" value="true" />
</sqlMapGenerator>
<!-- Mapper接口的生成策略 -->
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.atguigu.mybatis.mymapper" targetProject=".\src\main\java">
<property name="enableSubPackages" value="true" />
</javaClientGenerator>
<!-- 逆向分析的表 -->
<!-- tableName设置为*号,可以对应所有表,此时不写domainObjectName -->
<!-- domainObjectName属性指定生成出来的实体类的类名 -->
<table tableName="user" domainObjectName="User"/>
<table tableName="goods" domainObjectName="Goods"/>
</context>
</generatorConfiguration>
(4)执行MBG插件的generate目标
(5)测试
@Test
public void testMBG() throws IOException {
InputStream is = Resources.getResourceAsStream("mybatis_config.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
GoodsMapper mapper = sqlSession.getMapper(GoodsMapper.class);
GoodsExample goodsExample = new GoodsExample();
goodsExample.createCriteria().andIdBetween(1, 9);
List<Goods> goods = mapper.selectByExample(goodsExample);
System.out.println(goods);
}