MyBatis持久层框架详解

一、什么是MyBatis

MyBatis是一个实现了数据持久化的开源框架。简单理解就是对JDBC进行封装。

MyBasic优点:

  • 和JDBC相比,减少了50%以上的代码量

  • MyBatis是最简单的持久化框架,小巧且简单

  • MyBatis相当灵活,不会对应用程序或者数据库的现有设计强加任何影响,SQL卸载XML里,从程序代码中彻底分离,降低耦合度,便于统一管理和优化,并可重复使用

  • 提供XML标签,支持编写动态SQL语句

  • 提供映射标签,支持对象与数据库的ORM字段关系映射

MyBatis缺点:

  • SQL语句的编写工作量较大,尤其是字段多、关联表多的时候。对开发人员编写SQL语句有一定的要求

  • SQL语句依赖于数据库,导致数据库一致性差,不能随意更换数据库

二、三层架构

表现层:用于展示数据

业务层:用于处理业务需求

持久层:和数据库进行交互

三、MyBatis的环境配置

1、新建项目

(我在创建的时候出现了maven-clean-plugun报红,解决方案参考链接)

2、环境配置

pom.xml添加配置

// 添加MySQL配置
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.29</version>
</dependency>

// 添加oracle配置
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.2.2</version>
</dependency>

// 添加MyBatis配置
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.2.2</version>
</dependency>

resource设置为资源根目录

在resource下添加配置文件

database.properties文件

添加MySQL和Oracle配置参数

mysqldriver=com.mysql.cj.jdbc.Driver
mysqlurl=jdbc:mysql://192.168.153.134:3306/new?allowMultiQueries=true
mysqluser=root
mysqlpwd=123123
oracleDriver=oracle.jdbc.driver.OracleDriver
oracleUrl=jdbc:oracle:thin:@192.168.153.136:1521:prod
oracleuser=scott
oraclepwd=123123
mybatis-config.xml文件

通过mybatis-config文件连接MySQL/Oracle文件,模板如下:

mapper配置中可以使用相对路径,也可以使用绝对路径。由于版本不同,相对路径的书写方式也有所区别。

<?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="database.properties"></properties>

    <typeAliases>
        <package name="org.example.pojo"/>
    </typeAliases>

    <environments default="mysqlDev">
        <environment id="mysqlDev">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="${mysqldriver}"/>
                <property name="url" value="${mysqlurl}"/>
                <property name="username" value="${mysqluser}"/>
                <property name="password" value="${mysqlpwd}"/>

            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="org.example.dao/DogDao.xml"/>
        
    </mappers>

</configuration>
mybatis-config中配置mapper映射路径
方法一:
<mappers>
    <package name="org.example.dao" />
</mappers>

方法二:
<mappers>
    <mapper resource="org.example.dao/DogDao.xml"/>       
</mappers>

方法三:
<mappers>
    <mapper url="file:///D:\Servers\KB21\Java\mybatisstu\src\resource\org.example.dao\DogDao.xml"/>
</mappers>

test类-定义工厂模式

public class DogTest {
    // 工厂模式
    SqlSessionFactory sqlSessionFactory=null;
    // 定义会话
    SqlSession sqlSession = null;
    // 定义DogDao对象
    DogDao dogDao = null;

    @Before
    public void init(){
        System.out.println("Start");
        // 加载mybatis_config.xml配置文件
        InputStream inputStream = DogTest.class.
                getClassLoader().
                getResourceAsStream("mybatis-config.xml");
        // 获取builder建造工厂
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        // 通过建造工厂来建造SqlSessionFactory
        sqlSessionFactory = builder.build(inputStream);
        // 创建Session会话
        sqlSession = sqlSessionFactory.openSession();
        // 获取Session会话的执行者
        dogDao = sqlSession.getMapper(DogDao.class);

    }

    @Test
    public void showInfo(){
        System.out.println(sqlSessionFactory);
        System.out.println(sqlSession);
        System.out.println(dogDao);
    }

    @After
    public void down(){
        sqlSession.commit();
        sqlSession.close();
        System.out.println("Over");
    }
}

如果能正常显示,则可以继续测试方法是否可以执行

四、SQL语句编写

1、增删改语句编写

定义DogDao接口

在接口中定义方法

public interface DogDao {
    int save(Dog dog);
    int update(Dog dog);
    int delete(Dog dog);

<!--批量操作-->
    int batchDelete(List<Integer> dogID);
    int batchAdd(List<Dog> dogs);
    int batchUpdate(List<Dog> dogs);
}

编写SQL语句DogDao.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="org.example.dao.DogDao">

    <insert id="save">
        insert into dog(name,health,love,strain,lytm)
        values(#{name},#{health},#{love},#{strain},now())
    </insert>

    <update id="update">
        update dog
        set name=#{name},health=#{health}
        where id=#{id}
    </update>

    <delete id="delete">
        delete from dog where id=#{id}
    </delete>

    <delete id="batchDelete">
        delete from dog where id in <foreach collection="list" item="id" open="(" close=")" separator=",">
        #{id}
    </foreach>
    </delete>

    <sql id="tableName">dog</sql>
    <insert id="batchAdd">
        insert into <include refid="tableName"/>
        values
            <foreach collection="list" item="dog" separator="," >
            (null,#{dog.name},#{dog.health},#{dog.love},#{dog.strain},now())
            </foreach>
    </insert>


    <update id="batchUpdate">

        <foreach collection="list" item="dog" separator=";">
            update
            <include refid="tableName"/>
            <set>
                <if test="dog.name!=null and dog.name!='' ">
                    name=#{dog.name},
                </if>
                <if test="dog.health!=null">
                    health=#{dog.health},
                </if>
                <if test="dog.love!=null">
                    love=#{dog.love},
                </if>
                <if test="dog.strain!=null and dog.strain!='' ">
                    strain=#{dog.strain},
                </if>
            </set>
            where id=#{dog.id}
        </foreach>
    </update>


</mapper>

2、动态编写SQL语句

在上面的insert语句中,我们插入字段的时候只能按照指定字段进行插入,这样的写法所有字段都必须填写。如果有字段不需要填写,这种写法显然不合适,需要进行升级。

DogDao.xml

<!--动态新增-->
    <insert id="add">
        insert into dog
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="name!=null and name!=''">
                name,
            </if>
            <if test="health!=null">
                health,
            </if>
            <if test="love!=null">
                love,
            </if>
            <if test="strain!=null and strain!=''">
                strain,
            </if>
            <if test="lytm!=null">
                lytm,
            </if>
        </trim>
        values
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="name!=null and name!=''">
                #{name},
            </if>
            <if test="health!=null">
                #{health},
            </if>
            <if test="love!=null">
                #{love},
            </if>
            <if test="strain!=null and strain!=''">
                #{strain},
            </if>
            <if test="lytm!=null">
                #{lytm},
            </if>
        </trim>
    </insert>

测试

方法测试

在测试类里面添加测试语句

@Test
    public void testSaveDog(){
        Dog dog = new Dog();
        dog.setName("绿绿");
        dog.setHealth(100);
        dog.setLove(100);
        dog.setStrain("狼狗");
        dogDao.save(dog);
    }

    @Test
    public void testUpdateDog(){
        Dog dog = new Dog();
        dog.setId(38);
        dog.setHealth(80);
        dog.setName("卡卡");
        dogDao.update(dog);
    }

    @Test
    public void testDeleteDog(){
        Dog dog = new Dog();
        dog.setId(27);
        dogDao.delete(dog);
    }

    @Test
    public void testBatchDeleteDog(){
        List<Integer> dogID = new ArrayList<>();

        dogID.add(22);
        dogID.add(23);
        dogID.add(24);
        dogDao.batchDelete(dogID);
    }

    @Test
    public void testBatchAdd(){
        List<Dog> dogs = new ArrayList<>();
        Dog dog1 = new Dog("白白",100,100,"白狗");
        Dog dog2 = new Dog("黄黄",100,100,"黄狗");
        Dog dog3 = new Dog("黑黑",100,100,"黑狗");
        Dog dog4 = new Dog("花花",100,100,"花狗");
        dogs.add(dog1);
        dogs.add(dog2);
        dogs.add(dog3);
        dogs.add(dog4);
        dogDao.batchAdd(dogs);

    }

    @Test
    public void testBatchUpdate(){
        List<Dog> dogs = new ArrayList<>();
        Dog dog1 = new Dog(28,"白白",100,80,"白狗");
        Dog dog2 = new Dog(29,"黄黄",100,80,"黄狗");
        Dog dog3 = new Dog(30,"黑黑",100,80,"黑狗");
        Dog dog4 = new Dog(31,"花花",100,80,"花狗");
        dogs.add(dog1);
        dogs.add(dog2);
        dogs.add(dog3);
        dogs.add(dog4);
        dogDao.batchUpdate(dogs);
    }

}

3、查找语句

在DogDao接口中定义方法体,查询全部数据

public interface DogDao {
    List<Dog> findAllDog();
}

DogDao.xml

<select id="findAllDog" resultType="Dog">
    select id,name,health,love,strain,lytm from dog;
</select>

4、条件查询

DogDao接口

//    根据狗狗的名字(模糊查询)和亲密度查询狗狗的信息 可以自由选择降序和升序(1.升序,2.降序)
List<Dog> getAllDogByNameAndLove(
      @Param("dogname") String dogName,
      @Param("doglove") Integer love,
      @Param("ordervalue") Integer orderValue
);

DogDao.xml

<select id="getAllDogByNameAndLove" resultType="Dog">
    select id,name,health,love,strain,lytm from dog
    <where>
        <if test="dogname!=null and dogname!=''">
            name like concat('%',#{dogname},'%')
        </if>
        <if test="doglove!=null">
            and love=#{doglove}
        </if>
    </where>
    <choose>
        <when test="ordervalue==1">
            order by lytm asc
        </when>
        <when test="ordervalue==2">
            order by lytm desc
        </when>
        <otherwise>
            order by id desc
        </otherwise>
    </choose>
</select>

Test类

当name、love都为null时,全部输出。默认排序方式为通过id降序排序

@Test
public void testgetAllDogByNameAndLove(){
//    List<Dog> dogs = dogDao.getAllDogByNameAndLove(null, null, null);
//    List<Dog> dogs = dogDao.getAllDogByNameAndLove(null,100,2);
    List<Dog> dogs = dogDao.getAllDogByNameAndLove("黑",null,1);

    for (Dog dog : dogs) {
        System.out.println(dog);
    }
}

5、多表联查 - 一对多

Dog类

public class Dog {
    // 当前狗狗对象有过的主人信息
    private List<Master> masters; 

    // getter and setter方法
    public List<Master> getMasters() {
        return masters;
    }
    public void setMasters(List<Master> masters) {
        this.masters = masters;
    }
}

DogDao接口

public interface DogDao {

//    根据狗狗ID找出狗狗的详细信息,以及所有领养过此狗狗的所有主人信息(集合)
    Dog getDogAndMastersByDogId(Integer id);

//    根据指定狗狗品种找出狗狗的详细信息以及所有领养过此品种的所有主人信息(集合)
    List<Dog> getAllDogAndMasterByDogStrain(String strain);

}

DogDao.xml

<!--定义Dog与Master的映射关系-->
<resultMap id="dogMap" type="Dog">
    <id column="id" property="id"></id>
    <result column="name" property="name"></result>
    <result column="health" property="health"></result>
    <result column="love" property="love"></result>
    <result column="strain" property="strain"></result>
    <result column="lytm" property="lytm"></result>
    <collection property="masters" ofType="Master">
        <id column="pid" property="pid"></id>
        <result column="uname" property="name"></result>
        <result column="age" property="age"></result>
        <result column="gender" property="gender"></result>
        <result column="yearnum" property="yearnum"></result>
        <result column="did" property="did"></result>
    </collection>
</resultMap>

<!-- 根据狗狗ID找出狗狗的详细信息,以及所有领养过此狗狗的所有主人信息 -->
<select id="getDogAndMastersByDogId" resultMap="dogMap">
    select d.id,d.name,d.health,d.love,d.strain,d.lytm,m.pid,m.name uname,m.age,m.gender,m.yearnum,m.did
    from dog d left join master m on m.did=d.id
    where d.id=#{dogId}
</select>

<!-- 根据指定狗狗品种找出狗狗的详细信息以及所有领养过此品种的所有主人信息 -->
<select id="getAllDogAndMasterByDogStrain" resultMap="dogMap">
    select d.id,d.name,d.health,d.love,d.strain,d.lytm,m.pid,m.name uname,m.age,m.gender,m.yearnum,m.did
    from dog d left join master m on m.did=d.id
    where d.strain=#{dogStrain}
</select>

Test类

@Test
    public void testgetDogAndMastersByDogId(){
        Dog dog = dogDao.getDogAndMastersByDogId(3);
        System.out.println(dog);
        List<Master> masters = dog.getMasters();
        for(Master master:masters){
            System.out.println(master);
        }
    }
    @Test
    public void testgetAllDogAndMasterByDogStrain(){
        List<Dog> dogs = dogDao.getAllDogAndMasterByDogStrain("西施");
        for(Dog dog:dogs){
            System.out.println(dog);
            List<Master> masters = dog.getMasters();
            for(Master master:masters){
                System.out.println(master);
            }
        }
    }

resultMap和resultType的区别:

  • resultType:只有查询出来的列名和pojo的属性一致时才会映射成功

  • resultMap:如果查询出来的列名和pojo的属性名不一致时,可以通过resultMap对列名和属性名做映射关系

6、多表联查 - 一对一

新建一个狗狗品种的详细描述

StrainType类

public class StrainType {
    private Integer id;
    private String name;
    private String description;

// 重写toString方法

// getter and setter方法

}

DogDao接口

定义方法体

//    Dog List<Master> StrainInfo
Dog getDogAndMastersAndStraininfoByDogId(Integer id);

DogDao.xml

重新定义映射集合关系

<resultMap id="dogMap2" type="Dog">
    <id column="id" property="id"></id>
    <result column="name" property="name"></result>
    <result column="health" property="health"></result>
    <result column="love" property="love"></result>
    <result column="strain" property="strain"></result>
    <result column="lytm" property="lytm"></result>

<!--一对一映射-->
    <association property="strainType" javaType="StrainType">
        <id column="sid" property="id"></id>
        <result column="sname" property="name"></result>
        <result column="description" property="description"></result>
    </association>
<!--一对多映射-->
    <collection property="masters" ofType="Master">
        <id column="pid" property="pid"></id>
        <result column="uname" property="name"></result>
        <result column="age" property="age"></result>
        <result column="gender" property="gender"></result>
        <result column="yearnum" property="yearnum"></result>
        <result column="did" property="did"></result>
    </collection>
</resultMap>

<select id="getDogAndMastersAndStraininfoByDogId" resultMap="dogMap2">
    select d.id,d.name,d.health,d.love,d.strain,d.lytm,
           s.id sid,s.name sname,s.description,
           m.pid,m.name uname,m.age,m.gender,m.yearnum,m.did
    from dog d
        left join straininfo s on d.strain = s.name
        left join master m on d.id = m.did where d.id=#{dogId};
</select>

Test类

@Test
    public void testgetDogAndMastersAndStraininfoByDogId(){
        Dog dog = dogDao.getDogAndMastersAndStraininfoByDogId(2);
        System.out.println("狗狗信息");
        System.out.println(dog);
        System.out.println("狗狗主人的信息:");
        List<Master> masters = dog.getMasters();
        for(Master master:masters){
            System.out.println(master);
        }
        System.out.println("狗狗品种:");
        System.out.println(dog.getStrainType());

    }

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MyBatis是一个开源的持久层框架,它可以将数据库操作与Java对象之间的映射关系进行配置,提供了一种简单且灵活的方式来访问数据库。 在MyBatis中,映射文件是用于定义SQL语句和结果映射的配置文件。下面是映射文件的详解: 1. 命名空间(namespace):映射文件中的命名空间用于对SQL语句进行分类和管理,可以通过命名空间来引用映射文件中定义的SQL语句。 2. 结果映射(resultMap):结果映射用于将查询结果映射到Java对象上。可以通过resultMap标签定义结果映射,指定查询结果与Java对象之间的对应关系。 3. SQL语句(select、insert、update、delete):映射文件中可以定义各种SQL语句,包括查询、插入、更新和删除等操作。可以通过标签(如select、insert、update、delete)来定义SQL语句,并在其中编写具体的SQL语句。 4. 参数映射(parameterType):参数映射用于将Java对象作为参数传递给SQL语句。可以通过parameterType属性指定参数类型,也可以通过parameterMap标签定义参数映射。 5. 返回值映射(resultType):返回值映射用于将查询结果转换为Java对象。可以通过resultType属性指定返回值类型,也可以通过resultMap标签引用已定义的结果映射。 6. 动态SQLMyBatis支持动态SQL,可以根据条件动态生成SQL语句。可以使用if、choose、when、otherwise等标签来实现动态SQL的编写。 7. 参数传递:映射文件中可以使用#{}或者${}来传递参数。#{}会将参数转义后传递给数据库,${}会直接将参数拼接到SQL语句中。 8. 引用其他映射文件:映射文件可以通过include标签引用其他映射文件,可以将一些通用的SQL语句定义在公共的映射文件中,然后在需要的地方引用。 以上是对MyBatis映射文件的详解,希望能对你有所帮助。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值