Mybatis的CRUD之XML方式以及动态SQL

MyBatis 接口代理方式实现 Dao 层

  • 传统方式实现 Dao 层,我们既要写接口,还要写实现类。而 MyBatis 框架可以帮助我们省略编写 Dao 层接口实现类的步骤。程序员只需要编写接口,由 MyBatis 框架根据接口的定义来创建该接口的动态代理对象。

实现规则

  1. 映射配置文件中的名称空间必须和 Dao 层接口的全类名相同。
  2. 映射配置文件中的增删改查标签的 id 属性必须和 Dao 层接口的方法名相同。
  3. 映射配置文件中的增删改查标签的 parameterType 属性必须和 Dao 层接口方法的参数相同。
  4. 映射配置文件中的增删改查标签的 resultType 属性必须和 Dao 层接口方法的返回值相同。

获取动态代理对象
SqlSession 功能类中的 getMapper() 方法。

MyBatis 映射配置文件 - 动态 SQL

1.动态 SQL 指的就是 SQL 语句可以根据条件或者参数的不同进行动态的变化。
<where>:条件标签。
<if>:条件判断的标签。
<foreach>:循环遍历的标签。
2.我们可以将一些重复性的 SQL 语句进行抽取,以达到复用的效果。
<sql>:抽取 SQL 片段的标签。
<include>:引入 SQL 片段的标签。

数据准备

SQL

创建学生信息表

-- 创建学生表
CREATE TABLE student(
	sid INT PRIMARY KEY AUTO_INCREMENT,
	`name` VARCHAR(20),
	age INT
);

-- 添加信息
INSERT INTO student VALUES (NULL,'小付',25),(NULL,'小花花',18),(NULL,'李四',24);

准备项目

使用maven创建项目
在这里插入图片描述

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.fs</groupId>
    <artifactId>MyBatis_day02_01</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
<!--        MyBatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.2</version>
        </dependency>
<!--        mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
<!--        log4j日志记录,可以在控制台输出sql语句方便我们查错-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
<!--        junit测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
<!--        lombok在实体类上注解@Data可以自动帮我们添加getset方法等-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.20</version>
        </dependency>

    </dependencies>
</project>

dao 接口

package com.fs.dao;

import com.fs.entity.Student;

import java.util.List;
/*
dao模拟
 */
public interface StudentMapper {
    //查询所有学生信息
    List<Student> findAll();
    //更新学生信息
    int updateStudent(Student student);
    //多条件查询学生信息
    List<Student> selectCondition(Student student);
    //根据多个id查询学生信息
    List<Student> selectByIds(List<Integer> ids);
    //根据姓名查询学生
    Student findStudentByName(String name);
}

Student实体类

package com.fs.entity;

import lombok.Data;

@Data //这个注解是lombok包下的,可以自动帮我们添加getset方法等
public class Student {
    private Integer sid;
    private String name;
    private Integer age;
}

service 业务层

package com.fs.service;

import com.fs.entity.Student;

import java.util.List;
/*
Service层接口,模拟业务层
 */
public interface StudentService {
    //下面的抽象方法与dao一样
    List<Student> findAll();
    int updateStudent(Student student);
    List<Student> selectCondition(Student student);
    List<Student> selectByIds(List<Integer> ids);
    Student findStudentByName(String name);
}

业务层实现类

package com.fs.service.impl;

import com.fs.dao.StudentMapper;
import com.fs.entity.Student;
import com.fs.service.StudentService;
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;
import java.util.List;

public class StudentServiceImpl implements StudentService {
    //声明Dao接口
    private StudentMapper studentMapper;

    //构造方法通过SqlSession的getMapper(接口的字节码)生成studentMapper代理类
    public StudentServiceImpl() {
        try {
            //加载配置文件
            InputStream rs = Resources.getResourceAsStream("MyBatisConfig.xml");
            //获取工厂建造类
            SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
            //获取工厂对象
            SqlSessionFactory build = sqlSessionFactoryBuilder.build(rs);
            //获取SqlSession对象
            SqlSession sqlSession = build.openSession(true);
            //得到代理对象
            studentMapper = sqlSession.getMapper(StudentMapper.class);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /*
    调用dao方法实现功能
     */
    @Override
    public List<Student> findAll() {
        return studentMapper.findAll();
    }

    @Override
    public int updateStudent(Student student) {
        return studentMapper.updateStudent(student);
    }

    @Override
    public List<Student> selectCondition(Student student) {
        return studentMapper.selectCondition(student);
    }

    @Override
    public List<Student> selectByIds(List<Integer> ids) {
        return studentMapper.selectByIds(ids);
    }

    @Override
    public Student findStudentByName(String name) {
        return studentMapper.findStudentByName(name);
    }

}

配置文件

数据库连接信息配置文件 jdbc.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://mysql服务器的ip地址:3306/创建student的库
username=root
password=root

log4j日志记录配置文件 log4j.properties

# Global logging configuration
# ERROR WARN INFO DEBUG
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

MyBatis核心配置文件 MyBatisConfig.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!--MyBatis的DTD约束-->
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">

<!--configuration 核心根标签-->
<configuration>

    <!--引入数据库连接的配置文件-->
    <properties resource="jdbc.properties"/>

    <!--配置LOG4J-->
    <settings>
        <setting name="logImpl" value="log4j"/>
    </settings>

    <!--起别名-->
    <typeAliases>
        <!--        给一个类起别名-->
        <!--        <typeAlias type="com.fs.entity.Student" alias="student"/>-->
        <!--        给一个包下的类起别名,别名为类名的首字母小写-->
        <package name="com.fs.entity"/>
    </typeAliases>

    <!--environments配置数据库环境,环境可以有多个。default属性指定使用的是哪个-->
    <environments default="mysql">
        <!--environment配置数据库环境  id属性唯一标识-->
        <environment id="mysql">
            <!-- transactionManager事务管理。  type属性,采用JDBC默认的事务-->
            <transactionManager type="JDBC"></transactionManager>
            <!-- dataSource数据源信息   type属性 连接池-->
            <dataSource type="POOLED">
                <!-- property获取数据库连接的配置信息 -->
                <property name="driver" value="${driver}" />
                <property name="url" value="${url}" />
                <property name="username" value="${username}" />
                <property name="password" value="${password}" />
            </dataSource>
        </environment>
    </environments>

    <!-- mappers引入映射配置文件 -->
    <mappers>
        <!-- mapper 引入指定的映射配置文件   resource属性指定映射配置文件的名称 -->
        <mapper resource="StudentMapper.xml"/>
    </mappers>
</configuration>

mapper映射配置文件,详细的介绍了动态sql常用的where标签if,foreach标签的使用
在映射配置文件中,MDL我只写了update,而insert,delete这两个和update没有任何区别,甚至标签体都可以混用,我们知道就好,但是实际开发还是什么需求用什么标签

<?xml version="1.0" encoding="UTF-8" ?>
<!--MyBatis的DTD约束-->
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace:dao接口的全限定名-->
<mapper namespace="com.fs.dao.StudentMapper">
<!--    定义sql语句片段-->
    <sql id="select">select <include refid="fields"></include> from</sql>
<!--    将字段抽取出来,因为*会影响sql查询的速度-->
    <sql id="fields">sid,name,age</sql>

<!-- 测试 用include标签来引用sql片段  select sid,name,age from student -->
    <select id="findAll" resultType="student">
        <include refid="select"></include> student
    </select>

    <!--    根据name查找学生-->
    <select id="findStudentByName" resultType="student">
        select * from student where name = #{name}
    </select>

<!--    根据sid跟新学生对象-->
    <update id="updateStudent">
        update student set name = #{name},age = #{age} where sid = #{sid}
    </update>

<!--    动态sql-->
    <select id="selectCondition" resultType="student">
<!-- where 标签的作用就是,自动添加where关键字,会自动将多余的and去掉-->
        select * from student
        <where>
            <if test="sid != null">
                sid = #{sid}
            </if>
            <if test="name != null">
                and name = #{name}
            </if>
            <if test="age != null">
                and age = #{age}
            </if>
        </where>
    </select>
<!--  foreach标签   -->
    <select id="selectByIds" resultType="student" parameterType="list">
        select * from student
        <!--
            Collection:指定遍历的对象
            open:遍历开始拼接的字符串
            close:遍历结束后的字符串拼接
            separator:每次拼接的分隔符
            item:遍历得到的结果名
            注意,如果传入的集合为空,就不会进行任何字符串拼接,包括open close
        -->
        <where>
            <foreach collection="list" open="sid in(" separator="," close=")" item="sid">
                #{sid}
            </foreach>
        </where>
    </select>

</mapper>

测试类模拟controller层,控制台展示

package com.fs.dao;

import com.fs.entity.Student;
import com.fs.service.impl.StudentServiceImpl;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

public class StudentMapperTest {

    /**
     * 测试查询所有
     */
    @Test
    public void testFindAll() {
        StudentServiceImpl studentService = new StudentServiceImpl();
        List<Student> all = studentService.findAll();
        for (Student student : all) {
            System.out.println(student);
        }
    }

    /**
     * 更新学生信息
     */
    @Test
    public void testUpdate() {
        StudentServiceImpl studentService = new StudentServiceImpl();
        Student student1 = new Student();
        student1.setAge(24);
        student1.setName("张三");
        student1.setSid(3);
        int i = studentService.updateStudent(student1);
        System.out.println("更新了:"+i+"条学生信息");
    }


    /**
     * 根据多条件查询学生信息
     */
    @Test
    public void selectCondition() {
        StudentServiceImpl studentService = new StudentServiceImpl();
        Student student1 = new Student();
        student1.setAge(24);
        student1.setName("李四");
//        student1.setSid(3);
        List<Student> stu = studentService.selectCondition(student1);
        for (Student student : stu) {
            System.out.println(student);
        }
    }

    /**
     * 根据多个id查询
     */
    @Test
    public void selectByIds() {
        StudentServiceImpl studentService = new StudentServiceImpl();
        ArrayList<Integer> integers = new ArrayList<>();
        integers.add(1);
        integers.add(2);
        integers.add(3);
        List<Student> students = studentService.selectByIds(integers);
        for (Student student : students) {

            System.out.println(student);
        }
    }

    /*
    根据名字查询学生信息
     */
    @Test
    public void findStudentByName() {
        StudentServiceImpl studentService = new StudentServiceImpl();
        Student xh = studentService.findStudentByName("小花花");
        System.out.println(xh);
    }
}

猜你喜欢

转载自blog.csdn.net/fushuaiCSDN/article/details/106823665