一. mybatis是什么?

  1. MyBatis是一个ORM的数据库持久化框架;
  2. Mybatis底层还是原生的JDBC代码,对JDBC代码的封装。

二. 什么是ORM

  1. ORM:对象关系映射(Object Relational Mapping,简称ORM):是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术;

  2. ORM原理:

    • 以一定的映射方式,把实体模型和数据库关系进行映射;

    • ORM框架启动时加载这些映射和数据库配置文件连接数据库;

    • ORM通过对最原生jdbc的封装,并提供更加便利的操作API;

    • Dao通过ORM提供的便捷API以对象的方式操作数据库关系。

三. 实现步骤

  1. 使用文档:文档使用地址; mybatis需要的jar包——》https://gitee.com/coderyeah/layui-module/tree/master/lib(地址);
  2. 先说一个核心对象:SqlSessionFactory,接下来,咱们就是要想方设法拿到这个核心对象;
  3. 要获取SqlSessionFactory,我们需要准备一个核心的Mybatis-config.xml文件,然后通过SqlSessionFactoryBuilder来创建,所以步骤:
    • 创建Mybatis核心配置文件(Mybatis-config.xml),并配置环境;
    • 加载核心配置文件;
    • 创建一个SqlSessionFactoryBuilder对象;
    • 通过SqlSessionFactoryBuilder对象构建一个SqlSessionFactory对象;
    • 创建Mapper映射文件,并配置;
    • 通过SqlSessionFactory获取SqlSession执行映射SQL。

四. 核心配置文件:MyBatis-Config.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<configuration>
<typeAliases>
<typeAlias type="com.lqs.domain.User" alias="User"/>
<package name="com.lqs.domain"/>
</typeAliases>
<!-- 引入配置文件信息,这里不能加classpath:。
resource:引入类路径下的资源,即classpath,所以不需要写classpath:
url:引入网络路径或磁盘路径下的资源
-->
<properties resource="db.properties"></properties>
<!-- 环境们 (很多环境的意思)
default:默认使用哪一个环境(必需对应一个环境的id)
-->
<environments default="development">
<!-- 一个环境 id:为这个环境取唯一一个id名称 -->
<environment id="development">
<!-- 事务管理 type:JDBC(支持事务)/MANAGED(什么都不做) -->
<transactionManager type="JDBC" />
<!-- 数据源, 连接池 type(POOLED):MyBatis自带的连接池 -->
<dataSource type="POOLED">
<!-- 连接数据库的参数:直接写死的方式 -->
<!--
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql:///mydb" />
<property name="username" value="root" />
<property name="password" value="admin" />
-->
<!-- 连接数据库的参数:使用属性文件的方式 -->
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<!-- 这个mappers代表的是相应的ORM映射文件 -->
<mappers>
<mapper resource="com/lqs/mapper/UserMapper.xml"/>
<!-- 将包内的映射器接口实现全部注册为映射器 -->
<package name="com.lqs.mapper"/>
</mappers>
</configuration>

五. 属性文件:db.properties

1
2
3
4
username=root
password=123456
driver=com.mysql.jdbc.Driver
url=jdbc:mysql:///jdbc

项目目录:

image-20220721172938977

六. 具体代码实现

  1. User类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    package com.lqs.domain;

    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    import org.apache.ibatis.type.Alias;

    @Data
    @AllArgsConstructor
    @Alias("user")//别名
    public class User {
    private Long id;
    private String name;
    private Integer age;
    private boolean sex;
    private String hobby;
    }

  2. 自定义mybatis工具类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    package com.lqs.utils;

    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 SqlSession sqlSession = null;

    static {
    String resource = "mybatis-config.xml";
    try (final InputStream in = Resources.getResourceAsStream(resource);) {
    final SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
    sqlSession = factory.openSession(true);//自动提交
    } catch (IOException e) {
    e.printStackTrace();
    }
    }

    public static SqlSession getSqlSession() {
    return sqlSession;
    }
    }

  1. 接口

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    package com.lqs.dao;

    import com.lqs.domain.User;
    import org.apache.ibatis.annotations.Select;

    import java.util.List;

    public interface IUserDao {
    /**
    * 查询所有用户
    *
    * @return
    */
    List<User> queryAll();

    /**
    * 根据id查询一个用户
    *
    * @param id
    * @return
    */
    @Select("select * from t_user where id = #{id}")
    User queryOne(Long id);

    /**
    * 添加一个用户
    *
    * @param user
    */
    void add(User user);

    /**
    * 根据id删除一个用户
    *
    * @param id
    */
    void delete(Long id);

    /**
    * 根据id更新用户
    *
    * @param user
    */
    void update(User user);


    }

  2. 接口实现类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    package com.lqs.dao.impl;

    import com.lqs.dao.IUserDao;
    import com.lqs.domain.User;
    import com.lqs.utils.MybatisUtil;
    import org.apache.ibatis.session.SqlSession;

    import java.util.List;

    public class UserDaoImpl implements IUserDao {

    final IUserDao mapper = MybatisUtil.getSqlSession().getMapper(IUserDao.class);

    @Override
    public List<User> queryAll() {
    return mapper.queryAll();
    }

    @Override
    public User queryOne(Long id) {
    return mapper.queryOne(id);
    }

    @Override
    public void add(User user) {
    mapper.add(user);
    }

    @Override
    public void delete(Long id) {
    mapper.delete(id);
    }

    @Override
    public void update(User user) {
    mapper.update(user);
    }
    }

  3. UserMaper.xml文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    <?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">
    <!--完全限定名 将xml和接口进行了映射-->
    <mapper namespace="com.lqs.dao.IUserDao">
    <!-- 返回主键 -->
    <insert id="add" parameterType="User" useGeneratedKeys="true" keyProperty="id" keyColumn="id">
    insert into t_user (name, age, sex, hobby)
    VALUES (#{name}, #{age}, #{sex}, #{hobby})
    </insert>
    <update id="update" parameterType="long">
    update t_user
    set name=#{name},
    age=#{age},
    sex= #{sex},
    hobby= #{hobby}
    where id = #{id}
    </update>

    <update id="test" parameterType="user">
    update t_user
    <set>
    <if test="name != null">
    name=#{name}
    </if>
    <if test="age != null">
    age=#{age}
    </if>
    <if test="hobby != null">
    hobby= #{hobby}
    </if>
    </set>
    where id=#{id}
    </update>

    <delete id="delete" parameterType="long">
    delete
    from t_user
    where id = #{id}
    </delete>
    <select id="queryAll" resultType="User">
    select *
    from t_user
    </select>
    <!-- <select id="queryOne" resultType="User" parameterType="Long">-->
    <!-- select *-->
    <!-- from t_user-->
    <!-- where id = #{id}-->
    <!-- </select>-->
    </mapper>
  4. 一下是测试类代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113

    public class MybatisTest {
    /**
    * 查询所有
    *
    * @throws IOException
    */
    @Test
    public void test1() throws IOException {
    String resource = "mybatis-config.xml";
    //加载配置文件
    final InputStream in = Resources.getResourceAsStream(resource);
    // 创建 sql会话工厂 SqlSessionFactory
    final SqlSessionFactory build = new SqlSessionFactoryBuilder().build(in);
    System.out.println(build);
    //获取sqlSession 对象
    final SqlSession sqlSession = build.openSession();
    System.out.println(sqlSession);
    final IUserDao mapper = sqlSession.getMapper(IUserDao.class);
    final List<User> users = sqlSession.selectList("queryAll");//写方法名
    sqlSession.close();
    // final List<User> users = mapper.queryAll();
    System.out.println(users.get(0).getName());
    users.forEach(System.out::println);
    System.out.println("ok");

    }

    /**
    * 查询一个
    *
    * @throws IOException
    */
    @Test
    public void test2() throws IOException {
    String resource = "mybatis-config.xml";
    final InputStream in = Resources.getResourceAsStream(resource);
    final SqlSessionFactory build = new SqlSessionFactoryBuilder().build(in);
    final SqlSession sqlSession = build.openSession();
    final IUserDao mapper = sqlSession.getMapper(IUserDao.class);
    final User user = mapper.queryOne(6L);
    System.out.println(user);
    }

    /**
    * 添加一个
    */
    @Test
    public void test3() throws IOException {
    String resource = "mybatis-config.xml";
    final InputStream in = Resources.getResourceAsStream(resource);
    final SqlSessionFactory build = new SqlSessionFactoryBuilder().build(in);
    final SqlSession sqlSession = build.openSession();
    // final SqlSession sqlSession = build.openSession(true);//自动提交
    final User coderyeah = new User("coderyeah", 21, true, "写代码");
    sqlSession.getMapper(IUserDao.class).add(coderyeah);
    //手动提交
    sqlSession.commit();
    sqlSession.close();
    System.out.println("ok" + coderyeah.getId());
    }

    /**
    * 更新一个
    */
    @Test
    public void test4() throws IOException {
    String resource = "mybatis-config.xml";
    final InputStream in = Resources.getResourceAsStream(resource);
    final SqlSessionFactory build = new SqlSessionFactoryBuilder().build(in);
    final SqlSession sqlSession = build.openSession();
    // final SqlSession sqlSession = build.openSession(true);//自动提交
    final User coderyeah = new User(8L, "coderyeah", 22, false, "写代码,打游戏");
    sqlSession.getMapper(IUserDao.class).update(coderyeah);
    //手动提交
    sqlSession.commit();
    sqlSession.close();
    System.out.println("ok");
    }

    @Test
    public void test5() throws IOException {
    String resource = "mybatis-config.xml";
    final InputStream in = Resources.getResourceAsStream(resource);
    final SqlSessionFactory build = new SqlSessionFactoryBuilder().build(in);
    final SqlSession sqlSession = build.openSession();
    // final SqlSession sqlSession = build.openSession(true);//自动提交

    sqlSession.getMapper(IUserDao.class).delete(9L);
    //手动提交
    sqlSession.commit();
    sqlSession.close();
    System.out.println("ok");
    }

    IUserDao dao = new UserDaoImpl();

    @Test
    public void testAll() {
    dao.queryAll().forEach(System.out::println);
    System.out.println("---------------------------");
    System.out.println(dao.queryOne(8L));
    System.out.println("---------------------------");
    final User user = new User("乔纳森.乔斯达", 25, true, "冒险");
    dao.add(user);
    System.out.println("-------------添加成功--------------"+user.getId());
    // dao.delete(10L);
    // dao.update(new User(11L,"JOJO", 19, true, "冒险,星尘十字军"));

    }


    }

七. Log4j日记实现

  1. Log4j主要用于日志信息的输出。可以将信息分级别(严重fatal、错误error、警告warn、调式debug、信息info)按不同方式(控制台、文件、数据库)和格式输出。

  2. 实现步骤:

    (1)导入log4j的jar包(3个);

    (2) 在resources下添加log4j.properties【名字不能改】;

    (3) 日志级别:debug(调试时用)、info、warn、error(运行时用);

    (4) 在日志中我们可以看到执行的SQL语句,可以看到我们传递的参数。

  3. Log4j主要有以下3部分组件构成:

    (1) 日志器(Logger):负责消息输出,提供了各种不同级别的输出方法;

    (2) 输出器(Appender):负责控制消息输出的方式,例如输出到控制台、文件输出等;

    (3) 布局器(格式器,Layout):负责控制消息的输出格式。

    (模板):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    #日志器logger #輸出器appender #布局器layout
    #1.控制台输出
    #指定日志器的输出级别和日志器的名称
    #log4j.rootLogger=info,myconsole
    #指定输出器
    #log4j.appender.myconsole=org.apache.log4j.ConsoleAppender
    #指定布局器
    #log4j.appender.myconsole.layout=org.apache.log4j.SimpleLayout

    #2.文件输出.txt
    #指定日志器的输出级别和日志器的名称
    #log4j.rootLogger=error,myfile
    #指定输出器
    #log4j.appender.myfile=org.apache.log4j.FileAppender
    #log4j.appender.myfile.File=E:\\log4j.txt
    #指定布局器(普通布局表示文本输出)
    #log4j.appender.myfile.layout=org.apache.log4j.SimpleLayout

    #3.文件输出.html
    #指定日志器的输出级别和日志器的名称
    #log4j.rootLogger=error,myhtml
    #指定输出器
    #log4j.appender.myhtml=org.apache.log4j.FileAppender
    #log4j.appender.myhtml.File=D:\\log4j.html
    #指定布局器(网页布局)
    #log4j.appender.myhtml.layout=org.apache.log4j.HTMLLayout


    #4.控制台输出+文件输出.txt
    #指定日志器的输出级别和日志器的名称
    #log4j.rootLogger=error,con,file
    #指定输出器
    #log4j.appender.con=org.apache.log4j.ConsoleAppender
    #log4j.appender.file=org.apache.log4j.FileAppender
    #log4j.appender.file.File=D\:\\log4j.txt
    #指定布局器(网页布局)
    #log4j.appender.con.layout=org.apache.log4j.SimpleLayout
    #log4j.appender.file.layout=org.apache.log4j.SimpleLayout


    #5.控制台输出+自定义布局
    log4j.rootLogger=DEBUG,my
    #指定输出器
    log4j.appender.my=org.apache.log4j.ConsoleAppender
    #指定布局器(自定义布局)
    #指定布局为自定义布局
    log4j.appender.my.layout=org.apache.log4j.PatternLayout
    #指定在自定义布局的格式,%d -- 表示当前系统时间,%t -- 执行该业务的线程名称,%p -- 日记器的级别,-5 -- 5表示输出字符的个数,符号表示右对齐
    #%c -- 表示指定业务所在的类的完全限定名(包名.类名),%m -- 输出额外信息,%n -- 表示换行
    log4j.appender.my.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
    #设置package(可以是自定义的包也可以是api的包)输出级别
    log4j.logger.org.springframework=info
    log4j.logger.com.lqs=debug

八. 面试题 #与$区别

  1. {OGNL表达式}:底层采用PreparedStatement实现,安全,预防sql注入,预编译,不会改变sql结构。

    MyBatis会把这个表达式使用?(占位符)替换,作为一个sql参数使用:推荐使用。比如name的值为:

    定义SQL: select * from t_user where name = #{name}

    最终SQL: select * from t_user where name = ?

  2. ${OGNL表达式}:底层采用Statement实现,sql字符串拼接方式,可能发生sql注入问题,会改变sql结构。

    1. MyBatis会把这个表达式的值替换到sql中,作为sql的组成部分。把获取到值直接拼接到SQL中;

    2. 如果sql中使用${OGNL},并且参数的类型是(integer、string….)那么OGNL表达式可以写成任意形式。