myBatis入门程序介绍

前言

Mybaits框架也称为对象关系映射(ORM)框架,它通过描述java对象与数据库表之间映射关系,自动的将java应用程序中的对象持久化到关系型数据库中。这些功能的完成主要依赖两种配置文件,主配置文件(通常叫做:mybaits-config.xml)和完成关系与对象映射文件(一般为Mapper.xml),前者主要目的是告诉框架,要创建一个什么样数据库会话(包括:数据库连接信息、是否使用二级缓存、连接池、懒加载、mapper文件位置等);后者则具体处理数据库表与对象映射关系和数据的持久化问题。

myBaits主配文件

myBaits的主配文件,一般存放在src\main\resources文件夹下,并且需要将resources设置为Resources,此时配置文件将生成在程序的根目录下。如下图:
myBatis入门程序介绍_第1张图片
主配置文件是要说明创建一个什么样用于进行持久化对象的,其主要内容代码如下:


DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    
    <properties resource="db.properties" />
    <settings>
        
        <setting name="lazyLoadingEnabled" value="true" />
        
        <setting name="aggressiveLazyLoading" value="false"/>
     
    settings>
    
    <typeAliases>
        <package name="com.bjwl.pojo" />
    typeAliases>
    
    <environments default="mysql">
        
        <environment id="mysql">
            
            <transactionManager type="JDBC" />
            
            <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>
        <mapper resource="com/bjwl/mapper/IdCardMapper.xml" />
        <mapper resource="com/bjwl/mapper/PersonMapper.xml" />
        <mapper resource="com/bjwl/mapper/UserMapper.xml" />
    mappers>
configuration>

主配文件由configuration标签完成,并通过“http://mybatis.org/dtd/mybatis-3-config.dtd”对其中元素的定义、元素之间的规则、属性等进行约束。
核心配置项:environments 标签中配置数据库环境信息,如驱动、URL、连接池、事务等内容,在;通过mappers配置Mapper的位置信息;这两个配置项是主配文件的核心,缺一不可。以下几个配置项是可选配置项
可选配置项:在setting进行全局参数设定,如:二级缓存使用、懒加载、主键生成策略等,标签完成,通常我们使用myBatis提供的默认值即可,无需进行配置,除非你有特殊要求。通过typeAliases配置类的别名,可有可无,如果有时做映射文件可以使用别名,没有使用全限定类名即可;properties是一个配置属性的元素,该元素通常用来将内部的配置外在化,即通过外部的配置来动态的替换内部定义的属性,当配置文件很复杂或者某一些配置项在其他地方还要使用,使用它完成。如上例中,将数据库配置放到外面,其中db.properties文件如下:

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://xx.xx.xxx.xxx:3306/sl?serverTimezone=GMT%2B8
jdbc.username=root
jdbc.password=xxxxx

通过配置文件框架构造一个sqlsessionFactoryBulider对象,用于生成sqlSessionFactory对象,而sqlSessionFactory可以构造出sqlsession对象,myBaits所有的持久化操作是通过sqlsession对象完成的,这几个对象具体使用在此不做具体说明。

映射文件

关系与对象映射文件(mapper.xml)是myBatis的核心技术,程序员使用这个框架,主要的工作就在此处;数据库的增加、删除、修改、查询及对象与关系的映射集中在此进行配置,由框架完成相应的转换。


DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.bjwl.dao.StudentDao">
    <cache/>
    <select id="getList" flushCache="false" resultType="com.bjwl.pojo.StudentEntity">
        select * from student
    select>
    <insert id="addStudent" parameterType="com.bjwl.pojo.StudentEntity">
        insert into student(sno,sname,sage) values(#{sno},#{sName},#{sAge})
    insert>
mapper>

该文件使用mapper包裹的一组属性配置,也通过“http://mybatis.org/dtd/mybatis-3-config.dtd”对其中元素的定义、元素之间的规则、属性等进行约束。select、insert、update、delete分别对应的数据库的查询、增加、修改和删除。每个标签中id是方法的名字,在一个xml文件必须是唯一的,不可或缺;parameterType代表传入参数类型、resultType(resultMap)代表输出的结果Java类型,可以为string、整型、实体对象或实体对象集合,用于将查询结果映射到Java对象上,resultType 和resultMap在一个标签中只能使用一个,resultMap一般用于复杂对象的匹配;其他为选配项:如、标签中的、不再详细说明。

示例

为了说明问题,使用以下示例代码完成,首先创建数据表
人员(person)和身份证(idcard)一对一,二者相互参照

--人员表
CREATE TABLE `person` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  `sex` varchar(50) DEFAULT NULL,
  `card_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `FK_person` (`card_id`),
  CONSTRAINT `FK_person` FOREIGN KEY (`card_id`) REFERENCES `idcard` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
)
--身份证表
CREATE TABLE `idcard` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `code` varchar(50) DEFAULT NULL,
  `person_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `FK_idcard` (`person_id`),
  CONSTRAINT `FK_idcard` FOREIGN KEY (`person_id`) REFERENCES `person` (`id`)
)

用户(user)、订单(orders),一个用户有多个订单(一对多),其SQL语句如下

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(100) DEFAULT NULL,
  `address` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`)
)

CREATE TABLE `orders` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `number` varchar(50) DEFAULT NULL,
  `user_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `FK_orders` (`user_id`),
  CONSTRAINT `FK_orders` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)
) 

订单(orders)和产品(product),一个订单有多个产品,一个产品有多个订单(多对多),多对多关系产生一个关联表(ordersitem),此两个表的SQl语句如下

CREATE TABLE `product` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) DEFAULT NULL,
  `price` double DEFAULT NULL,
  PRIMARY KEY (`id`)
)

CREATE TABLE `ordersitem` (
  `order_id` int(11) NOT NULL,
  `product_id` int(11) NOT NULL,
  PRIMARY KEY (`order_id`,`product_id`),
  KEY `FK_ordersitem123` (`product_id`),
  CONSTRAINT `FK_ordersitem` FOREIGN KEY (`order_id`) REFERENCES `orders` (`id`),
  CONSTRAINT `FK_ordersitem123` FOREIGN KEY (`product_id`) REFERENCES `product` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
)

产生上述表的ER模型为:
myBatis入门程序介绍_第2张图片
创建maven工程,如果没有maven环境,需下载各种jar包,自行导入jar包即可。在pom文件中配置mybaits、mysql、单元测试、日志输出的坐标,pom依赖代码如下:

  <dependencies>
    <dependency>
      <groupId>org.mybatisgroupId>
      <artifactId>mybatisartifactId>
      <version>3.5.1version>
    dependency>
    <dependency>
      <groupId>mysqlgroupId>
      <artifactId>mysql-connector-javaartifactId>
      <version>8.0.16version>
    dependency>
    <dependency>
      <groupId>junitgroupId>
      <artifactId>junitartifactId>
      <version>4.11version>
      <scope>testscope>
    dependency>
    <dependency>
      <groupId>org.junit.jupitergroupId>
      <artifactId>junit-jupiter-apiartifactId>
      <version>RELEASEversion>
      <scope>compilescope>
    dependency>
    <dependency>
      <groupId>org.junit.jupitergroupId>
      <artifactId>junit-jupiter-apiartifactId>
      <version>RELEASEversion>
      <scope>compilescope>
    dependency>
    <dependency>
      <groupId>log4jgroupId>
      <artifactId>log4jartifactId>
      <version>1.2.17version>
    dependency>
  dependencies>

工程目录如下图所示:
myBatis入门程序介绍_第3张图片
pojo包下存放实体类,数据库中实体对象一对一、一对多、多对多的关系映射为实体之间类与类之间的关联关系。如下人员和身份证关系映射代码如下:

public class Person {
    private Integer id;
    private String name;
    private Integer age;
    private String sex;
    private IdCard card;  //个人关联的证件
    //以下省略get set
    @Override
    public String toString() {
        return "Person [id=" + id + ", name=" + name + ", "
                + "age=" + age + ", sex=" + sex + ", card=" + card + "]";
    }
}

public class IdCard {
    private Integer id;
    private String code;
    //以下省略get set
    @Override
    public String toString() {
        return "IdCard [id=" + id + ", code=" + code + "]";
    }
}

用户与订单、订单与产品则被映射为对象集合,代码如下:

public class User {
    private Integer id;                 // 用户编号
    private String username;           // 用户姓名
    private String address;            // 用户地址
    private List<Orders> ordersList; //用户关联的订单
    
    @Override
    public String toString() {
        return "User [id=" + id + ", username=" + username + ", address="
                + address + ", ordersList=" + ordersList + "]";
    }
}

public class Orders {
    private Integer id;    //订单id
    private String number;//订单编号
    //关联商品集合信息
    private List<Product> productList;
    
    @Override
    public String toString() {
        return "Orders [id=" + id + ", number=" + number + ", productList=" + productList + "]";
    }
}

public class Product {
    private Integer id;  //商品id
    private String name; //商品名称
    private Double price;//商品单价
    private List<Orders> orders; //与订单的关联属性
    
    @Override
    public String toString() {
        return "Product [id=" + id + ", name=" + name
                + ", price=" + price + "]";
    }
}

在mapper创建映射文件,由于几乎每个实体内,包含其他的实体或实体集合,使用resultMap完成对象与结果集的映射;数据查询方式也分两种,一种是嵌套查询映射,根据前一条查询结果,根据连接字段做第二次、第三次查询,嵌套一次执行一次查询语句;一种是嵌套结果映射,通过sql关联将结果全部取出,然后根据resultmap定义的映射完成匹配。
association标签:实体类中引用的是单个实体,我们使用association标签,如:查询人员及身份证信息代码如下。

<?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.bjwl.mapper.PersonMapper">
    <!-- 嵌套查询:通过执行另外一条SQL映射语句来返回预期的特殊类型 -->
    <select id="findPersonById" parameterType="Integer"
            resultMap="IdCardWithPersonResult">
        SELECT * from person where id=#{id}
    </select>
    <resultMap type="Person" id="IdCardWithPersonResult">
        <id property="id" column="id" />
        <result property="name" column="name" />
        <result property="age" column="age" />
        <result property="sex" column="sex" />
        <!-- 一对一:association使用select属性引入另外一条SQL语句 -->
        <association property="card" column="card_id" javaType="IdCard" fetchType="lazy"
                     select="com.bjwl.mapper.IdCardMapper.findCodeById" />
    </resultMap>

    <!-- 嵌套结果:使用嵌套结果映射来处理重复的联合结果的子集 -->
    <select id="findPersonById2" parameterType="Integer"
            resultMap="IdCardWithPersonResult2">
        SELECT p.*,idcard.code,idcard.id as cardid
        from person p,idcard idcard
        where p.card_id=idcard.id
          and p.id= #{id}
    </select>
    <resultMap type="Person" id="IdCardWithPersonResult2">
        <id property="id" column="id" />
        <result property="name" column="name" />
        <result property="age" column="age" />
        <result property="sex" column="sex" />
        <association property="card" javaType="IdCard">
            <id property="id" column="cardid" />
            <result property="code" column="code" />
        </association>
    </resultMap>
</mapper>

association使用select属性引入另一条SQL语句,com.bjwl.mapper.IdCardMapper.findCodeById,代码如下:

<mapper namespace="com.bjwl.mapper.IdCardMapper">
    
    <select id="findCodeById" parameterType="Integer" resultType="IdCard">
        SELECT * from idcard where id=#{id}
    select>
mapper>

执行findPersonById第一个查询结果如下图:
myBatis入门程序介绍_第4张图片
执行findPersonById2第一个查询结果如下图
在这里插入图片描述
collection标签:实体类中引用的是实体集合,我们使用collection标签。如:一个订单中可能包括多个产品的集合。

<mapper namespace="com.bjwl.mapper.OrdersMapper">
    <!-- 多对多嵌套查询:通过执行另外一条SQL映射语句来返回预期的特殊类型 -->
    <select id="findOrdersWithProduct" parameterType="Integer"
            resultMap="OrdersWithProductResult">
        select * from orders WHERE id=#{id}
    </select>
    <resultMap type="Orders" id="OrdersWithProductResult">
        <id property="id" column="id" />
        <result property="number" column="number" />
        <collection property="productList" column="id" ofType="Product"
                    select="com.bjwl.mapper.ProductMapper.findProductById">
        </collection>
    </resultMap>

    <!-- 多对多嵌套结果查询:查询某订单及其关联的商品详情 -->
    <select id="findOrdersWithProduct2" parameterType="Integer"
            resultMap="OrdersWithProductResult2">
        select o.*,p.id as pid,p.name,p.price
        from tb_orders o,tb_product p,tb_ordersitem  oi
        WHERE oi.orders_id=o.id
          and oi.product_id=p.id
          and o.id=#{id}
    </select>
    <!-- 自定义手动映射类型 -->
    <resultMap type="Orders" id="OrdersWithProductResult2">
        <id property="id" column="id" />
        <result property="number" column="number" />
        <!-- 多对多关联映射:collection -->
        <collection property="productList" ofType="Product">
            <id property="id" column="pid" />
            <result property="name" column="name" />
            <result property="price" column="price" />
        </collection>
    </resultMap>
</mapper>

为了去除每次测试程序中,都需要写创建sqlsessionfactoryBulider和sqlsessionfactory,写一个工具类完成,在utils包下,创建静态类MybatisUtils,代码如下:

public class MybatisUtils {
    public static SqlSessionFactory sqlSessionFactory = null;
    // 初始化SqlSessionFactory对象
    static{
        try {
            //使用MyBatis提供的Resources类加载mybatis的配置文件
            Reader reader = Resources.getResourceAsReader("myBatis_config.xml");
            //构建sqlSession的工厂
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    // 获取SqlSession对象的静态方法
    public static SqlSession getSession(){
        return sqlSessionFactory.openSession();
    }
}

在test包下,写测试类MybatisAssociatedTest,代码如下:

public class MybatisAssociatedTest {
    /**
     * 嵌套查询
     */
    @Test
    public void findPersonByIdTest() {
        // 1、通过工具类生成SqlSession对象
        SqlSession session = MybatisUtils.getSession();
        // 2.使用MyBatis嵌套查询的方式查询id为1的人的信息
        Person person = session.selectOne("com.bjwl.mapper."
                + "PersonMapper.findPersonById", 2);
        // 3、输出查询结果信息
        System.out.println(person);
        // 4、关闭SqlSession
        session.close();
    }

    @Test
    public void findPersonByIdTest2() {
        // 1、通过工具类生成SqlSession对象
        SqlSession session = MybatisUtils.getSession();
        // 2.使用MyBatis嵌套结果的方法查询id为1的人的信息
        Person person = session.selectOne("com.bjwl.mapper."
                + "PersonMapper.findPersonById2", 1);
        // 3、输出查询结果信息
        System.out.println(person);
        // 4、关闭SqlSession
        session.close();
    }

    @Test
    public void findUserTest() {
        // 1、通过工具类生成SqlSession对象
        SqlSession session = MybatisUtils.getSession();
        // 2、查询id为1的用户信息
        User user = session.selectOne("com.bjwl.mapper."
                + "UserMapper.findUserWithOrders", 1);
        // 3、输出查询结果信息
        System.out.println(user);
        // 4、关闭SqlSession
        session.close();
    }

    /**
     * 多对多
     */
    @Test
    public void findOrdersTest(){
        // 1、通过工具类生成SqlSession对象
        SqlSession session = MybatisUtils.getSession();
        // 2、查询id为1的订单中的商品信息
        Orders orders = session.selectOne("com.bjwl.mapper."
                + "OrdersMapper.findOrdersWithProduct", 1);
        // 3、输出查询结果信息
        System.out.println(orders);
        // 4、关闭SqlSession
        session.close();
    }
}

注意:运行程序时,会报找不到mapper.xml文件的错误,此时需要在pom文件标签增加一个resources项即可。

<resources>
      <resource>
        <directory>src/main/javadirectory>
        <includes>
          <include>**/*.xmlinclude>
        includes>
      resource>
    resources>

拓展与小结

映射文件是mybatis框架的核心,在正式开发中通常使用嵌套结果查询来完成,查询的条件又要使用到动态SQL,内容复杂知识点多,需要多做练习巩固。以上示例我们使用的mybaits一种方式,在实际开发中通常使用的是通过动态代理方式,变更非常简单。主要变化有三点,其一,将mapper.xml文件放到resources目录下,在java包中定义接口,接口的方法与mapper.xml的id严格对应;
myBatis入门程序介绍_第5张图片
其二,在主配文件把包路径换成目录路径;
myBatis入门程序介绍_第6张图片
其三,通过代理对象完成数据库操作。
myBatis入门程序介绍_第7张图片

你可能感兴趣的:(myBatis介绍,数据库,java,mysql)