java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > MyBatis框架与参数

MyBatis框架与参数案例解析

作者:期待のcode

MyBatis是一款Java持久层框架,实现对象与数据库的映射,文章介绍了MyBatis的基本概念,并给出了一个完整的使用案例,结合实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧

MyBatis框架概述

MyBatis 是一款基于 Java 语言的半自动化对象关系映射(ORM)持久层框架,其核心目标是对 JDBC API 进行抽象与封装,在保留开发者对 SQL 语句精细控制能力的前提下,它有效解决了传统 JDBC 开发中存在的流程冗余、业务逻辑与数据访问逻辑耦合、数据与对象映射复杂等问题。该框架最初由 Apache 软件基金会以“iBatis”为名开源,2010 年迁移至 Google Code 平台并正式更名为“MyBatis”,目前由 GitHub 社区主导维护,是 Java 生态中应用最广泛的持久层框架之一。

MyBatis 可通过 XML 或注解等主流方式,对需执行的 SQL 语句及对应的执行规则进行配置。框架会将 Java 对象中的数据与 SQL 语句中的动态参数进行绑定,进而执行 SQL 操作,SQL 执行完成后,MyBatis 会自动将数据库返回的结果集映射为 Java 对象并返回。

持久层是软件架构中负责数据持久化的核心层级,主要功能是将内存中的临时数据持久化到存储介质(如数据库),并能从存储介质中恢复数据至内存。作为连接业务逻辑层与数据存储层的桥梁,它可避免业务逻辑层直接与数据库交互导致的系统耦合度升高问题。

MyBatis案例与详解

创建数据库和表结构

create database mybatis_db;
use mybatis_db;
​
CREATE TABLE `user` (
  `id` int(11) NOT NULL auto_increment,
  `username` varchar(32) NOT NULL COMMENT '用户名称',
  `birthday` datetime default NULL COMMENT '生日',
  `sex` char(1) default NULL COMMENT '性别',
  `address` varchar(256) default NULL COMMENT '地址',
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
​
insert  into `user`(`id`,`username`,`birthday`,`sex`,`address`) values (1,'老、王','2018-02-27 17:47:08','男','北京'),(2,'熊大','2018-03-02 15:09:37','女','上海'),(3,'熊二','2018-03-04 11:34:34','女','深圳'),(4,'光头强','2018-03-04 12:04:06','男','广州');

创建 maven Java工程
引入坐标依赖,MyBatis的3.4.5的版本坐标,MySQL驱动的jar包5.1.6版本,Junit单元测试的jar包,引入log4j的jar包1.2.12版本(需要引入log4j.properties的配置文件)

    <dependencies>
        <!--mybatis核心包-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.5</version>
        </dependency>
        <!--mysql驱动包-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
        <!-- 单元测试 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
            <scope>test</scope>
        </dependency>
        <!-- 日志 -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
    </dependencies>

log4j.properties配置文件

编写User的实现类,属性尽量使用包装类型

import java.io.Serializable;
import java.util.Date;
public class User implements Serializable {
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", birthday=" + birthday +
                ", sex='" + sex + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

编写UserMapper的接口和方法

import java.util.List;
public interface UserMapper {
    //查询所有的用户
    public List<User> findAll();
}

在resources目录下,创建mapper文件夹,编写UserMapper.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="com.qcby.mapper.UserMapper">
    <select id="findAll" resultType="com.qcby.domain.User">
        select * from user;
    </select>
</mapper>

通过namespace关联com.qcby.mapper.UserMapper接口,为接口中的findAll()方法绑定一条SQL语句,并指定查询结果会被映射为User对象。

编写主配置文件,在resources目录下创建SqlMapConfig.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>
    <environments default="mysql">
        <environment id="mysql">
            <!-- 配置事务管理类型 -->
            <transactionManager type="JDBC"/>
            <!-- 配置是否需要使用连接池,POOLED使用,UNPOOLED不使用 -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql:///mybatis_db"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <!-- 加载映射的配置文件 -->
    <mappers>
        <mapper resource="mappers/UserMapper.xml"/>
    </mappers>
</configuration>

编写测试代码

import com.qcby.domain.User;
import com.qcby.mapper.UserMapper;
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 org.junit.Test;
import java.io.InputStream;
import java.util.List;
public class UserTest {
    /**
     * 测试查询所有的方法
     * @throws Exception
     */
    @Test
    public void testFindAll() throws Exception {
        InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
        SqlSession session = factory.openSession();
        UserMapper mapper = session.getMapper(UserMapper.class);
        List<User> list = mapper.findAll();
        for (User user : list) {
            System.out.println(user);
        }
        session.close();
        in.close();
    }
    @Test
    public void run() throws Exception {
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession session = factory.openSession();
        List<User> list = session.selectList("com.qcby.mapper.UserMapper.findAll");
        for (User user : list) {
            System.out.println(user);
        }
        session.close();
        inputStream.close();
    }
}

实现效果:

执行testFindAll()

testFindAll () 函数通过 MyBatis 的接口代理方式实现数据库查询
首先利用 MyBatis 的 Resources 工具类加载主配置文件 SqlMapConfig.xml 的输入流,再通过 SqlSessionFactoryBuilder 构建出 SqlSessionFactory 会话工厂,随后打开 SqlSession 会话,调用 SqlSession 的 getMapper (UserMapper.class) 获取 UserMapper 接口的代理对象,调用代理对象的 findAll () 方法时,MyBatis 会自动匹配 UserMapper.xml 中对应 namespace 和 id 的 SQL 语句执行查询,得到 User 对象集合并打印,最后释放资源。这种方式面向接口编程,支持编译期类型检查,是 MyBatis 官方推荐的规范用法。

执行run()

run () 函数采用 MyBatis 传统的命名空间 + ID 方式执行查询
流程上同样先加载配置文件、创建 SqlSessionFactory 并打开 SqlSession,但执行查询时直接调用 SqlSession 的 selectList () 方法,通过字符串 “com.qcby.mapper.UserMapper.findAll” 定位目标 SQL,得到 User 对象集合并打印,最后释放资源。

实现增删改查
UserMapper接口代码

import com.qcby.domain.User;
import java.util.List;
public interface UserMapper {
    public List<User> findAll();
    public User findById(Integer userId);
    public void insert(User user);
    public void update(User user);
    public void delete(Integer userId);
    public List<User> findByName1(String username);
    public List<User> findByName2(String username);
    public Integer findByCount();
}

UserMapper.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="com.qcby.mapper.UserMapper">
    <select id="findAll" resultType="com.qcby.domain.User">
        select * from user;
    </select>
    <!-- 通过id查询,SQL语句使用#{}占位符的名称,名称可以任意,仅限于基本数据类型和String类型
    -->
    <select id="findById" resultType="com.qcby.domain.User" parameterType="int">
        select * from user where id = #{id};
    </select>
    <!--保存操作-->
    <insert id="insert" parameterType="com.qcby.domain.User">
        <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
            select last_insert_id();
        </selectKey>
        insert into user (username,birthday,sex,address) values (#{username},#{birthday},#{sex},#{address})
    </insert>
    <!-- 修改 -->
    <update id="update" parameterType="com.qcby.domain.User">
        update user set username = #{username},birthday = #{birthday},sex = #{sex},address=#{address} where id = #{id}
    </update>
    <!-- 删除 -->
    <delete id="delete" parameterType="Integer">
        delete from user where id = #{id}
    </delete>
    <!-- 模糊查询1 -->
    <select id="findByName1" resultType="com.qcby.domain.User" parameterType="string">
        select * from user where username  like #{username}
    </select>
    <!-- 模糊查询2,固定写法 -->
    <select id="findByName2" resultType="com.qcby.domain.User" parameterType="string">
        select * from user where username  like '%${value}%'
    </select>
    <!-- 具体函数的查询 -->
    <select id="findByCount" resultType="int">
        select count(*) from user
    </select>
</mapper>

UserTest 代码

package com.qcby;
import com.qcby.domain.User;
import com.qcby.mapper.UserMapper;
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 org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
public class UserTest1 {
    private InputStream in;
    private SqlSession session;
    private UserMapper mapper;
    @Before
    public void init() throws Exception {
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
        session = factory.openSession();
        mapper = session.getMapper(UserMapper.class);
    }
    @After
    public void destory() throws IOException {
        in.close();
        session.close();
    }
    @Test
    public void testFindAll() throws Exception {
        List<User> list = mapper.findAll();
        // 遍历
        for (User user : list) {
            System.out.println(user);
        }
        in.close();
    }
    @Test
    public void testFindById() throws Exception {
        User user = mapper.findById(41);
        System.out.println(user);
        in.close();
    }
    @Test
    public void testInsert() throws Exception {
        User user = new User();
        user.setUsername("美美");
        user.setBirthday(new Date());
        user.setSex("男");
        user.setAddress("顺义");
        mapper.insert(user);
        session.commit();
        System.out.println(user.getId());
    }
    @Test
    public void testUpdate() throws Exception {
        User user = mapper.findById(4);
        user.setUsername("小凤");
        mapper.update(user);
        session.commit();
    }
    @Test
    public void testDelete() throws Exception {
        mapper.delete(2);
        session.commit();
    }
    // 第一种
    @Test
    public void testFindByName() throws Exception {
        List<User> list = mapper.findByName1("%王%");
        for (User user : list) {
            System.out.println(user);
        }
    }
    // 第二种
    @Test
    public void testFindByName1() throws Exception {
        List<User> list = mapper.findByName2("王");
        for (User user : list) {
            System.out.println(user);
        }
    }
    @Test
    public void testFindByCount() throws Exception {
        Integer count = mapper.findByCount();
        System.out.println("总记录数:"+count);
    }
}

实现效果:

执行 testInsert() 方法

该方法执行的是这条SQL语句

<insert id="insert" parameterType="com.qcby.domain.User">
        <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
            select last_insert_id();
        </selectKey>
        insert into user (username,birthday,sex,address) values (#{username},#{birthday},#{sex},#{address})
    </insert>

其中selectKey标签用于获取插入记录后自动生成的主键值,keyProperty=“id” 表示将查询到的主键值赋值给传入User对象的id属性,order=“AFTER” 指定该查询在insert语句执行之后执行(自增长主键是在记录插入后生成的),resultType=“java.lang.Integer” 声明查询返回的主键类型为Integer,内部 SQL select last_insert_id(); 是 MySQL 的内置函数,用于获取当前会话中最后一次插入操作生成的自增长主键值。MyBatis 通过 <selectKey> 获取到主键值后,会主动调用对象的setId()方法赋值,而由于对象是引用传递,外部的user对象就能通过getId()获取到这个值。

session.commit() 的核心功能是提交事务,确保数据库修改持久化。在 MyBatis 中,默认采用 JDBC 事务管理机制(对应配置中的 <transactionManager type="JDBC"/>),通过 factory.openSession() 获取的 SqlSession 默认开启事务且不自动提交。当执行 mapper.insert(user) 时,插入操作仅暂存于事务中,直到调用 session.commit() 才会将数据永久写入数据库,完成数据持久化,若未显式调用 commit(),SqlSession 关闭时会自动执行事务回滚,所有未提交的修改都将被撤销,数据库不会保留新增数据。

模糊查询符号使用的区别

实现效果:

MyBatis参数详解

类型别名定义
MyBatis 内置了一些常用类型的别名(如int对应Integer、string对应String、list对应ArrayList等),开发者无需手动定义即可直接使用。
也可以进行别名的注册,在SqlMapConfig.xml配置文件中设置

<!-- 定义别名 -->
<typeAliases>
  <!-- 把com.qcby.domain.User使用user别名来显示
  <typeAlias type="com.qcby.domain.User" alias="user"/>
  -->
  <!-- 针对com.qcby.domain包下的所有的类,都可以使用当前的类名做为别名 -->
  <package name="com.qcby.domain"/>
</typeAliases>

在 MyBatis 的核心配置文件中,使用<typeAlias>标签单独指定某个类的别名,或通过<package>标签批量扫描某个包下的所有类,此时 MyBatis 会默认以类名(首字母大小写均可,不区分大小写)作为别名,例如扫描com.qcby.domain包后,User类可直接用user或User作为别名

<select id="findAll" resultType="user">
  select * from user
</select>

定义后的类型别名可直接在 Mapper 配置文件的parameterType、resultType等属性中使用,其值不再是原来的全路径了

到此这篇关于MyBatis框架与参数案例解析的文章就介绍到这了,更多相关MyBatis框架与参数内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文