学习目标
第一章 - MyBatis缓存【了解】
知识点-缓存概述
1.目标
2.路径
- 缓存概述
- 为什么使用缓存
- 缓存的适用情况
- MyBatis缓存类别
3.讲解
3.1缓存概述
缓存就是一块内存空间.保存临时数据
3.2为什么使用缓存
将数据源(数据库或者文件)中的数据读取出来存放到缓存中,再次获取的时候 ,直接从缓存中获取,可以减少和数据库交互的次数,这样可以提升程序的性能!
3.3缓存的适用情况
- 适用于缓存的:经常查询但不经常修改的(eg: 省市,类别数据),数据的正确与否对最终结果影响不大的
- 不适用缓存的:经常改变的数据 , 敏感数据(例如:股市的牌价,银行的汇率,银行卡里面的钱)等等,
3.4MyBatis缓存类别
一级缓存:它是sqlSession对象的缓存,自带的(不需要配置)不可卸载的(不想使用还不行). 一级缓存的生命周期与sqlSession一致。
二级缓存:它是SqlSessionFactory的缓存。只要是同一个SqlSessionFactory创建的SqlSession就共享二级缓存的内容,并且可以操作二级缓存。二级缓存如果要使用的话,需要我们自己手动开启(需要配置的)。
4.小结
- 缓存: 内存空间, 保存临时数据
- 为什么要使用缓存? 提高性能
- 适合使用缓存? 经常查询的, 不经常改变
- MyBatis的缓存类别
- 一级缓存 : 默认开启的,属于sqlsession级别
- 二级缓存 : 需要配置,默认不开启, 属于sqlsessionfactory
知识点-一级缓存
1.目标
2.路径
- 证明一级缓存的存在
- 一级缓存分析
- 测试一级缓存清空
3.讲解
3.1证明一级缓存的存在
只有查询的操作,才有缓存的必要性。增删改的操作不会有缓存。 其他的代码这里就不提供了,大家可以理解为了其实就是重复调用一个findByUid()方法,并且查询的用户id一样。
package com.itheima.test;
import com.itheima.bean.User;
import com.itheima.dao.UserDao;
import com.itheima.utils.SqlSessionFactoryUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
public class TestUserDao {
/*
证明一级缓存的存在:
1. 一级缓存是跟着sqlsession同生共死。
2. 只要重复查询即可,必须要查一样的id的用户
*/
@Test
public void testFindByUid(){
//1. 问工具类要sqlSession
SqlSession session = SqlSessionFactoryUtil.getSession();
//2. 问sqlSession要代理对象
UserDao userDao = session.getMapper(UserDao.class);
//3. 调用方法
User user = userDao.findByUid(1);
System.out.println("user = " + user);
//再查一次!
User user2 = userDao.findByUid(2);
System.out.println("user2 = " + user2);
//4. 收尾
session.close();
}
}
3.2一级缓存分析
第一次发起查询用户 id 为 1 的用户信息,先去找缓存中是否有 id 为 1 的用户信息,如果没有,从数据库查询用户信息。得到用户信息,将用户信息存储到一级缓存中。第二次发起查询用户 id 为 1 的用户信息,先去找缓存中是否有 id 为 1 的用户信息,缓存中有,直接从缓存中获取用户信息。mybatis里面判定是否存在现在要执行的操作的缓存数据,是通过sql语句判断的。在前面保存到缓存里面去的时候,就使用了sql语句充当KEY , 缓存数据充当Value来保存。
😃如果 sqlSession 去执行 commit操作(执行插入、更新、删除),清空 SqlSession 中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。 commit动作一定会清空缓存,因为有可能存在一种假设: 原来查询的是id为1的用户信息,接着做了更新操作,把id为1的用户信息给修改了,那么此时缓存里面的数据就是过期数据。
3.3测试一级缓存清空
- 增删改动作会清空一级缓存
package com.itheima.test;
import com.itheima.bean.User;
import com.itheima.dao.UserDao;
import com.itheima.utils.SqlSessionFactoryUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
public class TestUserDao {
//证明:清空一级缓存
@Test
public void testFindByUid02(){
//1. 问工具类要sqlSession
SqlSession session = SqlSessionFactoryUtil.getSession();
//2. 问sqlSession要代理对象
UserDao userDao = session.getMapper(UserDao.class);
//3. 调用方法
User user = userDao.findByUid(1);
System.out.println("user = " + user);
//删除其中的一条数据。
int row = userDao.deleteByUid(5);
System.out.println("删除的结果:" + row);
//再查一次!
User user2 = userDao.findByUid(1);
System.out.println("user2 = " + user2);
//4. 收尾
session.close();
}
}
4.小结
- 一级缓存: 依赖sqlSession对象的, 自带的不可卸载的. 一级缓存的生命周期和sqlSession一致
- 一级缓存清空
- sqlSession销毁 , 调用close()
- 增删改 提交之后 , 调用了commit
知识点-二级缓存
1.目标
2.路径
- 二级缓存的结构
- 二级缓存的使用
- 二级缓存的测试
3.讲解
二级缓存是SqlSessionFactory的缓存。只要是同一个SqlSessionFactory创建的SqlSession就共享二级缓存的内容,并且可以操作二级缓存. 默认mybatis不会开启二级缓存,需要手动配置,因为范围太大,而且工厂很可能永远不会关闭!
3.1二级缓存的结构
3.2二级缓存的使用
3.2.1 在 SqlMapConfig.xml 文件开启二级缓存
二级缓存它有两个开关: 一个是在SQLMapConfig.xml里面,这个开关默认是开启的。还有一个开关,这个开关需要在每一个mapper.xml(映射文件)里面开启。哪个映射文件配置了这个开关,那么即表示这个映射文件里面的所有查询操作会可以使用二级缓存。
因为 cacheEnabled 的取值默认就为 true,所以这一步可以省略不配置。为 true 代表开启二级缓存;为 false 代表不开启二级缓存。
3.2.2 配置相关的 Mapper 映射文件
- 默认情况下mybatis已经全局性开启了二级缓存,但是所有的查询动作都不会把数据放在二级缓存里面。
- 如果希望某一个查询的动作,把数据存放在二级缓存里里面,那么需要在映射文件中配置
<cache>
标签表示当前这个 mapper 映射将使用二级缓存,即:该mapper文件中的所有查询操作都将使用二级缓存, 无需单独为每一个2.路径
- @Insert:实现新增
- @Update:实现更新
- @Delete:实现删除
- @Select:实现查询
- @SelectKey:保存之后 获得保存的id
3.实现
- Dao
package com.itheima.dao; import com.itheima.bean.User; import org.apache.ibatis.annotations.*; import java.util.List; /* 这里使用注解来替代crud的 映射文件 */ public interface UserDao { @Insert("insert into t_user values (null , #{username}, #{sex} , #{birthday} , #{address})") int add(User user); @Delete("delete from t_user where uid = #{uid}") int delete(int uid); @Update("update t_user set username = #{username} , sex = #{sex} , birthday=#{birthday} , address=#{address} where uid = #{uid}") int update(User user); @Select("select * from t_user where uid = #{uid}") User findByUid(int uid); @Select("select * from t_user") List<User> findAll(); /* <selectKey keyProperty="" resultType="" order=""> SELECT LAST_ISNERT_ID(); </selectKey>*/ /* SelectKey : 添加之后,获取主键返回 keyProperty : 用什么属性来装 resultType : 属性是什么类型 before: false: 表明添加数据之后再去获取id值 true: 表明在添加数据之前就获取id值 statement: 查询id的语句 : SELECT LAST_INSERT_ID() */ @SelectKey(keyProperty = "uid" , resultType = int.class , before = false , statement = "SELECT LAST_INSERT_ID()") @Insert("insert into t_user values (null , #{username}, #{sex} , #{birthday} , #{address})") int add02(User user); }
- SqlMapConfig.xml
- 单元测试
package com.itheima.test; import com.itheima.bean.User; import com.itheima.dao.UserDao; import com.itheima.utils.SqlSessionFactoryUtil; import org.apache.ibatis.session.SqlSession; import org.junit.Test; import java.util.Date; import java.util.List; public class TestUserDao { @Test public void testAdd(){ SqlSession session = SqlSessionFactoryUtil.getSession(); UserDao dao = session.getMapper(UserDao.class); User user = new User(); user.setUsername("张三"); user.setSex("男"); user.setBirthday(new Date()); user.setAddress("深圳"); dao.add(user); session.close(); } @Test public void testDelete(){ SqlSession session = SqlSessionFactoryUtil.getSession(); UserDao dao = session.getMapper(UserDao.class); dao.delete(16); session.close(); } @Test public void testUpdate(){ SqlSession session = SqlSessionFactoryUtil.getSession(); UserDao dao = session.getMapper(UserDao.class); //先查询 User user = dao.findByUid(1); user.setSex("女"); //再修改 dao.update(user); session.close(); } @Test public void testFindAll(){ SqlSession session = SqlSessionFactoryUtil.getSession(); UserDao dao = session.getMapper(UserDao.class); //先查询 List<User> list = dao.findAll(); System.out.println("list = " + list); session.close(); } //添加完毕,获取主键id @Test public void testAdd02(){ SqlSession session = SqlSessionFactoryUtil.getSession(); UserDao dao = session.getMapper(UserDao.class); User user = new User(); user.setUsername("张三"); user.setSex("男"); user.setBirthday(new Date()); user.setAddress("深圳"); dao.add02(user); //打印id: System.out.println(user.getUid()); session.close(); } }
4.小结
- 查询
@Select("sql语句")
- 新增
@SelectKey(keyProperty = "主键属性名",resultType = 主键Java类型,before = false,statement = "SELECT LAST_INSERT_ID()") @Insert("sql语句")
- 更新
@Update("sql语句")
- 删除
@Delete("sql语句)
知识点-使用Mybatis注解实现复杂关系映射开发
1.目标
2.路径
- 复杂关系映射的注解说明
- 使用注解实现一对一复杂关系映射及延迟加载
- 使用注解实现一对多复杂关系映射及延迟加载
3.讲解
实现复杂关系映射之前我们可以在映射文件中通过配置
来实现, @ResultMap 这个注解不是封装用的。 下面我们一起来学习 **@Results 注解, @Result 注解, @One 注解, @Many注解。 **
3.1复杂关系映射的注解说明
- @Results 注解 , 代替的是标签
//该注解中可以使用单个@Result 注解,也可以使用@Result 集合 @Results({@Result(), @Result() })或@Results(@Result())
- @Resutl 注解 ,代替了
标签和 标签 , @Result(column="列名",property="属性名",one=@One(select="指定用来多表查询的 sqlmapper"),many=@Many(select="")) @Resutl 注解属性说明 column 数据库的列名 Property 需要装配的属性名 one 需要使用的@One 注解(@Result(one=@One)())) many 需要使用的@Many 注解(@Result(many=@many)()))
- @One 注解(一对一),代替了
标签,是多表查询的关键,在注解中用来指定子查询返回单一对象。 @Result(column="列名",property="属性名",one=@One(select="指定用来多表查询的 sqlmapper"))
@Many 注解(一对多) ,代替了
标签,是是多表查询的关键,在注解中用来指定子查询返回对象集合 注意:聚集元素用来处理“一对多”的关系。需要指定映射的 Java 实体类的属性,属性的 javaType(一般
为 ArrayList) 但是注解中可以不定义;@Result(property="",column="",many=@Many(select=""))
3.2使用注解实现(多)一对一复杂关系映射及延迟加载
3.2.1需求
查询账户(Account)信息并且关联查询用户(User)信息。
先查询账户(Account)信息,当我们需要用到用户(User)信息时再查询用户(User)信息。
3.2.2实现
- User02.java
package com.itheima.bean; import lombok.Data; import java.io.Serializable; import java.util.Date; @Data public class User02 implements Serializable { private int uid; private String username; private String sex; private Date birthday; private String address; }
- Account02.java
package com.itheima.bean; import lombok.Data; @Data public class Account02 { private int aid; private double money; private int uid; //表示一对一的关系: 一个账户只能属于一个用户 private User02 user02; }
- AccountDao02.java
package com.itheima.dao; import com.itheima.bean.Account02; import com.itheima.bean.User02; import org.apache.ibatis.annotations.One; import org.apache.ibatis.annotations.Result; import org.apache.ibatis.annotations.Results; import org.apache.ibatis.annotations.Select; import org.apache.ibatis.mapping.FetchType; import java.util.List; //一口气查询所有的账户 public interface AccountDao02 { /* @Select : 查询的注解 @Results : 等价于 <resultMap> 标签,用于做映射处理 @Result : 用于做具体的映射,每一个属性的映射,都需要用到这个注解 property : 属性名 column :列名 如果有一个属性是对象类型,那么也需要用@Result来映射 @Result: property : 属性名 javaType : 属性的类型是什么 column: 把什么列当成参数传递给下面调用的方法 one :用来表示一对一的映射 select : 用于表示要调用哪个类的哪个方法来得到结果 fetchType : 用于设置懒加载,默认不用懒加载 FetchType.LAZY : 懒加载 FetchType.EAGER : 不懒 */ @Select("select * from t_account") @Results(value = { @Result(property = "aid" , column = "aid"), @Result(property = "money", column = "money"), @Result(property = "uid" , column = "uid"), @Result(property = "user02" , javaType = User02.class , column = "uid", one = @One(select = "com.itheima.dao.UserDao02.findByUid" )) }) List<Account02> findAll(); }
- UserDao02.java
package com.itheima.dao; import com.itheima.bean.User; import com.itheima.bean.User02; import org.apache.ibatis.annotations.Select; // 根据用户的id来查询用户的信息 public interface UserDao02 { @Select("select * from t_user where uid = #{uid}") User02 findByUid(int uid); }
- 测试
package com.itheima.test; import com.itheima.bean.User; import com.itheima.dao.AccountDao02; import com.itheima.dao.UserDao; import com.itheima.utils.SqlSessionFactoryUtil; import org.apache.ibatis.session.SqlSession; import org.junit.Test; import java.util.Date; import java.util.List; public class TestAccountDao02 { @Test public void testFindAll(){ SqlSession session = SqlSessionFactoryUtil.getSession(); AccountDao02 dao = session.getMapper(AccountDao02.class); System.out.println(dao.findAll()); session.close(); } }
3.3使用注解实现一对多复杂关系映射及延迟加载
3.3.1需求
完成加载用户对象时,查询该用户所拥有的账户信息。
等账户信息使用的时候再查询.
3.3.2实现
- Account03.java
package com.itheima.bean; import lombok.Data; @Data public class Account03 { private int aid; private double money; private int uid; }
- User03.java
package com.itheima.bean; import lombok.Data; import java.io.Serializable; import java.util.Date; import java.util.List; @Data public class User03 implements Serializable { private int uid; private String username; private String sex; private Date birthday; private String address; //表示一个用户有多个账户: private List<Account03> account03List; }
- UserDao03.java
package com.itheima.dao; import com.itheima.bean.User03; import org.apache.ibatis.annotations.Many; import org.apache.ibatis.annotations.Result; import org.apache.ibatis.annotations.Results; import org.apache.ibatis.annotations.Select; import org.apache.ibatis.mapping.FetchType; import java.util.List; //查询所有的用户 public interface UserDao03 { /* @Select :查询注解 @Results :等价于<resultMap> @Result : 等价于<id>和<result> 标签 property:属性名 column : 列名 如果有一个属性是一个集合的类型,也需要用@Result来映射 @Result : 也可以映射一对多 property: 属性名 column: 把哪个列值,当成参数,传递给下面的方法 many: 表示一对多 select :用于写调用的方法的全路径 :com.itheima.dao.AccountDao03.findByUid */ @Select("select * from t_user") @Results(value={ @Result(property = "uid",column = "uid" , id = true), @Result(property = "username",column = "username"), @Result(property = "sex",column = "sex"), @Result(property = "birthday",column = "birthday"), @Result(property = "address",column = "address"), @Result(property = "account03List" , column = "uid" , many = @Many(select = "com.itheima.dao.AccountDao03.findByUid" )) }) List<User03> findAll(); }
- AccountDao03.java
package com.itheima.dao; import com.itheima.bean.Account03; import org.apache.ibatis.annotations.Select; import java.util.List; //根据用户的id,来查询账户的数据 public interface AccountDao03 { @Select("select * from t_account where uid = #{uid}") List<Account03> findByUid(int uid); }
- 测试
package com.itheima.test; import com.itheima.bean.User; import com.itheima.dao.UserDao; import com.itheima.dao.UserDao03; import com.itheima.utils.SqlSessionFactoryUtil; import org.apache.ibatis.session.SqlSession; import org.junit.Test; import java.util.Date; import java.util.List; //一对多查询: 查询所有的用户,并且把账户的信息也查询出来 public class TestUserDao03 { @Test public void testFinAll(){ SqlSession session = SqlSessionFactoryUtil.getSession(); UserDao03 dao = session.getMapper(UserDao03.class); System.out.println(dao.findAll()); session.close(); } }
4.小结
- 代替ResultMap标签
@Results(value={ @Result(column = "列名",property = "属性名",id = boolean值), @Result(column = "列名",property = "属性名", one=@One(select="", fetchType="") ), @Result(column = "列名",property = "属性名", many=@Many(select="", fetchType="") ) })
第四章 - 分页处理【重点】
知识点 - 分页
1.目标
2.路径
- 使用PageHelper实现分页效果
3.讲解
3.1 添加依赖
<dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.1.10</version> </dependency>
3.2 添加插件
需要在mybatis的核心配置(SqlMapConfig.xml)文件中,配置分页插件。 位于
environments
的前面。 配置分页的插件其实就是配置拦截器。这个拦截器有什么作用呢? 它的作用是能够让我们在不侵入代码|源码的情况下实现分页的效果,也就是它会在底层的sql语句给我们追加 limit ? ,?<plugins> <plugin interceptor="com.github.pagehelper.PageInterceptor"> </plugin> </plugins>
3.3 示例代码
- javabean
@Data @NoArgsConstructor @AllArgsConstructor public class User implements Serializable { private int uid; private String username; private String sex; private Date birthday; private String address; }
- dao
- 返回值使用pagehelper提供的 Page
- 最终的sql语句使用查询所有的语句
package com.itheima.dao; import com.github.pagehelper.Page; import com.itheima.bean.User; import org.apache.ibatis.annotations.Select; import java.util.List; public interface UserDao { /** * 分页查询 * @return */ @Select("select * from t_user") List<User> findPage(); /** * 分页查询: * 1. 除了返回当前这一页的集合数据之外 * 2. 还需要返回其他的数据(比如: 当前第几页,总共多少页,每页显示多少条,总共多少条!) * 3. pagehelper分页插件里面定义了一个专门用于包装分页数据的Bean : Page * 3.1 Page 其实就是一个ArrayList * 3.2 Page 继承了ArrayList,再添加几个属性! * @return */ @Select("select * from t_user") Page<User> findPage2(); }
- 测试代码
在查询之前需要设置查询的参数。
package com.itheima.test; import com.github.pagehelper.Page; import com.github.pagehelper.PageHelper; import com.itheima.bean.User; import com.itheima.dao.UserDao; import com.itheima.utils.SqlSessionFactoryUtil; import org.apache.ibatis.session.SqlSession; import org.junit.Test; import java.util.List; public class TestUserDao { @Test public void testFindPage(){ SqlSession session = SqlSessionFactoryUtil.getSession(); UserDao dao = session.getMapper(UserDao.class); //要想使用分页,必须在调用方法之前,配置想查询第几页,每页查询多少条! PageHelper.startPage(2, 2); List<User> list = dao.findPage(); for (User user : list) { System.out.println("user = " + user); } session.close(); } @Test public void testFindPage2(){ SqlSession session = SqlSessionFactoryUtil.getSession(); UserDao dao = session.getMapper(UserDao.class); //要想使用分页,必须在调用方法之前,配置想查询第几页,每页查询多少条! PageHelper.startPage(2, 2); Page<User> page = dao.findPage2(); System.out.println("当前页:" + page.getPageNum()); System.out.println("总动多少页:" + page.getPages()); System.out.println("每页显示:" + page.getPageSize()); System.out.println("总动多少条:" + page.getTotal()); //直接打印这个result 打印出来的内容并不是我们平常见到的集合的样子,多了很多东西。 System.out.println("当前这一页的集合:" + page.getResult()); //这个不影响使用,直接遍历,也可以使用。 for (User user : page.getResult()) { System.out.println("user=" + user); } session.close(); } }
4.总结
- 添加依赖
- 添加插件
- 查询的语句为 select * from t_user
第五章 - 综合案例
案例一 - 显示所有联系人
一,案例需求
二 、实现步骤
- 添加依赖
<dependencies> <!--MyBatis坐标--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.6</version> </dependency> <!--mysql驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.37</version> </dependency> <!--单元测试--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.10</version> <scope>test</scope> </dependency> <!--lombok 依赖--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.18</version> </dependency> <!--日志--> <!-- log start --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.12</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.6.6</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.6.6</version> </dependency> <!-- 分页插件依赖 --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.1.10</version> </dependency> <!-- https://mvnrepository.com/artifact/commons-beanutils/commons-beanutils --> <dependency> <groupId>commons-beanutils</groupId> <artifactId>commons-beanutils</artifactId> <version>1.9.4</version> </dependency> <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.1.2</version> </dependency> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>1.1.2</version> </dependency> <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.39</version> </dependency> <!-- dbutils :: 可以不添加 --> <dependency> <groupId>commons-dbutils</groupId> <artifactId>commons-dbutils</artifactId> <version>1.6</version> </dependency> <!-- c3p0:: 可以不添加 --> <dependency> <groupId>com.mchange</groupId> <artifactId>c3p0</artifactId> <version>0.9.2.1</version> </dependency> </dependencies>
- 设置maven的编译版本
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties>
- 拷贝配置文件 SqlMapConfig.xml db.properties log4j.properties 到 resources目录
记得修改db.propeties里面的数据库连接
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/linkman的数据库 jdbc.user=root jdbc.password=root
- 拷贝工具类 SqlSessionFactoryUtil
- dao代码
package com.itheima.dao; import com.github.pagehelper.Page; import com.itheima.bean.LinkMan; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Select; import java.util.List; public interface LinkManDao02 { /** * 查询所有的联系人 * @return */ @Select("select * from linkman") List<LinkMan> findAll(); }
- service代码
package com.itheima.service; import com.github.pagehelper.Page; import com.github.pagehelper.PageHelper; import com.itheima.bean.LinkMan; import com.itheima.bean.PageBean; import com.itheima.dao.LinkManDao; import com.itheima.dao.LinkManDao02; import com.itheima.utils.SqlSessionFactoryUtil; import org.apache.ibatis.session.SqlSession; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; public class LinkManService { /** * 查询所有联系人 * @return List<LinkMan> */ public List<LinkMan> findAll() throws SQLException { System.out.println("使用mybatis来查询所有的联系人!"); //1. 从工具类获取SqlSession SqlSession session = SqlSessionFactoryUtil.getSession(); //2. 从sqlsession获取代理对象 LinkManDao02 dao02 = session.getMapper(LinkManDao02.class); //3. 调用方法 List<LinkMan> list = dao02.findAll(); //4. 返回、收尾 session.close(); return list; } }
案例二 - 添加联系人
一、案例需求
点击添加联系人跳转添加联系人页面
在添加联系人页面,点击提交按钮,把数据提交到服务器,保存到数据库
在添加完成,可以查看到新建的联系人信息
二、实现步骤
- dao 代码
package com.itheima.dao; import com.github.pagehelper.Page; import com.itheima.bean.LinkMan; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Select; import java.util.List; public interface LinkManDao02 { @Insert("insert into linkman values(null , #{name} , #{sex}, #{age} , #{address}, #{qq}, #{email})") int add(LinkMan linkMan); }
- service代码
package com.itheima.service; import com.github.pagehelper.Page; import com.github.pagehelper.PageHelper; import com.itheima.bean.LinkMan; import com.itheima.bean.PageBean; import com.itheima.dao.LinkManDao; import com.itheima.dao.LinkManDao02; import com.itheima.utils.SqlSessionFactoryUtil; import org.apache.ibatis.session.SqlSession; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; public class LinkManService { /** * 添加联系人 * @param linkMan 要添加到数据库的联系人对象 * @return 影响的行数,如果 >0 表示添加成功,否则添加失败 */ public int add(LinkMan linkMan) throws SQLException { System.out.println("使用mybatis来添加联系人!"); //1. 从工具类获取SqlSession SqlSession session = SqlSessionFactoryUtil.getSession(); //2. 从sqlsession获取代理对象 LinkManDao02 dao02 = session.getMapper(LinkManDao02.class); //3. 调用方法 int row = dao02.add(linkMan); //4. 返回、收尾 session.close(); return row; } }
案例三 - 分页展示联系人
一、案例需求
二、 实现步骤
- dao实现
package com.itheima.dao; import com.github.pagehelper.Page; import com.itheima.bean.LinkMan; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Select; import java.util.List; public interface LinkManDao02 { @Select("select * from linkman") Page<LinkMan> findPage(); }
- service实现
package com.itheima.service; import com.github.pagehelper.Page; import com.github.pagehelper.PageHelper; import com.itheima.bean.LinkMan; import com.itheima.bean.PageBean; import com.itheima.dao.LinkManDao; import com.itheima.dao.LinkManDao02; import com.itheima.utils.SqlSessionFactoryUtil; import org.apache.ibatis.session.SqlSession; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; public class LinkManService { /** * 分页查询联系人 * @param currentPage 想看第几页 * @param pageSize 每页想看多少条 * @return PageBean 里面封装了当前页的集合数据以及页码使用的信息。 */ public PageBean<LinkMan> findByPage(int currentPage , int pageSize) throws SQLException { System.out.println("使用mybatis来完成分页功能..."); //1. 创建PageBean PageBean<LinkMan> pageBean = new PageBean<LinkMan>(); //2. 调用dao得到结果 //2.1. 从工具类获取SqlSession SqlSession session = SqlSessionFactoryUtil.getSession(); //2.2. 从sqlsession获取代理对象 LinkManDao02 dao02 = session.getMapper(LinkManDao02.class); //2.3. 调用方法 //设置想要查询第几页,每页查询多少条 PageHelper.startPage(currentPage, pageSize); Page<LinkMan> page = dao02.findPage(); //2.4. 返回、收尾 session.close(); //3. 封装PageBean pageBean.setCurrentPage(currentPage); pageBean.setTotalPage(page.getPages()); pageBean.setPageSize(pageSize); pageBean.setTotalSize((int) page.getTotal()); pageBean.setList(page.getResult()); return pageBean; } }
总结
缓存:
1. mybatis为了提高程序的执行效率,设置了两级缓存: 一级缓存和二级缓存 2. 一级缓存: 属于SqlSession级别的缓存,只在当前的SqlSession内有效,自动设置 2.1 当进行增删改操作的时候,有事务的提交,那么缓存就会清空掉 3. 二级缓存: 属于SqlSessionFactory级别的缓存,只要是从这个SqlsessionFactory 做出来的Sqlsession,都可以共享这个二级缓存。 2.1 当进行增删改操作的时候,有事务的提交,那么缓存就会清空掉 2.2 二级缓存有两个开关,默认已经在全局性的开启了二级缓存,但是哪一个映射文件 想使用二级缓存,那么需要在自己的映射文件里面添加: <cache/> 4. 一般很少去使用二级缓存,因为范围太大,所以很少使用它。
懒加载:
1. 懒加载只会出现在多表查询里面,在对从表(第二张表)处理的时候,可以稍微偷懒,不是 一口气就把所有的表的数据给查询出来,而是等用到了之后再去查询! 2. 懒加载的步骤: 2.1 永远会先查询第一张表的所有数据 findAll(); 2.2 再去查询第二张表,一般是根据主键|外键来查询。 findByXXX(int id); 2. 一对一: 一个账户属于一个用户 public class Account{ ... private User user; } AccountDao.xml: <resultMap id="accountMap" type="account"> <id property="" column=""/> <result property="" column=""/> <association property="user" javaType="user" select="com.itheima.dao.UserDao.findByUid" column="uid" fetchType="lazy"/> </resultMap> <select id="findAll" resultMap=""> select * from t_account; </select> 3. 一对多: 一个用户有很多的账户 public class User{ ... private List<Account> accountList; } UserDao.xml: <resultMap id="accountMap" type="account"> <id property="" column=""/> <result property="" column=""/> <collection property="accountList" ofType="account" select="com.itheima.dao.AccountDao.findByUid" column="uid" fetchType="lazy"/> </resultMap> <select id="findAll" resultMap=""> select * from t_user; </select>
注解开发:
基本CRUD: @Insert @Delete @Update @Select @SelectKey 多表关系: @Results : 匹配 <resultMap>标签 @Result : 匹配 <id> 和 <result标签> @One : 一对一 匹配 association @Many : 多对多 匹配 collection
分页插件:
1. 导入依赖 2. 配置插件 3. 查询之前先设置查询第几页,每页查询多少条。