Mbatis

mybatis基础

一、ORM映射

  • ORM(Object Relationl Mapping),对象关系映射,即在数据库和对象之间作映射处理。
  • 即为在数据库获取数据后,转化为实体类的过程,使用ORM框架代替JDBC后,框架可以帮助程序员自动进行转换,只要像平时一样操作对象,ORM框架就会根据映射完成对数据库的操作,极大的增强了开发效率
  • orm框架代替了jdbc技术

二、MyBatis简介

MyBatis是一个半自动的ORM框架,其本质是对JDBC的封装。使用MyBatis不需要写JDBC代码,但需要程序员编写SQL语句。之前是apache的一个开源项目iBatis,2010年改名为MyBatis。

三、MyBatis条件

  • 引入依赖

    <dependencies>
        <!-- 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>8.0.26</version>
        </dependency>
        <!-- junit -->
        <dependency>
        <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
        </dependency>
        <!-- log4j -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.12</version>
        </dependency>
    </dependencies>
    
  • 创建SqlMapConfig.xml文件,存入resources文件夹之中

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
        <!-- 配置环境 -->
        <environments default="mysql">
            <environment id="mysql">
                <!-- 事务类型 -->
                <transactionManagertype="JDBC"></transactionManager>
                <!-- 数据源 -->
                <dataSource type="POOLED">
                    <property name="driver"value="com.mysql.jdbc.Driver"/>
                    <property name="url"value="jdbc:mysql:///mybatis"/>
                    <property name="username"value="root"/>
                    <property name="password"value="root"/>
                </dataSource>
            </environment>
        </environments>
    </configuration>
    

用法一:

  • 手动创建实体类

  • 在src- >main->mapper文件下创建相应的pojomapper.xml文件

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-
    mapper.dtd">
    <mappernamespace="com.zbzzs.mapper.UserMapper">
        <select id="findAll"resultType="com.zbzzs.pojo.User">
           select * from user
        </select>
    </mapper>
    
  • 将mapper文件夹注册到SqlMapConfig.xml文件中

    <!-- 注册映射文件 -->
    <mappers>
        <mapper resource="com/itbaizhan/mapper/UserMapper.xml"> </mapper>
    </mappers>
    

注意:

  • 映射文件要和接口名称相同
  • 映射文件要和接口的目录结构相同
  • 映射文件中namespace属性要写接口的全名

四、mybatis使用流程

1.引入常用依赖

<dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <!-- jsp -->
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>jsp-api</artifactId>
      <scope>provided</scope>
      <version>2.2</version>
    </dependency>
    <!-- servlet -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <scope>provided</scope> 
      <version>3.0.1</version>
    </dependency>
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter</artifactId>
      <version>RELEASE</version>
      <scope>compile</scope>
    </dependency>
    <!--  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>8.0.26</version>
    </dependency>
    <!--  log4j  -->
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.12</version>
    </dependency>
  </dependencies>

2.生成SqlMapperConfig.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="jdbc.properties"></properties>

    <environments default="mysql">
        <environment id="mysql">
            <!--  事务类型  -->
            <transactionManager type="JDBC"></transactionManager>
            <!--  数据源  -->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>


    </environments>
    <mappers>
        <package name="mapper"/>
    </mappers>
</configuration>

3.映射文件

<?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.zbzzs.mapper2.ClassesMapper2">
    <!-- 自定义映射关系   -->
    <resultMap id="MyClassesMapper" type="com.zbzzs.pojo.Classes">
        <id property="cid" column="cid"></id>
        <result property="className" column="className"></result>
        <!-- select:从表查询调用的方法  column:调用方法时传入的参数字段    -->
        <collection property="studentList"
                    ofType="com.zbzzs.pojo.Student"
                    select="com.zbzzs.mapper2.StudentMapper2.findByClassId"
                    column="cid"
                    fetchType="lazy">
        </collection>
    </resultMap>

    <select id="findAll" resultMap="MyClassesMapper">
        select * from classes
    </select>

    <select id="findByCid" resultType="com.zbzzs.pojo.Classes" parameterType="int">
        select * from classes where cid = ${cid}
    </select>
</mapper>

4.主键回填(选)

<selectKey keyProperty="id"
keyColumn="id" resultType="int"
order="AFTER">
       SELECT LAST_INSERT_ID();
    </selectKey>
@SelectKey(keyColumn = "id", keyProperty = "id", resultType = int.class,
            before = false, statement = "SELECT LAST_INSERT_ID()")
    @Insert("insert into user(username,sex,address) values(#{username},#{sex},#{address})")
    void add(User user);

5.注解式开发

@Select("select * from classes where cid = #{cid}")
    Classes findByCid(int cid);

    // 查询所有班级
    @Select("select * from classes")
    @Results(id = "classMapper", value = {
            @Result(id = true, property = "cid", column = "cid"),
            @Result(property = "className", column = "className"),
            @Result(property = "studentList", column = "cid",
                    many = @Many(select = "com.zbzzs.mapper.StudentMapper.findByClassId",
                            fetchType = FetchType.LAZY))
    })
    List<Classes> findAll();
public interface UserMapper {
    @Results(id = "userMapper",value = {
            @Result(id = true,property = "id",column = "id"),
            @Result(property = "username",column = "username1"),
            @Result(property = "sex",column = "sex1"),
            @Result(property = "address",column = "address1")
    })
    @Select("select * from user")
    List<User> findAll();

    @ResultMap("userMapper")
    @Select("select * from user where id = #{id}")
    User findById(int id);

    @SelectKey(keyColumn = "id", keyProperty = "id", resultType = int.class,
            before = false, statement = "SELECT LAST_INSERT_ID()")
    @Insert("insert into user(username,sex,address) values(#{username},#{sex},#{address})")
    void add(User user);

    @Update("update user set username = #{username},sex=#{sex},address=#{address} where id = #{id}")
    void update(User user);

    @Delete("delete from user where id = #{id}")
    void delete(int id);

    @Select("select * from user where username like #{username}")
    List<User> findByUsernameLike(String username);
@Select("select * from student")
    // 自定义映射关系
    @Results(id = "studentMapper",value = {
            @Result(id = true,property = "sid",column = "sid"),
            @Result(property = "name",column = "name"),
            @Result(property = "age",column = "age"),
            @Result(property = "sex",column = "sex"),
            /**
             * property:属性名
             * column:调用从表方法时传入的参数列
             * one:表示该属性是一个对象
             * select:调用的从表方法
             * fetchType:加载方式
             */
            @Result(property = "classes",column = "classId",
            one = @One(select = "com.zbzzs.mapper.ClassesMapper.findByCid",
            fetchType = FetchType.EAGER))
    })
    List<Student> findAll();

    // 根据班级ID查询学生
    @Select("select * from student where classId = #{classId}")
    List<Student> findByClassId(Integer classId);

6.动态sql

<select id="findByCondition" parameterType="com.zbzzs.pojo.User" resultType="com.zbzzs.pojo.User">
        select * from user
        <where>
            <if test="username != null and username.length() != 0">
                username like #{username}
            </if>
            <if test="sex != null and sex.length() != 0">
                and sex = #{sex}
            </if>
            <if test="address != null and address.length() != 0">
                and address = #{address}
            </if>
        </where>
    </select>

    <update id="updateUser" parameterType="com.zbzzs.pojo.User">
        update user
        <set>
            <if test="username != null and username.length != 0">
                username = #{username},
            </if>
            <if test="sex != null and sex.length != 0">
                sex = #{sex},
            </if>
            <if test="address != null and address.length != 0">
                address = #{address}
            </if>
        </set>
        <where>
            id = #{id}
        </where>
    </update>

    <select id="findByUsername" resultType="com.zbzzs.pojo.User" parameterType="string">
        select * from user
        <where>
            <choose>
                <when test="username.length() &lt; 5">
                    <bind name="likename" value="'%'+username+'%'"/>
                    username like #{likename}
                </when>
                <when test="username.length() &lt; 10">
                    username = #{username}
                </when>
                <otherwise>
                    id = 1
                </otherwise>
            </choose>    
        </where>
    </select>

    <delete id="deleteBatch" parameterType="int">
        delete from user
        <where>
            <foreach open="id in(" close=")" separator="," collection="array" item="id" >
                #{id}
            </foreach>
        </where>
    </delete>


    <insert id="insertBatch" parameterType="com.zbzzs.pojo.User">
        insert into user(username,sex,address) values
        <foreach collection="list" item="user" separator=",">
            (#{user.username},#{user.sex},#{user.address})
        </foreach>
    </insert>


    <select id="findUser" parameterType="map"resultType="com.zbzzs.pojo.User">
        select * from user
        <where>
            <foreach collection="queryMap" separator="and" index="key" item="value">
                ${key} = #{value}
            </foreach>
        </where>
    </select>
  • if中的条件不能使用&&/||,而应该使用and/or
  • if中的条件可以直接通过属性名获取参数POJO的属性值,并且该值可以调用方法。
  • where后为什么要加1=1?任意条件都可能拼接到Sql中。如果有多个条件,从第二个条件开始前都需要加And关键字。加上1=1这个永久成立的条件,就不需要考虑后面的条件哪个是第一个条件,后面的条件前都加And关键字即可。
  • 可以代替sql中的where 1=1 和第一个and,更符合程序员的开发习惯
  • 标签用在update语句中。借助 ,可以只对有具体值的字段进行更新。 会自动添加set关键字,并去掉最后一个if语句中多余的逗号

7.缓存(选)

  • MyBatis一级缓存也叫本地缓存(一级默认开启)。
  • SqlSession对象中包含一个Executor对象,Executor对象中包含一个PerpetualCache对象,在该对象存放一级缓存数据。由于一级缓存是在SqlSession对象中,所以只有使用同一个SqlSession对象操作数据库时才能共享一级缓存。
  • MyBatis的一级缓存是默认开启的,不需要任何的配置。
清空MyBatis一级缓存
  • SqlSession 调用 close() :操作后SqlSession对象不可用,该对象的缓存数据也不可用。
  • SqlSession 调用 clearCache() / commit() :操作会清空一级缓存数据。
  • SqlSession 调用增删改方法:操作会清空一级缓存数据,因为增删改后数据库发生改变,缓存数据将不准确。
开启二级缓存
  • 对实体类实现可序列化接口( Serializable

  • 在MyBatis配置文件添加如下设置:(默认为true,可省略

    <settings>
        <setting name="cacheEnabled" value="true"/>
    </settings>
    
  • 在映射文件添加 标签,该映射文件下的所有方法都支持二级缓存。

    <cache size="2048"/>
    
  • 注意:一级缓存对应一个SqlSession二级缓存对应一个SqlSessionFactory对象

注解式二级缓存

在持久层接口上方加注解

@CacheNamespace(blocking=true)

该接口的所有方法都支持二级缓存。

8.分解式查询

//要有相应的接口方法
public interface ClassesMapper {
    // 查询所有班级
    List<Classes> findAll();
}
public interface StudentMapper {
    // 根据班级Id查询学生
    List<Student> findByClassId(int classId);
}
<select id="findByClassId"resultType="com.zbzzs.pojo.Student" parameterType="int">
   select * from student where classId = ${classId}
</select>
<!-- 自定义映射关系   -->
<resultMap id="MyClassesMapper" type="com.zbzzs.pojo.Classes">
    <id property="cid" column="cid"></id>
    <result property="className" column="className"></result>
    <!-- select:从表查询调用的方法 column:调用方法时传入的参数字段   -->
    <collection property="studentList" ofType="com.zbzzs.pojo.Student"        
       select="com.zbzzs.mapper2.StudentMapper2.findByClassId" column="cid">
    </collection>
</resultMap> 
<select id="findAll" resultMap="MyClassesMapper">
   select * from classes
</select>

9.延迟加载(分解式查询)

  • 在 、 中添加fetchType属性设置加载方式。lazy:延迟加载;eager:立即加载。

  • 由于打印对象时会调用对象的 toString 方法, toString 方法默认会触发延迟加载的查询,所以我们无法测试出延迟加载的效果。我们在配置文件设置lazyLoadTriggerMethods属性,该属性指定对象的什么方法触发延迟加载,设置为空字符串即可

    <settings>
        <setting name="lazyLoadTriggerMethods" value=""/>
    </settings>
    

10.注解开发

  • 创建maven工程,引入依赖

  • 创建mybatis核心配置文件SqlMapConfig.xml

  • 将log4j.properties文件放入resources中,让控制台打印SQL语句

  • 创建实体类

  • 创建持久层接口,并在接口方法上定义Sql语句

  • 在核心配置文件注册持久层接口,由于没有映射文件,所以只能采用注册接口或注册包的方法

    <mappers>
        <package name="com.zbzzs.mapper"/>
    </mappers>
    
    @SelectKey(keyColumn = "id", keyProperty ="id", resultType = int.class,before = false,statement = "SELECT LAST_INSERT_ID()")
    @Insert("insert into user(username,sex,address) values(#{username},#{sex},#{address})")
    void add(User user);
    
    @Update("update user set username = #{username},sex=#{sex},address=#{address} where id = #{id}")
    
    void update(User user);
    @Delete("delete from user where id = #{id}")
    
    void delete(int id);
    @Select("select * from user where username like #{username}")
    List<User> findByUsernameLike(String username);
    

11.分页插件

  • 分页插件

    <!-- PageHelper -->
    <dependency>
        <groupId>com.github.pagehelper</groupId>
        <artifactId>pagehelper</artifactId>
        <version>5.3.0</version>
    </dependency>
    
  • Mybatis配置文件中配置PageHelper插件

    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor">
            <!-- 设置数据库类型-->
            <property name="helperDialect" value="mysql"/>
        </plugin>
    </plugins>
    
  • 使用PageHelper插件

    @Test
    public void testFindPage() {
        // (1)查询前设置分页参数,参数一:页数,从1开始。参数二:每页条数
        PageHelper.startPage(1, 3);
        // (2)正常查询
        List<User> all = userMapper.findAll();
        // (3)创建页面对象,创建时将查询结果传入构造方法
        PageInfo pageInfo = new PageInfo(all);
        // (4)打印页面对象的属性
        System.out.println("结果集:"+pageInfo.getList());
        System.out.println("总条数:"+pageInfo.getTotal());
        System.out.println("总页数"+pageInfo.getPages());
        System.out.println("当前页"+pageInfo.getPageNum());
        System.out.println("每页条数"+pageInfo.getSize());
    }
    

12. Generator_工具引入

  • 自动生成POJO类、持久层接口与映射文件,极大减少了代码的编写量,提高开发效率

  • 在pom文件中配置MBG插件

    <build>
        <plugins>
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>                               <version>1.3.7</version> <configuration> 
                <!-- MBG配置文件位置 --> 
                <configurationFile>
                    src/main/resources/generatorConfig.xml
                </configurationFile > 
                <!-- 运行显示详情 -->
                <verbose>true</verbose> 
                <!-- 允许覆盖文件 --> 
                <overwrite>true</overwrite> 
                </configuration> 
            </plugin> 
        </plugins> 
    </build>
    
  • 编写MBG配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
    
    
    <generatorConfiguration>
        <!-- jdbc的jar包位置,插件需要连接数据库 -->  
      <classPathEntry location="D:\Repository\mysql\mysql-connector-java\8.0.26\mysql-connector-java-8.0.26.jar"/>
      
      <context id="default" targetRuntime="MyBatis3">
        <!-- 是否去除自动生成的注释-->
        <commentGenerator>
          <property name="suppressAllComments" value="true"/>
        </commentGenerator>
        
        <!--数据库连接参数-->
        <jdbcConnection driverClass="com.mysql.jdbc.Driver"
                connectionURL="jdbc:mysql://localhost:3306/mybatis"
                userId="root"
                password="root">
          </jdbcConnection>
          
        <!-- 类型处理器,在数据库类型和java类型之间的转换控制-->
        <javaTypeResolver>
          <property name="forceBigDecimals" value="false"/>
        </javaTypeResolver>
    
    
        <!-- targetProject:JAVA类路径  targetProject:生成的POJO类的包-->
        <javaModelGenerator targetProject="src/main/java" targetPackage="com.zbzzs.pojo">
          <!-- 是否生成子包 -->
          <property name="enableSubPackages" value="false"/>
          <!-- 设置是否在getter方法中,对String类型字段调用trim()方法 -->
          <property name="trimStrings" value="true"/>
        </javaModelGenerator>
    
    
        <!-- targetProject:配置文件路径 targetPackage:生成映射文件的位置 -->
        <sqlMapGenerator targetProject="src/main/resources" targetPackage="com.zbzzs.mapper">
          <!-- 是否生成子包 -->
          <property name="enableSubPackages" value="false"/>
        </sqlMapGenerator>
    
    
        <!-- targetPackage:JAVA类路径 targetProject:生成的持久层接口包 -->
        <javaClientGenerator targetProject="src/main/java" targetPackage="com.zbzzs.mapper" type="XMLMAPPER">
          <!-- 是否生成子包 -->
          <property name="enableSubPackages" value="false"/>
        </javaClientGenerator>
    
        <!-- 数据库表,表名不要和其他库中的表名一样 -->
        <table tableName="product"></table>
      </context>
    </generatorConfiguration>
    
  • 运行插件,自动生成POJO,持久层接口,映射文件:

  • 在配置文件中注册生成的映射文件

  • 使用案例

    public class TestMBG {
      InputStream is = null;
      SqlSession session = null;
      ProductMapper productMapper = null;
    
    
      @Before
      public void before() throws IOException {
        is = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(is);
        session = factory.openSession();
        productMapper = session.getMapper(ProductMapper.class);
       }
    
    
      @After
      public void after() throws IOException {
        session.close();
        is.close();
       }
    
    
      // 新增
      @Test
      public void testAdd(){
        Product product = new Product("百战Python课", 15000.0);
        productMapper.insert(product);
        session.commit();
       }
      // 修改
      @Test
      public void testUpdate(){
        Product product = new Product(5,"百战Python课", 25000.0);
        productMapper.updateByPrimaryKey(product);
        session.commit();
       }
      // 删除
      @Test
      public void testDelete(){
        productMapper.deleteByPrimaryKey(5);
        session.commit();
       }
    
    }
    
    
    // 根据id查询
    @Test
    public void testFindById() {
      Product product = productMapper.selectByPrimaryKey(1);
      System.out.println(product);
    }
    
    
    // 查询所有
    @Test
    public void testFindAll() {
      // 查询扩展对象,可以构建查询条件
      ProductExample productExample = new ProductExample();
      List<Product> products = productMapper.selectByExample(productExample);
      products.forEach(System.out::println);
    }
    
    // 根据商品名查询
    @Test
    public void testFindByName(){
      // 查询扩展对象,可以构建查询条件
      ProductExample productExample = new ProductExample();
      // 构建查询条件
      ProductExample.Criteria criteria = productExample.createCriteria();
      criteria.andProductnameLike("%尚学堂%");
      // 查询
      List<Product> products = productMapper.selectByExample(productExample);
      products.forEach(System.out::println);
    }
    
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值