Mybaits

总结笔记,课程来自:https://www.kuangstudy.com/course/play/1321000734250762241

前言

  1. Mybatis是什么?

  2. 我们为什么要学习Mybatis?

  3. 持久化是什么?

  4. 持久层是什么?

  5. mybatis依赖

    <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.2</version></dependency>
    

一、mybatis程序

1.思路:搭建环境->导入mybatis的jar包->编写代码->测试

2.mybatis程序

  1. 写工具类读取mybatis的配置文件获取sqlsession对象。

    import org.apache.ibatis.io.Resources;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSessionFactoryBuilder;import java.io.IOException;import java.io.InputStream;public class MybatisUtil { private static SqlSessionFactory sqlSessionFactory; static {     try {         // 使用mybatis第一步,获取sqlSessionFactory对象         String resource = "mybatis-config.xml";         InputStream inputStream = Resources.getResourceAsStream(resource);         sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);     } catch (IOException e) {         e.printStackTrace();     } } // 有了SqlSessionFactory,我们就可以获得sqlsession的实例了 // sqlsession对象完全包含了面向数据库执行sql命令需要的所有方法 public static SqlSession getSqlSession() {     return sqlSessionFactory.openSession(); }}
    
  2. 配置mybatis配置文件,连接数据库。

    // 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> <environments default="development">     <environment id="development">         <transactionManager type="JDBC"/>         <dataSource type="POOLED">             <property name="driver" value="com.mysql.jdbc.Driver"/>             <property name="url" value="jdbc:mysql://101.37.147.181:3306/z_mybatis?useUnicode=true&amp;characterEncoding=UTF-8"/>             <property name="username" value="root"/>             <property name="password" value="xxx"/>         </dataSource>     </environment> </environments> <!--每一个mapper.xml都需要在mybatis核心配置文件中注册--> <mappers>     <mapper resource="com/sywl/mapper/UserMapper.xml"></mapper> </mappers></configuration>
    
  3. 搭建环境,编写代码。(User,UserMapper接口,UserMapper.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"><mapper namespace="com.sywl.mapper.UserMapper"> <delete id="deleteUser">     delete from user where id = #{userId} </delete> <select id="selectUserList" resultType="com.sywl.entity.User">     select * from user </select> <select id="selectById" resultType="com.sywl.entity.User">     select * from user where id = #{id} </select> <insert id="insertUser" parameterType="com.sywl.entity.User">     insert into user(name,age) values (#{name},#{age}) </insert></mapper>
    
  4. 测试。

    @Test public void test01(){     // 1.获取sqlsession对象     SqlSession sqlSession = MybatisUtil.getSqlSession();     // 2.方式一:获取UserMapper接口,去执行方法     UserMapper mapper = sqlSession.getMapper(UserMapper.class);     List<User> users = mapper.selectUserList();     for (User user : users) {         System.out.println(user);     } } @Test public void test05(){     SqlSession sqlSession = MybatisUtil.getSqlSession();     List<User> userList = sqlSession.selectList("com.sywl.mapper.UserMapper.selectUserList");     for (User user : userList) {         System.out.println(user);     } }
    

3.可能出现的问题

  1. 配置文件没有注册。(mybatis配置文件中的没有配置)
  2. 绑定接口错误。(UserMapper.xml文件中的namespace配置不对)
  3. 方法名不对。(UserMapper.xml文件中id对应的方法名不对)
  4. 返回类型不对。(UserMapper.xml文件的resultType类型不对)
  5. 资源导出失败问题。(需要在pom.xml中的build中配置resources)

4.注意点

  1. resource绑定mapper,需要使用路径/

二、crud

1.万能Map

  1. Map传递参数,直接在sq中取出Map的key。

    Map map = new Map();map.set("name","zhangsan");map.set("userId",1);mapper.getUserById(map);// UserMapperUser getUserById(Map map);// UserMapper.xml<select id="getUserById" parameterType="map"> select * from user where username=#{name} or user_id=#{userId}</select>
    
  2. 对象传递参数,直接在sq中取对象的属性。

    User user = new User();user.setUsername("zhangsan");user.setUserId(1);mapper.getUserById(user);// UserMapperUser getUserById(User user);// UserMapper.xml<select id="getUserById" parameterType="user"> select * from user where username=#{username} or user_id=#{userId}</select>
    
  3. 只有一个基本类型参数的情况下,可以直接在sq中取到,省略parameterType。

    mapper.getUserById(id);// UserMapperUser getUserById(int id);// UserMapper.xml<select id="getUserById"> select * from user where username=#{username} or user_id=#{userId}</select>
    
  4. 多个参数传递时,用Map,或者@RequestParm注解。

2.模糊查询

  1. java代码执行时传递通配符。

    List<User> userList = mapper.getUserList("%李%");
    
  2. 在sql拼接时使用通配符。

    select * from user where username like "%"#{username}"%"
    

三、配置优化

1.总配置

//db.properties 加上jdbc前缀避免出错(连接不到数据库)jdbc.driver=com.mysql.jdbc.Driverjdbc.url=jdbc:mysql://localhost:3306/mybatis?useEncoding=true&characterEncoding=utf-8jdbc.username=rootjdbc.password=xxx
// 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 resource="db.properties"><!--db.properties在resources目录下可以直接写文件名-->        <property name="username" value="root"/>        <property name="password" value="xxx"/>    </properties>    <!--settings配置-->    <settings>        <!--全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。默认true-->        <setting name="cacheEnabled" value="true"/>        <!--延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。        特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态。默认false-->        <setting name="lazyLoadingEnabled" value="默认false"/>        <!--允许JDBC支持自动生成主键,需要数据库驱动支持。默认false-->        <setting name="useGeneratedKeys" value="false"/>        <!--指定MyBatis所用日志的具体实现,未指定时将自动查找。默认未指定-->        <setting name="logImpl" value="LOG4J"/>    </settings>    <!--别名设置:1给实体类起别名,2配置一个包名-->    <typeAliases>        <!--<typeAlias type="com.sywl.entity.User" alias="User"></typeAlias>-->        <package name="com.sywl.entity"/>    </typeAliases>    <environments default="development">        <!--环境一-->        <environment id="development">            <!--mybatis事务管理器:默认时JDBC,还有一个managed-->            <transactionManager type="JDBC"/>            <!--mybatis数据源:默认POOLED,还有UNPOOLED和JNDI-->            <dataSource type="POOLED">                <property name="driver" value="${driver}"/>                <property name="url" value="${url}"/>                <property name="username" value="${username}"/>                <property name="password" value="${password}"/>            </dataSource>        </environment>        <!--环境二-->        <environment id="test">            <transactionManager type="JDBC"/>            <dataSource type="POOLED">                <property name="driver" value="${driver}"/>                <property name="url" value="${url}"/>                <property name="username" value="${username}"/>                <property name="password" value="${password}"/>            </dataSource>        </environment>    </environments>    <!--mappers映射器-->    <mappers>        <mapper resource="org/mybatis/example/BlogMapper.xml"/>    </mappers></configuration>

2.相关配置属性

  1. properties(属性)

  2. settings(设置)

  3. typeAliases(类型别名)

  4. environments(环境配置)

    • environment(环境变量)
      • transactionManager(事务管理器)
      • dataSource(数据源)
        不过要记住:尽管可以配置多个环境,但每个SqlSessionFactory实例只能选择一种环境。
  5. mappers(映射器)

    1. 方式一:resource(推荐使用)

      <mappers> <!--每一个Mapper.xml文件都需要在核心配置文件中注册--> <mapper resource="com/sywl/mapper/UserMapper.xml"/></mappers>
      
    2. 方式二:使用class文件绑定注册

      <mappers> <!--每一个接口都需要在核心配置文件中注册--> <mapper class="com.sywl.mapper.UserMapper"/></mappers>// 注意://1接口和它的Mapper.xml配置文件必须同名。//2接口和它的Mapper.xml配置文件必须在同一个包下。
      
    3. 方式三:使用扫描包进行绑定注册。

      <mappers> <package name="com.sywl.mapper"/></mappers>// 注意://1接口和它的Mapper.xml配置文件必须同名。//2接口和它的Mapper.xml配置文件必须在同一个包下。
      

四、生命周期和作用域

生命周期类别是至关重要的,因为错误的使用会导致非常严重的并发问题

img

  1. SqlSessionFactoryBuider作用域。
    • 一旦创建了SqlSessionFactory,就不再需要它了
    • 因此SqlSessionFactoryBuilder实例的最佳作用域是方法作用域(局部方法变量)
  2. SqlSessionFactory作用域。
    • SqlSessionFactory可以想象成连接池。
    • SqlSessionFactory一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。
    • 因此SqlSessionFactory的最佳作用域是应用作用域。有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。
  3. SqlSession作用域。
    • 可以视为连接到连接池的一个请求。
    • SqlSession的实例不是线程安全的,因此是不能被共享的。
    • 所以它的最佳的作用域是请求或方法作用域。
    • 用完之后关闭,否则资源会被占用。
    • 为了确保每次都能执行关闭操作,你应该把这个关闭操作放到finally块中。

五、ResultMap

1.ResultMap结果集映射。

  1. 起别名

    <mapper namespace="com.sywl.mapper.UserMapper"> <select id="getUserById" resultType="com.sywl.entity.User">     select id,username,pwd as password from User where id = #{id} </select></mapper>
    
  2. ResultMap结果集映射(可以只映射字段名和属性名不同的)

    <resultMap id="userMap" type="com.sywl.entity.User"> <id column="id" property="id"/><!--数据库字段id和实体类属性id名称一致可省略id的映射--> <result column="username" property="username"/><!--数据库字段username和实体类属性username名称一致可省略username的映射--> <result column="pwd" property="password"/><!--数据库字段pwd和实体类属性password名称不一致不可省略的映射--></resultMap><select id="getUserById" resultMap="userMap"> select id,username,pwd from User where id = #{id}</select>
    

2.ResultMap多对一映射

2.1按照查询嵌套处理
@Datapublic class Student {    private int id;    private String username;    private Teacher teacher;}<mapper namespace="com.sywl.mapper.StudentMapper">    <!--    思路:1.查询所有的学生         2.根据查询出来的学生表的tid字段,查找对应的老师    -->    <resultMap id="studentTeacherMap" type="com.sywl.entity.Student">        <id property="id" column="id"></id>        <result property="username" column="username"/>        <!--对象:association,tid是学生表中关联的老师的id-->        <association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>    </resultMap>    <select id="getStudentList" resultMap="studentTeacherMap">        select * from student    </select>    <select id="getTeacher" resultType="Teacher">        select * from teacher where id = #{tid}<!--这个参数名推荐和上面column="tid"保持一致,但是不保持一致也不会出错-->    </select></mapper>
2.1按照结果嵌套处理
@Datapublic class Student {    private int id;    private String username;    private Teacher teacher;}<mapper namespace="com.sywl.mapper.StudentMapper">    <resultMap id="studentTeacherMap" type="com.sywl.entity.Student">        <id property="id" column="id"></id>        <result property="username" column="username"/>        <!--对象:association-->        <association property="teacher" javaType="Teacher">            <id property="id" column="tid"></id>            <result property="username" column="tname"></result>        </association>    </resultMap>    <select id="getStudentList" resultMap="studentTeacherMap">        select s.id,s.username,t.id tid,t.username tname from student s,teacher t where s.tid=t.id    </select></mapper>

3.ResultMap一对多映射

3.1按照查询嵌套处理
<mapper namespace="com.sywl.mapper.TeacherMapper">    <!--    思路:1.查询指定的老师         2.根据查询出来的老师的id字段别名是ttid,查找老师下对应的所有学生    -->    <resultMap id="teacherStudentMap" type="Teacher">        <id property="id" column="ttid"></id>        <!--ttid是老师表的id-->        <collection property="studentList" javaType="ArrayList" ofType="Student" select="getStudentByTeacherId" column="ttid"/>    </resultMap>    <!--按照查询嵌套处理-->    <select id="getTeacherById" resultMap="teacherStudentMap">        select t.id ttid,t.* from teacher t where id=#{tid}    </select>    <select id="getStudentByTeacherId" resultType="Student">        select * from student where tid = #{ttid}    </select></mapper>
3.2按照结果嵌套处理
@Datapublic class Teacher {    private int id;    private String username;    private List<Student> studentList;}<mapper namespace="com.sywl.mapper.TeacherMapper">    <resultMap id="teacherStudentMap" type="Teacher">        <id property="id" column="tid"/>        <result property="username" column="tname"/>        <!--        复杂的属性单独处理,集合:collection        javaType=""指定实体类属性的类型;        集合中的泛型信息,使用ofType获取。        -->        <collection property="studentList" ofType="Student">            <id property="id" column="tid"/>            <result property="username" column="sname"/>            <result property="tid" column="tid"/>        </collection>    </resultMap>    <!--按结果嵌套查询-->    <select id="getTeacherById" resultMap="teacherStudentMap">        select s.id sid,s.username sname,t.id tid,t.username tname from student s,teacher t where s.tid=t.id and t.id=#{tid}    </select></mapper>

六、日志工厂

1.mybatis的日志配置

使用哪个日志实现在mybatis-config.xml设置中配置
img

  • SLF4J
  • LOG4J(掌握)
  • LOG4J2
  • JDK_LOGGING
  • COMMONS_LOGGING
  • STDOUT_LOGGING(掌握:标准日志输出)
  • NO_LOGGING0

2.log4j

  • Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件。
  • 我们也可以控制每一条日志的输出格式。
  • 通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。
  • 最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。

3.mybatis使用log4j步骤

  1. 导入log4j的jar包。

    <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version></dependency>
    
  2. 设置mybatis配置文件的日志实现类是LOG4J

    <settings>     <!--指定MyBatis所用日志的具体实现,未指定时将自动查找。默认未指定-->     <setting name="logImpl" value="LOG4J"/></settings>
    
  3. 书写log4j.properties配置文件。

    # 将等级为DEBUG的日志信息输出到console和file两个目的地log4j.rootLogger=DEBUG,console,file# 控制台输出相关配置log4j.appender.console=org.apache.log4j.ConsoleAppenderlog4j.appender.Threshold=DEBUGlog4j.appender.console.Target=System.outlog4j.appender.console.layout=org.apache.log4j.PatternLayoutlog4j.appender.console.layout.ConversionPattern=[%-5p][%d{yyyy-MM-dd HH\:mm\:ss,SSS}][%c] \:%m%n# 文件输出的相关配置log4j.appender.file=org.apache.log4j.RollingFileAppenderlog4j.appender.file.File=./logs/all.loglog4j.appender.file.MaxFileSize=10mblog4j.appender.file.Threshold=DEBUGlog4j.appender.file.layout=org.apache.log4j.PatternLayoutlog4j.appender.file.layout.ConversionPattern=[%-5p][%d{yyyy-MM-dd HH\:mm\:ss,SSS}][%c] \:%m%n# 日志输出级别log4j.logger.org.mybatis=DEBUGlog4j.logger.java.sql=DEBUGlog4j.logger.java.sql.Statement=DEBUGlog4j.logger.java.sql.ResultSet=DEBUGlog4j.logger.java.sql.PreparedStatement=DEBUG
    

七、分页和注解开发

1.limit分页

// i : 为查询结果的索引值(默认从0开始)// n : 为查询结果返回的数量select * from user limit i,n;// 传一个参数时,意思是从第一个数据开始查询n个数据。select * from user limit n;

2.RowBounds分页

// 代码成设置分页@Testpublic void test02(){    SqlSession sqlSession = SqlSessionUtil.getSqlSession();    RowBounds rowBounds = new RowBounds(1, 2);    List<User> userList = sqlSession.selectList("com.sywl.mapper.UserMapper.selectList", rowBounds);    }

3.mybatis的PageHelper分页插件。

4.注解开发

@Select("select * from user")List<User> selectUser();@Insert("")void insertUser(User user);@Update("")void updateUser(User user);@Delete("")void deleteUserById(int id);

八、mybatis执行流程

img

九、动态SQL

  • 动态SQL是指根据不同的条件生成不同的SQL语句。
  • 动态SQL本质还是SQL语句,只是我们可以在SQL层面,执行一个逻辑代码。
  • 动态SQL就是在拼接SQL语句,我们只要保证SQL正确性,按照SQL格式去排列组合就可以了。

1.if

<select id="queryBlogIF" paremterType="map" resultType="blog">    select * from blog where 1=1    <if test="title != null">        title = #{title}    </if>    <if test="author != null">        and author = #{author}    </if></select>

2.choose,when,otherwise

<select id="queryBlogChoose" paremterType="map" resultType="blog">    select * from blog     <where>        <choose>            <!--只会选择其中一个去执行-->            <when test="title != null">                title = #{title}            </when>            <when test="author != null">                and author = #{author}            </when>            <otherwise>                and views = #{views}            </otherwise>        </choose>    </where></select>

3.trim(where,set)

标签作用:

  • where标签元素中有子元素返回任何内容的情况下才插入“where”子句。
  • 如果子句的开头为”AND”或”OR”,where标签元素会将他们去除。

标签作用:

  • set标签元素会动态的在行首插入set关键字,并会删除额外的逗号。(这些逗号是在使用条件语句给列赋值时引入的)

    <update id="updateAuthorIfNecessary">update Author  <set>    <if test="username != null">username=#{username},</if>    <if test="password != null">password=#{password},</if>    <if test="email != null">email=#{email},</if>    <if test="bio != null">bio=#{bio}</if>  </set>where id=#{id}</update>
    

4.foreach

<select id="selectPostIn" resultType="User">  select *  from user u  where id in  <foreach item="id" index="index" collection="ids"      open="(" separator="," close=")">        #{id}  </foreach></select>

5.SQL片段

  • 可以将一些功能的部分抽取出来,方便复用。

    5.1使用SQL标签抽取公共的部分。
    <sql id="if-title-author">  <if test="title != null">      title = #{title}  </if>  <if test="author != null">      and author = #{author}  </if></sql>
    
    5.2在需要的地方使用include标签引用即可。
    <select id="queryBlogIF" paremterType="map" resultType="blog">  select * from blog  <where>      <include refid="if-title-anthor"></include>  </where></select>
    

十、缓存

  1. 什么是缓存[Cache]?
    • 存在内存中的临时数据。
    • 将用户经常查询的数据放在缓存中,用户去查询数据就不用从磁盘上(关系型数据库数据文件)查询,从缓存中査询,从而提高査询效率,解决了高并发系统的性能问题。
  2. 为什么使用缓存?
    • 减少和数据库的交互次数,减少系统开销,提高系统效率。
  3. 什么样的数据能使用缓存?
    • 经常査询并且不经常改变的数据。

1.mybatis缓存

  • mybatis默认定义了两级缓存:一级缓存和二级缓存
  • 默认情况下,只有一级缓存开启。(SqlSession级别的缓存)
  • 二级缓存需要手动开启和配置,基于namespace级别的缓存。
  • 为了提高扩展性,mybatis定义了缓存接口Cache。(我们可以通过实现Cache接口来自定义二级缓存)

2.一级缓存

2.1测试步骤
  1. 开启日志。
  2. 测试在一个SqlSession中查询两次相同的记录。
  3. 查看日志输出。(只查询了一次数据库SQL,第二次直接从缓存中数据)
2.2一级缓存失效的情况
  1. 查询不同的东西。
  2. 增删改操作,可能会改变原来的数据,所以必定会刷新缓存。
  3. 查询不同的mapper.xml
  4. 手动清理缓存。(sqlSession.clearCache();)
2.3一级缓存总结
  • 一级缓存默认是开启的。
  • 一级缓存只在一次SqlSession中有效,即拿到连接到连接关闭的这个区间。

3.二级缓存

3.1二级缓存使用步骤
  1. 开启全局缓存。

    <settings> <!--默认是true,建议显式的在配置文件中声明--> <setting name="cacheEnabled" value="true"/></settings>
    
  2. 在要使用二级缓存的mapper.xml中开启。

    <!--直接开启使用--><cache/><!--也可以自定义参数开启使用--><cacheeviction="FIFO"flushInterval="60000"size="512"readOnly="true"/>
    

    LRU – 最近最少使用:移除最长时间不被使用的对象。

    FIFO – 先进先出:按对象进入缓存的顺序来移除它们。

    SOFT – 软引用:基于垃圾回收器状态和软引用规则移除对象。

    WEAK – 弱引用:更积极地基于垃圾收集器状态和弱引用规则移除对象。

  3. 测试。

    • 需要把实体类序列化(实体类实现Serializable接口),否则可能会报错。
3.2二级缓存总结
  • 只要开启了二级缓存,在同一个mapper下有效。

  • 所有的数据都会先放在一级缓存中。

  • 只有当会话提交或关闭的时候,才会提交到二级缓存中。

  • 可以在mapper.xml中的查询语句定义是否使用缓存

    <select id="getUser"resultType="user" userCache="false">  select * from user</select>
    

4.缓存原理

img

5.自定义缓存-ehcache

Ehcache是一种广泛使用的开源Java分布式缓存。主要面向通用缓存

<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>

配置一个ehcache.xml配置

总结

  1. mybatis是一款优秀的持久层框架,可以把数据持久化;它支持定制化sql,存储过程,结果集映射等。
  2. 使用的人多,传统的jdbc代码太复杂了,mybatis框架简化了流程,自动化。
  3. 持久化是数据从瞬时状态转化到持久状态。内存的特性是断电即失,持久化指存到数据库中,io文件持久化等。
  4. 持久层是完成持久化工作的代码块。

面试题

  1. MySQL引擎
  2. InnoDB底层原理
  3. 索引
  4. 索引优化
  5. 读写分离
  6. 主从复制
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值