MyBatis

本文详细介绍了MyBatis框架的入门步骤,包括环境搭建、配置文件解析、Mapper接口与XML配置文件的编写,以及如何实现CRUD操作。通过实例展示了如何使用MyBatis进行数据库交互,强调了其简单灵活、SQL与程序代码分离的特点,以及如何处理实体类属性与数据库字段不一致的问题。此外,还探讨了日志配置与分页实现,以及注解开发的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

MyBatis入门

MyBatis是一款优秀的持久层框架

支持定制SQL、存储过程以及高级映射;避免了JDBC代码、手动设置参数和获取结果集

MyBatis可使用xml配置文件与注解来配置和映射原生类型、接口和Java的POJO实体类为数据库中的记录

三层架构

img

应用开发三层架构:

表现层:MVC模式;Model模型-实体类,用于数据的封装与数据的传输;View视图-GUI,用于展示数据;Control控制器-事件,用于流程控制

业务层:事务脚本模式;将一个业务中所有的操作封装成一个方法,同时保证方法中所有的数据库更新操作,即保证同时成功或同时失败。避免部分成功部分失败引起的数据混乱操作。

持久层:DAO模式;建立实体类与数据库表映射,一个类对应一个表,一个属性对应一个列,目的是完成对象数据与关系数据的转换

持久层

MyBatis作为一个持久层框架,目的就是完成持久层中数据持久化的操作,即将内存中存储的断电即失的对象数据持久化的保存到数据库中去

特点

简单灵活、SQL与程序代码分离

  • 提供映射标签:支持对象与数据库的ORM字段关系映射
  • 提供对象关系映射标签:支持对象关系组建维护
  • 提供xml标签:支持编写动态SQL

第一个MyBatis程序

  • 搭建环境

    1. 新建普通Maven项目(检查Maven是否使用本地Maven)
    2. 删除src目录作为父工程使用
    3. 导入Maven依赖
  • 创建模块

    1. 在父工程文件目录右键新建一个model,选择maven工程

    2. 在子模块的main目录下resource目录新建mybatis-config.xml

      • XML配置文件:包含获取数据库连接实例的数据源(DataSource)和决定事务范围和控制方式的事务管理器

        示例:
        <?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>
            <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="637625"/>
                    </dataSource>
                </environment>
            </environments>
        </configuration>
        
  • MyBatisUtils工具类

    基于MyBatis的应用都是以一个SqlSessionFactory的实例为核心,通过SqlSessionFactoryBuilder从xml配置文件的Configuration实例数据库连接中构建出SqlSessionFactory实例

    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 MyBatisUtils {
        private static SqlSessionFactory sqlSessionFactory
        //获取sqlSessionFactory对象,从而生产sqlsession实例
        static{
    
            try {
                String resource = "mybatis-config.xml";
                InputStream inputStream = Resources.getResourceAsStream(resource);
                SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        //取得sqlsession的工厂类后,获取sqlsession实例
        //sqlsession包含了面向数据库执行SQL命令所需的所有方法
        public static SqlSession getSqlSession(){
            return sqlSessionFactory.openSession();
        }
    }
    
  • 实现代码

    1. 实体类

      创建与数据库表对应的实例类,表名对应类名,列名对应属性

      • IDEA:alt+insert快捷键生成有参构造、无参构造、属性的getter于setter以及toString方法,按住ctrl键实现参数多选

        例:
        public class User {
            private int id;
            private String name;
        
            public User() {
            }
        
            public User(int id, String name) {
                this.id = id;
                this.name = name;
            }
        
            public int getId() {
                return id;
            }
        
            public void setId(int id) {
                this.id = id;
            }
        
            public String getName() {
                return name;
            }
        
            public void setName(String name) {
                this.name = name;
            }
        
            @Override
            public String toString() {
                return "user{" +
                        "id=" + id +
                        ", name='" + name + '\'' +
                        '}';
            }
        }
        
        
        
    2. Mapper接口

      编写基于一个表操作的Mapper接口,定义操作方法

      public interface UserMapper {
          List<User> getUserList();
      }
      
    3. Mapper配置文件

      新建一个对应Mapper接口的Mapper配置文件,由Mapper.xml配置文件绑定Mapper接口,实现接口中定义的方法

      <?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:命名空间属性,绑定对应的Dao接口-->
      <mapper namespace="com.flagling.dao.UserDao">
      
          <select id="getUserList" resultType="com.flagling.pojo.User">
          select * from users where id = 1
        </select>
          
      </mapper>
      

      namespace绑定Mapper接口,在mapper标签中实现接口对应的数据库操作,id为数据库操作对应的方法名,resultType为返回结果集的一种类型,可指定为对应的实体类

      • 在MyBatis-config配置文件中添加Mapper映射

            <mappers>
                <mapper resource="com/flagling/mapper/UserMapper.xml"/>
            </mappers>
        
      • Java目录下的Mapper配置文件不一定会被Maven扫描成功,因此需要在父项目与子项目中添加资源过滤的代码

            <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>
        
    4. 测试

      规范:在test包中创建与main对应的目录结构,在对应的dao目录下创建接口的test类

      • 调用MyBatisUtils工具类获得SqlSession对象

      • SqlSession对象调用getMapper方法,取得Mapper接口的实现类,再调用实现类的方法执行sql语句

      • 关闭sqlsession

        public class UserDaoTest {
            @Test
            public void  test(){
                //调用MyBatisUtils工具类获得SqlSession对象
                SqlSession sqlSession = MyBatisUtils.getSqlSession();
               //执行sql
               //方式一:getMapper
                UserDao userdao = sqlSession.getMapper(UserDao.class);
                List<User> userList = userdao.getUserList();
        
                for(User user : userList){
                    System.out.println(user);
                }
                //关闭sqlsession
                sqlSession.close();
            }
        }
        
  • CRUD

    完成基础的查询之后,功能的增添只与Mapper接口及其配置文件Mapper.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:命名空间属性,绑定对应的Dao接口-->
    <mapper namespace="com.flagling.dao.UserMapper">
    
        <select id="getUserList" resultType="com.flagling.pojo.User">
        select * from mybatis.user;
      </select>
    </mapper>
    
    1. namespace:命名空间属性,绑定Mapper接口

    2. select:

      id:对应namespace中的方法名

      resultType:sql语句的返回值类型,一般可设置为对应的实体类

      parameterType:参数类型,在SQL语句中参数为#{参数所属的列值}

          <select id="getUserById" parameterType="int" resultType="com.flagling.pojo.User">
              select * from mybatis.user where id = #{id};
          </select>
      
    3. insert:

          <insert id="addUser" parameterType="com.flagling.pojo.User">
              insert into mybatis.user (id, name) VALUES (#{id},#{name});
          </insert>
      
      • parameterType为Mapper接口的方法定义传递参数类型,sql语句的参数取值直接与对象的属性名相对应,格式为#{name}

      • 增删改需要提交事务才能完成数据库操作,在代码中为调用sqlsession的commit方法

      userdao.addUser(new User(5,"老王"));
      sqlSession.commit();//提交事务
      
    4. delete

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

          <update id="updateUser" parameterType="com.flagling.pojo.User">
              update mybatis.user set name = #{name} where id = #{id}
          </update>
      
    6. Map对象

      当实体类或数据库中表的字段或参数过多时,应当考虑使用Map替换实体类对象作为方法参数使用,在Mapper配置文件中,参数类型写为map,sql语句中参数名为对应的key,这样可以直接取出map集合中key对应的value值

      Map<String ,Object> map = new HashMap<String , Object>;
      map.put("id",1);
      map.put("name","老李");//定制化map集合,直接取key对应的value值
      mapper.addUser(map);//直接传递map集合,
      
    7. 模糊查询

      1. 在Java代码执行时,传递参数左右加通配符%:%参数%

        List<User> userlist = mapper.getUserLike("%参数%");
        
      2. 在sql拼接中使用通配符

        select * from user where name like "%"#{value}"%"
        
  • 配置解析

    • Mybatis-config.xml作为MyBatis的核心配置文件,其中包含了会影响MyBatis行为的设置与属性信息
    1. 环境配置

      <environments default="development">
              <environment id="development">
                  <transactionManager type="JDBC"/>
                  <dataSource type="POOLED">
                      <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                      <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF8&amp;serverTimezone=Asia/Shanghai"/>
                      <property name="username" value="root"/>
                      <property name="password" value="637625"/>
                  </dataSource>
              </environment>
          </environments>
      

      可以配置多个环境,但在使用时每个SqlSessionFactory实例只能选择一种环境

      • <transactionManager type=""/>为MyBatis的事务管理器,MyBatis中有两种事务管理器
        1. JDBC:直接使用了JDBC的提交与回滚设施
        2. MANAGED:不回滚或提交一个连接,而是让容器管理事务的整个生命周期,已过时
      • dataSource:数据源,即连接数据库操作,MyBatis中有三种内建的数据源类型
        1. UNPOOLED:非连接池连接
        2. POOLED:连接池
        3. JNDI
    2. 属性:properties

      编写一个外部配置文件: db.properties

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

      通过properties引入外部配置文件

      <properties resource="db.properties">
      <property name="username" value="root"/>
      <property name="password" value="637625"/>
      </properties>
      
      <configuration>
        <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>
        </environments>
        <mappers>
          <mapper resource="org/mybatis/example/BlogMapper.xml"/>
        </mappers>
      </configuration>
      

      在环境配置中自动读取外部配置文件的值,同时还可以手动添加属性配置,但优先级低于外部配置文件,若同时定义一个字段两个值会优先使用外部配置文件的属性值

    3. 设置:setting

      一个配置完整的setting元素示例:

      <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>
      
      • cacheEnabled:全局开启或关闭缓存
      • logImpl:指定MyBatis日志具体实现,未指定时将自动查找
    4. 类型别名:typeAliases

      类型别名是为Java类型设置一个短名,存在的意义在于用来减少类完全限定名的冗余

      • 方式1:手动指定一个实体类的别名

        <typeAliass>
            <typeAlias type="com.flagling.pojo.User" alias="User"/>
        </typeAliass>
        
      • 方式2:自动扫描一个包下的所有实体类,默认设置一个别名为实体类名的首字母小写格式,若有注解则别名为其注解值

        <typeAlias>
            <package name="com.flagling.pojo"/>
        </typeAlias>
        
        @Alias("User")//注解别名
        public Class User{
           
        }
        
    5. 映射器

      注册绑定Mapper接口的配置文件

      方式1:

      <!-- 使用相对于类路径的资源引用 -->
      <mappers>
        <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
      </mappers>
      

      方式2:

      <!-- 使用映射器接口实现类的完全限定类名 -->
      <mappers>
        <mapper class="org.mybatis.builder.AuthorMapper"/>
      </mappers>
      
      • 采用方式2时,Mapper接口及配置文件必须同名且必须在同一个包下,否则会加载失败

      方式3:

      <!-- 将包内的映射器接口实现全部注册为映射器 -->
      <mappers>
        <package name="org.mybatis.builder"/>
      </mappers>
      
      • 采用方式3时与方式2一样,Mapper接口及配置文件必须同名且在同一个·包下,否则会加载失败
    6. 解决实体类属性名与数据库字段不一致问题

      当实体类属性与数据库表中字段一致时,类型处理器自动转译查找数据库表,当属性与字段不一致时,数据库表中无该属性名字段,则会获得null值

      image-20200927132035507

      解决方法:

      1. SQL起别名:(不建议)

        select id name as username from mybatis.user where id = #{id};
        
      2. ResultMap:结果集映射

        在Mapper配置文件中配置对应的结果集映射,再在sql操作中选择resultmap,简易使用如下

        结果集映射:

            <resultMap id="UserMap" type="User">//id为sql调用时的ID,type为映射的实体类别名
                <result column="id" property="id"/>//column为数据库表的列字段,property为实体类对应的属性
                <result column="name" property="username"/>         
            </resultMap>
        

        sql调用:

          <select id="getUserList" resultMap="UserMap">//选择返回结果集映射及对应的ID
            select * from mybatis.user;
          </select>
        

        结果:

        image-20200927134917487

  • 日志

    • 若一个SQL数据库操作出现了异常,需要进行排错,MyBatis提供的最好方式即是提供日志进行排错

      image-20200927144416309

    1. 日志工厂

      掌握

      LOG4J:需先在父项目导包

      STDOUT_LOGGING:标准日志工厂实现,无需导包

      设置:在MyBatis配置文件中settings中设置

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

      效果:

      image-20200927145142456

    2. LOG4J

      • 父项目pom.xml导包:

        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        
      • 子项目MyBatis配置文件配置

            <settings>
                <setting name="logImpl" value="LOG4J"/>
            </settings>
        
      • LOG4J可以使用log4j.properties配置文件进行各种详细的设置

        一个典型的配置文件:

        #将等级为DEBUG的日志信息输出到confole与file
        log4j.rootLogger=DEBUG,console,file
        #console输出相关设置
        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
        #file输出相关设置
        log4j.appender.file = org.apache.log4j.RollingFileAppender
        log4j.appender.file.File = ./log/project.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
        
      • 测试运行
        image-20200927195416742

      • 简单使用

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

        2. 创建静态日志对象,参数为当前类的class属性

          static Logger log = Logger.getLogger(UserMapper.class);
          
        3. 常用日志级别

                  log.info("info:进入testlog4j");
                  log.debug("debug:进入testlog4j");
                  log.error("error:进入testlog4j");
          
  • 分页

    Limit实现分页

    方法中创建一个HashMap存放分页起始地址startIndex与页面数据数量pageSize

            HashMap<String, Integer> userMap = new HashMap<String, Integer>();
            userMap.put("startIndex",1);
            userMap.put("pageSize",2);
    

    Mapper配置文件中设置对应参数类型为map,设置对应结果集映射

        <select id="getUserLimit" parameterType="map" resultMap="UserMap">
            select * from mybatis.user limit #{startIndex},#{pageSize}
        </select>
    

    HashMap中前两个元素键key必须与sql中参数名一致

  • 注解开发

    注解开发直接在接口的抽象方法上实现

        @Select("select * from user")
        List<User> getUserList();
    

    需要在核心配置文件绑定接口

        <mappers>
            <mapper class = "com.flagling.dao.UserMapper"/>
        </mappers>
    

    注解开发使用反射获得接口的class对象,得到接口完整的结构,反向推导调用方法,但MyBatis使用注解开发无法解决实体类属性与数据库表列名不对应的问题。

    底层:动态代理‘

    • 注解CRUD

      1. 查询:

        @select("select * from user where id = #{id}")
        User getUserById(@Param("id") int id);
        

        在Mapper中通过注解开发,所有的参数必须通过@Param注解将参数与指定字段进行关联映射,再于sql语句中取值,只要二者对应即可成功取值

      2. 添加:

        @Insert("insert into user(id,name) values (#{id},#{name})");
        int addUser(User user);
        
      3. 修改

        @Update("update user set name = #{name} where id = #{id}")
        int updateUser(User user);
        
      4. 删除

        @Delete("delete from user where id = #{uid}")
        int deleteUser(@Param("uid") int id);
        
      5. 事务提交

        在工具类中可设置CRUD操作自动提交事务,否则CRUD操作不会生效

        public static SqlSession  getSqlSeaaion(){
            return sqlSessionFactory.openSession(true)//openSession方法重载,传递一个布尔值true表示打开自动提交事务
        }
        
      6. #{}与${}

        #{}类似预编译,可以防止SQL注入,${}直接拼接

     ```java
     @Insert("insert into user(id,name) values (#{id},#{name})");
     int addUser(User user);
     ```
    
    1. 修改

      @Update("update user set name = #{name} where id = #{id}")
      int updateUser(User user);
      
    2. 删除

      @Delete("delete from user where id = #{uid}")
      int deleteUser(@Param("uid") int id);
      
    3. 事务提交

      在工具类中可设置CRUD操作自动提交事务,否则CRUD操作不会生效

      public static SqlSession  getSqlSeaaion(){
          return sqlSessionFactory.openSession(true)//openSession方法重载,传递一个布尔值true表示打开自动提交事务
      }
      
    4. #{}与${}

      #{}类似预编译,可以防止SQL注入,${}直接拼接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值