MyBatis(二)动态代理及XML配置

上篇文章中介绍了MyBatis的用法,在Mapper.xml中通过sql语句的唯一标识id去执行对应的sql语句,但是你应该也发现了其中的问题的,就是当你去调用的时候,你必须回到Mapper.xml文件中去复制id,然后又要回去看看参数是什么类型的。

所以MyBatis又提出了动态代理

我们只需要为MyBatis提供一个Mapper接口:在接口中书写Mapper.xml文件中对应的sql的方法。

但是该Mapper接口中的方法不是随意编写的,必须按照以下几个要求编写:

  • 方法名必须与sql语句中的id一致;
  • 参数类型必须一样;
  • 返回值类型必须一样;
  • Mapper.xml中的namespace书写该Mapper接口的全称限定名。

此时的项目结构:

ProductsMapper.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="mapper.ProductsMapper">

    <select id="selectProductById" parameterType="int" resultType="pojos.Products">
        select * from products where pid = #{pid};
    </select>

<!--    like模糊查询-->
    <select id="selectProductsLikePname" parameterType="String" resultType="pojos.Products">
        select * from products where pname like "%${pname}%";
    </select>

    <insert id="insertProducts" parameterType="pojos.Products" keyProperty="pid" useGeneratedKeys="true">
        insert into products (pname,price,pdate,cid) values (#{pname},#{price},#{pdate},#{cid});
    </insert>

    <delete id="deleteProductById" parameterType="int">
        delete from products where pid = #{pid};
    </delete>

<!--    修改要先获得原来的数据,再进行修改,参数为JavaBean-->
    <update id="updateProductById" parameterType="pojos.Products">
        update products set pname = #{pname} where pid = #{pid};
    </update>
</mapper>

ProductsMapper接口:

package mapper;

import pojos.Products;

import java.util.List;

public interface ProductsMapper {

    public Products selectProductById(int pid);
    public List<Products> selectProductsLikePname(String pname);
    public int insertProducts(Products products);
    public int deleteProductById(int pid);
    public int updateProductById(Products products);

}

测试:

通过session对象去获取对应的mapper对象,再通过mapper对象去调用方法,此时因为是调用方法,就可以根据idea的提示来书写方法名和方法所需要的参数了。

import mapper.ProductsMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import pojos.Products;

import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;


public class Test02 {
    @Test
    public void test01(){
        SqlSession session = null;
        String resource = "mybatis-config.xml";
        try {
            InputStream inputStream = Resources.getResourceAsStream(resource);
            session = new SqlSessionFactoryBuilder().build(inputStream).openSession();
            ProductsMapper mapper = session.getMapper(ProductsMapper.class);
            //根据主键查询单条数据
            Products product =  mapper.selectProductById(1);
            System.out.println(product);

            //模糊查询,结果为多条数据
            List<Products> products = mapper.selectProductsLikePname("新疆");
            for (Products product1 : products) {
                System.out.println(product1);
            }

            //插入数据
            Products p = new Products();
            p.setPname("野核桃");
            p.setPdate(new Date());
            p.setPrice(99);
            p.setCid("s002");
            int insert = mapper.insertProducts(p);
            session.commit();
            System.out.println(insert);
            System.out.println(p.getPid());

            //删除数据
            int delete = mapper.deleteProductById(9);
            session.commit();
            System.out.println(delete);

            //修改数据,要先获取原来的数据再进行修改
            Products product2 = mapper.selectProductById(8);
            product.setPname("芒果");
            int update = mapper.updateProductById(product2);
            session.commit();
            System.out.println(update);

        } catch (IOException e) {
            if(session != null){
                session.rollback();
            }
            e.printStackTrace();
        }finally {
            if(session != null){
                session.close();
            }
        }
    }
}

mybatis-config.xml中mappers的四种映射方式

每次只能使用一个,否则配置文件会报错。,但是里面可以放置多个

<!--    根据类路径下的文件路径(相对路径)-->
<mappers>
    <mapper resource="mapper/ProductsMapper.xml"/>
</mappers>

<!--    根据绝对路径(少用)-->
<mappers>
    <mapper url="F:\mybatis_code\src\main\resources\mapper\ProductsMapper.xml"/>
</mappers>

<!--    根据Mapper接口的全称类名-->
<!--    这种方式要求Mapper接口和Mapper.xml处于同一种目录下-->
<!--    如:ProductsMapper接口在包com.mapper下,那么必须在resource下新建目录com/mapper,然后放入ProductsMapper.xml-->
<mappers>
    <mapper class="mapper.ProductsMapper"/>
</mappers>

<!--    根据Mapper接口所在的包-->
<!--    该方式和第三种方式一样:要求Mapper接口和Mapper.xml处于同一种目录下-->
<mappers>
    <package name="mapper"/>
</mappers>

mybatis-config.xml配置properties

因为在mybatis.xml文件中需要填写一些与数据库有关的值,如driver、url、username、password,如果直接在配置文件中书写值,后续会不太好修改,所以可以将值放在属性中,在需要的地方使用${key}取值即可。

又可以分为内部属性和外部属性:

<properties>
    <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
</properties>

<!--   外部属性配置,引入外部的属性文件 -->
<properties resource="jdbc.properties"/>

可以同时配置,但是当出现同名时,会优先使用外部属性。

<properties resource="jdbc.properties">
    <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
</properties>

mybatis-config.xml配置typeAliases

parameterType和resultType的数据类型为JavaBean时,需要书写类的全称限定名,但是写来写去的就很烦,所以mybatis提供了typeAliases配置:

<typeAliases>
    <typeAlias type="pojos.Products" alias="products"/>
</typeAliases>

这样就不需要书写类的全称限定名,而是可以使用简单的alias别名了。

但是如果JavaBean很多的时候,这样一个个去配置的话就太麻烦了,所以MyBatis又贴心的给我们提供了另外一种方式:

将某个包下的所有的JavaBean的别名配置成类名小写字母开头:

<typeAliases>
    <package name="pojos"/>
</typeAliases>

可以配置多个包。

问题也就来了,不同包下的类是可以同名的,如果不同包下有同名的类,产生重名的话就会有冲突,所以这个时候我们就要使用@Aliase注解:

@Alias("别名")

并且还需要注意的是,MyBatis已经存在了一些别名,我们取的时候不能和它们冲突(可以查看MyBatis文档有哪些已经存在的)

posted @ 2021-03-13 22:05  deng-hui  阅读(346)  评论(0编辑  收藏  举报