Mybatis学习

mybatis3官方中文文档

https://mybatis.org/mybatis-3/zh/getting-started.html

 

一、使用Mybatis

1、添加依赖

     <!--mybatis依赖-->
        <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.7</version>
        </dependency>

     <!--mysql依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.25</version>
        </dependency>

        <!--junit依赖,测试用-->
        <!-- https://mvnrepository.com/artifact/junit/junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.1</version>
            <scope>test</scope>
        </dependency>

 

2、创建配置文件mybatis-config.xml(用于构建SqlSessionFactory)

<?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://localhost:3306/mybatis?useUnicode=true&amp;characterEncoding=utf-8"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>

  //为接口类注册 <mappers> <mapper class="com.chen.dao.UserMapper"/> </mappers> </configuration>

 

3、创建一个借口类UserMapper 

public interface UserMapper {
    //查询所有用户
    List<User> getUserList();

    //根据id查询用户
    User getUserById(int id);

    //新增一个用户
    int insertUser(User user);

    //修改一个用户
    int updateUser(User user);

    //删除一个用户
    int deleteUser(int id);
}

 

 

4、为接口类添加实现类,这里mybatis使用xml映射SQL语句(也可以通过注解定义)

创建同名xml文件(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.chen.dao.UserMapper">


    <!--id对应接口的方法名,resultType返回值类型,parameterType参数类型-->
    <!--注意标签的使用,增删改查语句对应的标签不要用错-->
    <!--参数类型一般使用三种: 基本数据类型, 对象, map-->
    <!--基本数据类型可以省略不设置-->
    <!--对象类型,可直接通过#{属性名}取得-->
    <!--map类型,可通过#{key}取得,优点:一是可以DIY名字,对象类型取值时只能通过属性名取得,而
    key可随便取名,二是当对象属性太多或者数据库表字段太多时,sql update语句等得写完全部字段,而
    map可以只写需要的几个字段
    -->
    <select id="getUserList" resultType="com.chen.pojo.User">
        select *
        from mybatis.user
    </select>

    <select id="getUserById" resultType="com.chen.pojo.User" parameterType="int">
        select *
        from mybatis.user
        where id = #{id}
    </select>

    <insert id="insertUser" parameterType="com.chen.pojo.User">
        insert into mybatis.user (id, name, pwd)
        values (#{id}, #{name}, #{pwd})
    </insert>

    <update id="updateUser" parameterType="com.chen.pojo.User">
        update mybatis.user
        set name = #{name},
            pwd  = #{pwd}
        where id = #{id};
    </update>

    <delete id="deleteUser" parameterType="int">
        delete
        from mybatis.user
        where id = #{id}
    </delete>
</mapper>

 

5、使用并测试

  为了方便一般将得到SqlSession的过程封装成工具类

  编写MybatisUtils工具类

public class MybatisUtils {

    private static SqlSessionFactory sqlSessionFactory;

    static {
        try {
            //XML 中构建 SqlSessionFactory
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static SqlSession getSqlSession() {
        return sqlSessionFactory.openSession();
    }
}

测试

public class UserMapperTest {
    @Test
    public void getUserListTest(){
        
        //注意!!!增删改一定要提交事务,如后几个方法
        
        //使用时先获取SqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();

        //通过SqlSession对象获得想要使用的接口,有另外一种方法可以获得,但不推荐
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        
        //接口运行对应方法
        List<User> userList = mapper.getUserList();
        for (int i = 0; i < userList.size(); i++) {
            System.out.println(userList.get(i).toString());
        }
        
        //记得一定要关闭连接
        sqlSession.close();
    }

    @Test
    public void getUserByIdTest(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = mapper.getUserById(1);
        System.out.println(user.toString());
        sqlSession.close();
    }

    @Test
    public void insertUserTest(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        System.out.println(mapper.insertUser(new User(7, "李四", "123456")));
        sqlSession.commit();
        sqlSession.close();
    }

    @Test
    public void updateUserTest(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        System.out.println(mapper.updateUser(new User(4, "王五", "1234565")));
        sqlSession.commit();
        sqlSession.close();

    }

    @Test
    public void deleteUser(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        System.out.println(mapper.deleteUser(5));
        sqlSession.commit();
        sqlSession.close();
    }
}

目录结构

Mybatis学习

 

 

使用到的三个类

SqlSessionFactoryBuilder

这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。 因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)。 你可以重用 SqlSessionFactoryBuilder 来创建多个 SqlSessionFactory 实例,但最好还是不要一直保留着它,以保证所有的 XML 解析资源可以被释放给更重要的事情。

SqlSessionFactory

SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。 使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,多次重建 SqlSessionFactory 被视为一种代码“坏习惯”。因此 SqlSessionFactory 的最佳作用域是应用作用域。 有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。

SqlSession

每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。 绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。 也绝不能将 SqlSession 实例的引用放在任何类型的托管作用域中,比如 Servlet 框架中的 HttpSession。 如果你现在正在使用一种 Web 框架,考虑将 SqlSession 放在一个和 HTTP 请求相似的作用域中。 换句话说,每次收到 HTTP 请求,就可以打开一个 SqlSession,返回一个响应后,就关闭它。 这个关闭操作很重要,为了确保每次都能执行关闭操作,你应该把这个关闭操作放到 finally 块中。

 

注意:

mybatis-config.xml里面的标签顺序要按规定顺序放,不然会报错

 

二、配置之属性优化

MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。 配置文档的顶层结构如下:

上面的值大多数用不到,了解即可,下面几个要会用

属性(properties)

这些属性可以在外部进行配置,并可以进行动态替换。既可以在典型的 Java 属性文件(如db.propertis)中配置这些属性,也可以在 properties 元素的子元素中设置。

 

创建db.propertis

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=false&useUnicode=true&characterEncoding=utf-8
username=root
password=123456

 

这样在mybatis-config.xml文件中配置数据源就可以直接使用db.propertis中的值,如:(可配置多套环境,但只能使用一套,environment 设置)

<?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"/>
    <environments default="development">
        <environment id="development">
            <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>
        <environment id="test">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&amp;characterEncoding=utf-8"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper class="com.chen.dao.UserMapper"/>
    </mappers>
</configuration>

 

也可以同时使用Java 属性文件(如db.propertis)和标签同时配置。比如:(属性文件优先级更高)

<properties resource="db.properties"> 
  <property name="username" value="dev_user"/>
  <property name="password" value="F2Fa3!33TYyg"/>
</properties>

 

三、配置值别名优化

类型别名(typeAliases)

类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。例如:

<typeAliases>
  <typeAlias alias="User" type="com.chen.pojo.User"/>
</typeAliases>

当这样配置时,User可以用在任何使用 com.chen.pojo.User的地方。

 

也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean,比如:

<typeAliases>
  <package name="com.chen.pojo"/>
</typeAliases>

设置后会自动扫描指定包下的bean,且生成默认别名,为类名首字母小写;若有注解,则别名为其注解值。见下面的例子:

@Alias("hello")
public class User{
    ...
}

 实体类少时可以使用第一种方式,多时建议使用第二种方式,扫描包名。

 

四、设置(settings)

这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。 下表描述了设置中各项设置的含义、默认值等。

可能用到的设置:

Mybatis学习

 

 

 Mybatis学习

 

 

 

Mybatis学习

 

 

 

一个配置完整的 settings 元素的示例如下:

<settings>
  <setting name="cacheEnabled" value="true"/>
  <setting name="lazyLoadingEnabled" value="true"/>
  <setting name="multipleResultSetsEnabled" value="true"/>
  <setting name="useColumnLabel" value="true"/>
  <setting name="useGeneratedKeys" value="false"/>
  <setting name="autoMappingBehavior" value="PARTIAL"/>
  <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
  <setting name="defaultExecutorType" value="SIMPLE"/>
  <setting name="defaultStatementTimeout" value="25"/>
  <setting name="defaultFetchSize" value="100"/>
  <setting name="safeRowBoundsEnabled" value="false"/>
  <setting name="mapUnderscoreToCamelCase" value="false"/>
  <setting name="localCacheScope" value="SESSION"/>
  <setting name="jdbcTypeForNull" value="OTHER"/>
  <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>

 

五、映射器(mappers)

mapperRegistry:注册我们绑定的Mapper文件;

方式一:使用相对于类路径的资源引用 (推荐使用)

   <!--    每一个mapper文件都要在mybatis核心配置文件中注册-->
    <mappers>
        <mapper resource="com/chen/dao/UserMapper.xml"/>
    </mappers>

方式二:使用class文件绑定注册

    <!--    每一个mapper文件都要在mybatis核心配置文件中注册-->
    <mappers>
        <mapper class="com.chen.dao.UserMapper"/>
    </mappers>

  注意点:

    • 接口和他的mapper配置文件必须同名
    • 接口和他的mapper配置文件必须在同一个文件夹下,或者在resources文件夹下建立相同的路径。      

方式三:使用扫描包进行注入绑定

   <!--    每一个mapper文件都要在mybatis核心配置文件中注册-->
    <mappers>
        <package name="com.chen.dao"/>
    </mappers>

  注意点:

    • 接口和他的mapper配置文件必须同名
    • 接口和他的mapper配置文件必须在同一个文件夹下,或者在resources文件夹下建立相同的路径。  

 

六、生命周期

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

SqlSessionFactoryBuilder

  • 一旦常见了SqlSessionFactory,就不在需要它了
  • 局部变量

SqlSessionFactory

  • 说白了就是可以想象成为:数据库连接池;
  • SqlSessionFactory一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或者重新创建另一个实例
  • 因此它的最佳作用域是应用作用域。
  • 最简单的就是使用单例模式或者静态单例模式。

SqlSession

  • 连接到连接池的一个请求;
  • SqlSession的实例不是线程安全的,因此不能被共享的,所以它的最佳作用域是请求或者方法作用域
  • 使用后需要赶紧关闭,否则资源被占用。

 

七、解决属性名和字段名不一致的问题

  解决方法:

    1、起别名

    2、ResultMap

        结果集映射

id               id
name             name
password         pwd
   <resultMap id="UserMap" type="user">
        <result column="id" property="id"/>
        <result column="name" property="name"/>
        <result column="pwd" property="password"/>
    </resultMap>

    <select id="getUserById" resultMap="UserMap" parameterType="int">
        select *
        from mybatis.user
        where id = #{id}
    </select>
      • resultMap 元素是 MyBatis 中最重要最强大的元素。

 

八、日志

 8.1、日志工厂

如果一个数据库操作出现了异常,我们需要排错,日志就是最好的助手。

曾经:sout、debug

现在:日志工厂。

Mybatis学习

 

  •  SLF4J 
  • LOG4J 【掌握】
  • LOG4J2
  • JDK_LOGGING
  • COMMONS_LOGGING
  • STDOUT_LOGGING  【掌握】
  • NO_LOGGING

在mybatis中具体使用哪一个日志实现,在设置中设定;

STDOUT_LOGGING 标准日志输出 

 <settings>
      <setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>

Mybatis学习

 8.2、LOG4J

什么事log4g?

  • Log4j是Apache的一个开源项目;
  • 可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;
  • 可以控制每一条日志的输出格式;
  • 通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。
  • 这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。

1.    先导包

<!-- https://mvnrepository.com/artifact/log4j/log4j -->
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.17</version>
    </dependency>

2、log4j.properties

#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
log4j.rootLogger=DEBUG,console,file

#控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n

#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/chen.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n

#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG

3、配置log4j为日志的实现

<settings>
    <setting name="logImpl" value="LOG4J"/>
</settings>

简单使用

1、在要使用log4j的类中,导入包 import org.apache.log4j.Logger;

2、日志对象,参数为当前类的class;

static Logger logger = Logger.getLogger(UserMapperTest.class); //括号里的是当前类

3、日志级别

logger.info("info,进入logger!");
logger.debug("debug,进入logger!");
logger.error("error,进入logger!");

 

 

 

 

 

 

 

 

 

 

 

 

 

       

 

上一篇:Java-Log4j配置


下一篇:MyBatis-日志工厂