Mybatis

Mybatis

1、什么是Mybatis?

  • 历史

    • MyBatis 本是apache的一个开源项目iBatis

    • 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis

    • 2013年11月迁移到Github

  • 定义

    • 一个基于Java的持久层框架

    • 支持定制化 SQL、存储过程以及高级映射

    • 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集

    • 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和  Java 的 Pojos(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录

  • Mybatis相关资料

    • maven仓库

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

      Github地址

    • 官网文档

      官网中文文档地址

2、持久化和持久层

  • 持久化

    • 把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘)

    • 持久化的主要应用是将内存中的对象存储在数据库中,或者存储在磁盘文件中、XML数据文件中等等

    • 持久化是将程序数据在持久状态和瞬时状态间转换的机制

    • JDBC就是一种持久化机制,文件IO也是一种持久化机制

  • 持久层

    • 完成持久化工作的代码块

3、第一个Mybatis程序

  • 环境搭建

    • 建数据库以及表

    • 新建Maven项目后在pom.xml中导入依赖

      <!--mysql依赖--><dependency>    <groupId>mysql</groupId>    <artifactId>mysql-connector-java</artifactId>    <version>5.1.47</version></dependency>?<!--mybatis依赖--><dependency>    <groupId>org.mybatis</groupId>    <artifactId>mybatis</artifactId>    <version>3.5.2</version></dependency>?<!--Lombok依赖--><dependency>    <groupId>org.projectlombok</groupId>    <artifactId>lombok</artifactId>    <version>1.18.12</version></dependency>
  • 编写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核心配置文件--><configuration>        <!--可以配置多种环境,如开发、测试,default指定用的是哪种环境-->    <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?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>                <property name="username" value="root"/>                <property name="password" value="root"/>            </dataSource>        </environment>    </environments></configuration>
  • 编写Mybatis工具类

    • 1、构建SqlSessionFactory

      • 每个基于Mybatis的应用都是以一个SqlSessionFactory的实例为核心的

      • SqlSessionFactoryBuilder可以从XML配置文件或者一个预先定制的Configuration的实例构建出SqlSessionFactory的实例

        • 使用任意的输入流(InputStream)实例,通过字符串形式的文件路径,或者url形式的文件路径配置

        • Resources工具类可使从classpath或其他位置加载资源文件更加容易

    • 2、从SqlSessionFactory中获取SqlSession

      • SqlSession 提供了在数据库执行 SQL 命令所需的所有方法

      • SqlSession 实例来直接执行已映射的 SQL 语句

    • SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession 的生命周期和作用域

      • SqlSessionFactoryBuilder

        • 一旦创建了 SqlSessionFactory,就不再需要SqlSessionFactoryBuilder了

        • 最佳作用域是方法作用域(也就是局部方法变量)

      • SqlSessionFactory

        • 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃SqlSessionFactory或重新创建另一个实例

        • 最佳作用域是应用作用域,最简单的就是使用单例模式或者静态单例模式

      • SqlSession

        • 每个线程都应该有它自己的 SqlSession 实例

        • 最佳的作用域是请求或方法作用域

    public class MybatisUtils {?    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    public static SqlSession getSqlSession(){        return sqlSessionFactory.openSession();    }}
  • 编写代码

    • 实体类

      @Data@NoArgsConstructor@AllArgsConstructorpublic class User {?    private Integer id;    private String name;    private String pwd;}
    • Dao接口,UserMapper

      public interface UserMapper {    List<User> getUserList();}
    • 接口实现类,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">?<!--namespace,绑定一个对应的mapper接口--><mapper namespace="com.hmx.dao.UserMapper">        <!--        id:sql语句对应的执行的方法名        resultType:返回结果,要写全限命名    -->    <select id="getUserList" resultType="com.hmx.pojo.User">        select * from mybatis.mybatistest    </select></mapper>
    • 在mybatis的配置文件中给每个Mapper.xml配置mapper

      <!--每一个Mapper.xml都需要在核心配置文件中注册--><mappers>    <mapper resource="com/hmx/dao/UserMapper.xml"/></mappers>
    • 测试

      public class UserMapperTest {    public static void main(String[] args) {?        //第一步:获得SqlSession对象        SqlSession sqlSession = MybatisUtils.getSqlSession();?        //获得mapper,执行sql语句        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);        List<User> userList = userMapper.getUserList();?        //输出结果        for (User user : userList) {            System.out.println(user);        }                //关闭SqlSession        sqlSession.close();    }}
    • 注意点:常见错误

      • Type interface com.hmx.dao.UserDao is not known to the MapperRegistry

        原因:Mapper.xml没有在核心配置文件中注册

        解决:在mybatis的配置文件中给每个Mapper.xml配置mapper

        <!--每一个Mapper.xml都需要在核心配置文件中注册--><mappers>    <mapper resource="com/hmx/dao/UserMapper.xml"/></mappers>
      • Could not find resource com/hmx/dao/UserMapper.xml

        原因:资源导入失败,Maven导出资源问题

        解决:在pom.xml中配置如下代码

        <build>    <resources>        <resource>            <directory>src/main/resources</directory>            <includes>                <include>**/*.properties</include>                <include>**/*.xml</include>            </includes>            <filtering>true</filtering>        </resource>        <resource>            <directory>src/main/java</directory>            <includes>                <include>**/*.properties</include>                <include>**/*.xml</include>            </includes>            <filtering>true</filtering>        </resource>    </resources></build>
      • com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException: 1 字节的 UTF-8 序列的字节 1 无效

        原因:xml编码问题

        解决:

        1、在pom.xml中配置如下代码

        <properties>    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties>

        若方法1没用,参考

        2、把每个xml文件的文件头

        <?xml version="1.0" encoding="UTF-8" ?>

        改为:

        <?xml version="1.0" encoding="UTF8" ?>

4、增删改查

  • 实体类:User

    @Data@NoArgsConstructor@AllArgsConstructorpublic class User {?    private Integer id;    private String name;    private String pwd;}
  • 接口类:UserMapper

    public interface UserMapper {?    //查询所有数据    List<User> getUserList();    //根据id查询数据    User selectById(int id);    //增加数据    int insertUser(User user);    //更新数据    int updateUser(User user);    //删除数据    int deleteUser(int id);}
  • 接口类的实现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"><!--namespace绑定一个mapper接口--><mapper namespace="com.hmx.dao.UserMapper">?    <select id="getUserList" resultType="com.hmx.model.User">        select * from mybatis.mybatistest;    </select>?    <select id="selectById" parameterType="int" resultType="com.hmx.model.User">        select * from mybatis.mybatistest where id = #{id};    </select>?    <insert id="insertUser" parameterType="com.hmx.model.User">        insert into mybatis.mybatistest (id,name,pwd) values (#{id},#{name},#{pwd});    </insert>?    <update id="updateUser" parameterType="com.hmx.model.User">        update mybatis.mybatistest set name = #{name},pwd = #{pwd} where id = #{id};    </update>?    <delete id="deleteUser">        delete from mybatis.mybatistest where id = #{id};    </delete></mapper>
  • 测试

    //查询所有数据public static void selectAll(){?    //第一步:获得SqlSession对象    SqlSession sqlSession = MybatisUtils.getSqlSession();    //执行sal语句    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);    List<User> userList = userMapper.getUserList();    for (User user : userList) {        System.out.println(user);    }    //关闭SqlSession    sqlSession.close();}?//根据id查询数据public static void selectById(){    SqlSession sqlSession = MybatisUtils.getSqlSession();?    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);    User user = userMapper.selectById(1);    System.out.println(user);?    sqlSession.close();}?//添加数据public static void insertUser(){    SqlSession sqlSession = MybatisUtils.getSqlSession();?    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);    userMapper.insertUser(new User(9,"大黄","123"));    sqlSession.commit();?    sqlSession.close();}?//修改数据public static void updateUser(){    SqlSession sqlSession = MybatisUtils.getSqlSession();?    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);    userMapper.updateUser(new User(4,"大黑子","333"));    sqlSession.commit();?    sqlSession.close();}?//删除数据public static void deleteUser(){    SqlSession sqlSession = MybatisUtils.getSqlSession();?    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);    userMapper.deleteUser(9);    sqlSession.commit();?    sqlSession.close();}

5、注解实现增删改查

  • Mybatis注解作用:

    • 使用注解来映射简单语句会使代码显得更加简洁

    • 但对于稍微复杂一点的语句,Java 注解不仅力不从心,还会让你本就复杂的 SQL 语句更加混乱不堪

    • 因此,如果你需要做一些很复杂的操作,最好用 XML 来映射语句

  • mybatis注解本质

    • 本质:反射机制

    • 底层:动态代理模式

  • 注意点:

    • 注解写在接口类中的方法上

    • 使用注解开发不需要写接口的实现类(XXXMapper.xml)文件,所以在配置文件中需要绑定XXXMapper.java

      <mappers>    <mapper class="com.hmx.mapper.UserMapper"/></mappers>
  • @Param()注解

    • 方法中只有一个参数,可加可不加,最好加,多个参数必须加

    • 基本类型和String类型需要加上

    • 和sql语句中引用的#{}相匹配

  • 增删改查

    public interface UserMapper {?    //查询所有数据    @Select("select * from mybatis.mybatistest")    List<User> getUserList();        //根据id查询数据    @Select("select * from mybatis.mybatistest where id = #{id}")    User selectById(@Param("id") int id);        //增加数据    @Insert("insert into mybatis.mybatistest (id,name,pwd) values (#{id},#{name},#{pwd})")    int insertUser(User user);        //更新数据    @Update("update mybatis.mybatistest set name = #{name},pwd = #{pwd} where id = #{id}")    int updateUser(User user);        //删除数据    @Delete("delete from mybatis.mybatistest where id = #{id};")    int deleteUser(@Param("id") int id);}

6、Mybatis配置文件解析

configuration核心配置文件中包含了会深深影响 MyBatis 行为的设置和属性信息,可以配置如下配置:

  • properties(属性)

    • 可以直接引入外部文件

      <properties resource="db.properties"/>
      #db.propertiesdriver=com.mysql.jdbc.Driverurl=jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8username=rootpassword=root
    • 如果db.properties中没有配置username和password,则可以可以在properties中增加一些属性配置

      <properties resource="db.properties">    <property name="username" value="root"/>    <property name="password" value="root"/></properties>
    • 如果两个配置文件和properties中存在同一字段,如:都含有username这个字段但是值不一样,优先使用外部配置文件

  • settings(设置)

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

      <settings>  1、<!--全局地开启或关闭所有映射器配置文件中已配置的任何缓存,有效值true|false,默认true-->  <setting name="cacheEnabled" value="true"/>      2、<!--       延迟加载的全局开关。       当开启时,所有关联对象都会延迟加载。       特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。       有效值true|false,默认false    -->  <setting name="lazyLoadingEnabled" value="true"/>      3、<!--是否允许单个语句返回多结果集(需要数据库驱动支持),有效值true|false,默认true-->  <setting name="multipleResultSetsEnabled" value="true"/>      4、<!--        使用列标签代替列名        实际表现依赖于数据库驱动,具体可参考数据库驱动的相关文档,或通过对比测试来观察        有效值true|false,默认true     -->  <setting name="useColumnLabel" value="true"/>      5、<!--        允许 JDBC 支持自动生成主键,需要数据库驱动支持        如果设置为 true,将强制使用自动生成主键        尽管一些数据库驱动不支持此特性,但仍可正常工作(如 Derby)        有效值true|false,默认false    -->  <setting name="useGeneratedKeys" value="false"/>      6、<!--         指定 MyBatis 应如何自动映射列到字段或属性。        NONE 表示关闭自动映射        PARTIAL 只会自动映射没有定义嵌套结果映射的字段        FULL 会自动映射任何复杂的结果集(无论是否嵌套)        默认值为PARTIAL    -->  <setting name="autoMappingBehavior" value="PARTIAL"/>      7、<!--        指定发现自动映射目标未知列(或未知属性类型)的行为。        NONE: 不做任何反应        WARNING: 输出警告日志        FAILING: 映射失败 (抛出 SqlSessionException)        默认值为NONE    -->  <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>      8、<!--        配置默认的执行器        SIMPLE 就是普通的执行器        REUSE 执行器会重用预处理语句(PreparedStatement)        BATCH 执行器不仅重用语句还会执行批量更新        默认值为SIMPLE-->  <setting name="defaultExecutorType" value="SIMPLE"/>      9、<!--        设置超时时间,它决定数据库驱动等待数据库响应的秒数        有效值为任意正整数 默认未设置 (null)    -->  <setting name="defaultStatementTimeout" value="25"/>      10、<!--        为驱动的结果集获取数量(fetchSize)设置一个建议值,此参数只可以在查询设置中被覆盖。        有效值为任意正整数 默认未设置 (null)    -->  <setting name="defaultFetchSize" value="100"/>

相关推荐