MyBatis-02 | 一篇了解MyBatis框架实现CRUD操作及MyBatis配置文件参数

本文详细介绍了MyBatis环境搭建步骤,包括Maven项目创建、依赖引入及配置文件设置。深入讲解了MyBatis的CRUD操作实现,涵盖增删改查的接口定义、XML映射文件编写及单元测试方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

回顾mybatis环境搭建

MyBatis的CRUD操作

例如,增加操作

好啦好啦,CRUDCRUD啦

配置文件参数

1. properties属性

2. environments

3. typeAliases

4. typeHandlers

5. Mappers (映射器)

6.Mapper 映射文件

7. select

8. parameterType(输入类型)

9. resultType(返回值类型)

10. resultMap(输出结果映射)

11. Plugins (插件)


回顾mybatis环境搭建

  • 首先创建一个maven项目,就一路next下去的那种即可;
  • 然后在pom文件中引入几个依赖:
<dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.5</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.13</version>
        </dependency>
        <!--日志这个不是必要的-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.12</version>
        </dependency>
        <!--单元测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>
  • 在Resource下创建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"></transactionManager>
            <!--数据库连接池-->
            <dataSource type="POOLED">
                <!--数据库连接配置-->
                <property name="driver" value="com.mysql.cj.jdbc.Driver"></property>
                <property name="url" value="jdbc:mysql://localhost:3306/TestDB?serverTimezone=UTC"></property>
                <property name="username" value="root"></property>
                <property name="password" value="123456"></property>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="edu/xatu/Dao/UserDao.xml"></mapper>
    </mappers>
</configuration>
  • 将log4j.properties也放在Resource包下:
log4j.rootLogger=DEBUG, Console

#Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n

log4j.logger.java.sql.ResultSet=INFO
log4j.logger.org.apache=INFO
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
  • 然后在Java包下创建实体类,通过getter/setter方法生成,再重写toString即可;
package edu.xatu.Domain;

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 adress;

    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 getAdress() {
        return adress;
    }

    public void setAdress(String adress) {
        this.adress = adress;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", birthday=" + birthday +
                ", sex='" + sex + '\'' +
                ", adress='" + adress + '\'' +
                '}';
    }
}
  • 下一步创建一个接口
package edu.xatu.Dao;

//用户持久层
public interface UserDao {
    //查询所有用户
    List<User> findAll();
}
  • 在Resource包下创建Java包下dao层路径相同一个UserDao.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="edu.xatu.mybatis.dao.UserDao" >
    <select id="findAll" resultType="edu.xatu.mybatis.domain.mbuser">
        select * from mbuser
    </select>
</mapper>
  • 最后创建一个测试类,为了今天的CRUD多个例子的测试,所以将重复的操作封装起来,通过@Before和@After注解让他们在各自的时间执行,这样在接下来的测试例子中就只需要关注单个操作的测试,而不用大量的重复代码了。
public class test01 {
    private InputStream in;
    private SqlSession session;
    private UserDao userDao;

    @Before//在测试方法执行之前执行
    public void init() throws IOException {
        //读取配置文件
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //获取sqlsessionfactory对象
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
        //获取Session对象
        session = factory.openSession();
        //获取dao的代理对象
        userDao = session.getMapper(UserDao.class);
    }
    //释放资源
    @After//在测试方法执行之后进行
    public void destroy() throws IOException {
        //提交事务
        session.commit();

        session.close();
        in.close();
    }

    /**
     * 测试查询所有的操作
     * @throws IOException
     */
    @Test
    public void testFindAll(){
        //执行所有查询方法
        List<User> users = userDao.findAll();
        for(User user : users){
            System.out.println(user);
        }
    }

   
}

好了,言归正传,接下来开始今天的重点CRUD的操作实现吧!

MyBatis的CRUD操作

其实在上面的环境搭建的代码中,很明显,已经写了一个查询所有的方法在里面了......

然后,在上面这种环境搭建成功的基础上,再实现CRUD就很简单了,只需要在三个文件里动动手脚就能搞定啦!

(1)在UserDao接口中定义一个方法;

(2)UserDao.xml文件的mapper标签中定义需要的sql语句;

(3)然后,编写单元测试方法

例如,增加操作

在UserDao接口定义增加一个用户的方法

//增加一个用户
void insertUser(User user);

在UserDao.xml中定sql语句

    <!--插入新用户 保存用户 parameterType参数的类型-->
    <insert id="saveUser" parameterType="edu.xatu.Domain.User">
      insert into mbuser(username,adress,birthday,sex) values(#{username},#{adress},#{birthday},#{sex});
    </insert>

在test中编写测试方法进行增加一个用户的单元测试

    /**
     * 测试增加用户操作
     */
    @Test
    public void testInsertUser(){
        User user = new User();
        user.setUsername("肖战");
        user.setAdress("湖南省长沙市");
        user.setBirthday(new Date());
        user.setSex("男");

        userDao.saveUser(user);
    }

不信你去看看你的数据库表,有木有新增一条记录吖

好啦好啦,CRUDCRUD啦

UserDao接口(全部操作的代码):

package edu.xatu.Dao;

import edu.xatu.Domain.Queryvo;
import edu.xatu.Domain.User;
import java.util.List;

/**
 * 用户持久层
 */
public interface UserDao {
    //查询所有用户
    List<User> findAll();

    //保存用户
    void saveUser(User user);

    //更新用户
    void updateUser(User user);

    //删除用户
    void deleteUser(Integer id);

    //根据id查询用户
    User findbyId(Integer userId);

    //根据名称模糊查询
    List<User> findbyName(String userName);

    //查询总用户数
    int findTotal();

    //根据queryvo中的条件查询用户
    List<User> findbyQuery(Queryvo vo);
}

UserDao.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="edu.xatu.Dao.UserDao">
    <select id="findAll" resultType="edu.xatu.Domain.User">
        select * from mbuser
    </select>

    <!--插入新用户 保存用户 parameterType参数的类型-->
    <insert id="saveUser" parameterType="edu.xatu.Domain.User">
      <!--配置插入操作之后,获取插入数据的id-->
      <selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER">
          select last_insert_id();
      </selectKey>
      insert into mbuser(username,adress,birthday,sex) values(#{username},#{adress},#{birthday},#{sex});
    </insert>

    <!--更新用户-->
    <update id="updateUser" parameterType="edu.xatu.Domain.User">
        update mbuser set username=#{username},adress=#{adress},birthday=#{birthday},sex=#{sex} where id=#{id}
    </update>

    <!--删除用户-->
    <!--删除方法parameterType属性为基本数据类型或者基本数据类型的包装类时,且sql语句中只传一个值,这里占位符写什么都可以-->
    <delete id="deleteUser" parameterType="Integer">
        delete from mbuser where id=#{suiyixie}
    </delete>

    <!--根据id查询用户-->
    <select id="findbyId" parameterType="Integer" resultType="edu.xatu.Domain.User">
        select * from mbuser where id=#{suiyi}
    </select>

    <!--根据名称模糊查询-->
    <select id="findbyName" parameterType="String" resultType="edu.xatu.Domain.User" >
        <!--  这里没有%时,在测试方法就必须写%-->
        select * from mbuser where username like #{name}
        <!--select * from mbuser where username like '%${value}%'-->
    </select>
    
    <!--获取用户总记录条数-->
    <select id="findTotal" resultType="int">
        select count(id) from mbuser;
    </select>

    <!--根据queryvo条件查询用户-->
    <select id="findbyQuery" parameterType="edu.xatu.Domain.Queryvo" resultType="edu.xatu.Domain.User">
        select * from mbuser where username like #{user.username}
    </select>
</mapper>

单元测试方法(全部操作的测试方法)

package edu.xatu.Test;

import edu.xatu.Dao.UserDao;
import edu.xatu.Domain.Queryvo;
import edu.xatu.Domain.User;
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;

/**
 * 测试mybatis的CRUD操作
 */
public class test01 {
    private InputStream in;
    private SqlSession session;
    private UserDao userDao;

    //定义重复操作
    @Before//在测试方法执行之前执行
    public void init() throws IOException {
        //读取配置文件
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //获取sqlsessionfactory对象
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
        //获取Session对象
        session = factory.openSession();
        //获取dao的代理对象
        userDao = session.getMapper(UserDao.class);
    }
    //释放资源
    @After//在测试方法执行之后进行
    public void destroy() throws IOException {
        //提交事务
        session.commit();

        session.close();
        in.close();
    }

    /**
     * 测试查询所有的操作
     * @throws IOException
     */
    @Test
    public void testFindAll(){
        //执行所有查询方法
        List<User> users = userDao.findAll();
        for(User user : users){
            System.out.println(user);
        }
    }


    /**
     * 测试增加用户操作
     */
    @Test
    public void testSave(){
        User user = new User();
        user.setUsername("肖战");
        user.setAdress("湖南省长沙市");
        user.setBirthday(new Date());
        user.setSex("男");

        System.out.println("操作前"+user);
        //只需要保存操作的代码即可
        userDao.saveUser(user);
        System.out.println("操作后"+user);
    }

    /**
     * 测试更新用户的操作
     */
    @Test
    public void testUpdate(){
        User user = new User();
        user.setId(2);
        user.setUsername("华晨宇");
        user.setAdress("四川省成都市");
        user.setBirthday(new Date());
        user.setSex("男");

        userDao.updateUser(user);
    }

    /**
     * 测试删除用户的操作
     */
    @Test
    public void testDelete(){
        userDao.deleteUser(1);
    }

    /**
     * 测试根据id查询用户操作
     */
    @Test
    public void testFindById(){
        User user = userDao.findbyId(3);
        System.out.println(user);
    }

    /**
     * 测试模糊查询
     */
    @Test
    public void testfindbyName(){
        List<User> user = userDao.findbyName("%华%");
//        List<User> user = userDao.findbyName("华");
        for(User users : user){
            System.out.println(users);
        }
    }

    /**
     * 测试用户条数
     */
    @Test
    public void testfindTotal(){
        int count = userDao.findTotal();
        System.out.println(count);
    }

    /**
     * 测试模糊查询
     */
    @Test
    public void testfindbyQuery(){
        Queryvo vo = new Queryvo();
        User user = new User();
        user.setUsername("%毛%");
        vo.setUser(user);
        List<User> users = userDao.findbyQuery(vo);
        for(User u : users){
            System.out.println(u);
        }
    }
}

配置文件参数

在上面的增加操作中有个问题啊,如果我想新增一条记录后,获取新增的这条记录的id应该怎么操作呢?selectKey了解一下啦~

<insert id="saveUser" parameterType="edu.xatu.Domain.User">
      <!--配置插入操作之后,获取插入数据的id-->
      <selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER">
          select last_insert_id();
      </selectKey>
      insert into mbuser(username,adress,birthday,sex) values(#{username},#{adress},#{birthday},#{sex});
    </insert>

要不测试一下你康康?

呶,这不获取到了id=6! 小小标签,作用倒是一堆,了不起了不起,保温杯里泡枸杞......

1. properties属性

在SqlMapConfig.xml中,其实阔以这样,对比上面的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>
    <properties resource="jdbcConfig.properties">
        <property name="driver" value="com.mysql.cj.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/TestDB?serverTimezone=UTC"></property>
        <property name="username" value="root"></property>
        <property name="password" value="123456"></property>
    </properties>
    <!--环境配置-->
    <environments default="mysql">
        <environment id="mysql">
            <transactionManager type="jdbc"></transactionManager>
            <!--数据库连接池-->
            <dataSource type="POOLED">
                <!--数据库连接配置-->
                <property name="driver" value="${driver}"></property>
                <property name="url" value="${url}"></property>
                <property name="username" value="${username}"></property>
                <property name="password" value="${password}"></property>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <!--<mapper resource="edu/xatu/Dao/UserDao.xml"></mapper>-->
        <!--package用于指定dao接口所在的包,当指定完成之后就不需要写mapper-->
        <package name="edu.xatu.Dao"></package>
    </mappers>
</configuration>

找到区别了吧,嘻嘻~  这时候你可能说,吃饱了撑的,写在环境配置里不香么,你挪上去干啥 ?!撑的

这样写我......确实撑的,其实啦

properties可以将数据库连接参数单独配置在jdbcConfig.properties(名字不重要)中,放在类路径下。这样只需要在SqlMapConfig.xml中加载jdbcConfig.properties的属性值。这样在SqlMapConfig.xml中就不需要对数据库连接参数硬编码。将数据库连接参数只配置在jdbcConfig.properties中,这样一来方便对参数进行统一管理,其它xml可以引用该jdbcConfig.properties,例如:

在Resource包下写了jdbcConfig.properties文件

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/TestDB?serverTimezone=UTC
user=root
password=123456

在SqlMapConfig.xml中通过properties读取资源即可

<properties resource="jdbcConfig.properties"></properties>

2. environments

MyBatis 可以配置多种环境。这会帮助你将 SQL 映射应用于多种数据库之中。但是你可以配置多种环境,但每个数据库对应一个 SqlSessionFactory。所以,如果你想连接两个数据库,你需要创建两个 SqlSessionFactory 实例,每个数据库对应一个。

  • 用environment 的id属性来标识,然后environments 的default指定

这块不想贴例子了,就给啥名就调用啥名也就是用的此种环境配置了

3. typeAliases

typeAliases可以用来自定义别名,需要parameterType指定输入参数的类型、需要resultType指定输出结果的映射类型。如果在指定类型时输入类型全路径,不方便进行开发,可以针对parameterType或resultType指定的类型定义一些别名,在配置文件中通过别名定义,方便开发。

(typeAliases配置别名,type属性指定的是实体类全限定名,alies属性指定别名,当指定了别名就不再区分大小写)

    <typeAliases>
        <typeAlias type="edu.xatu.Domain.User" alias="user"></typeAlias>
        <!--用于配置要指定别名的包,当指定后,该包下的实体类都会被注册别名,而且类名就是别名,不再区分大小写-->
        <package name="edu.xatu.Domain"></package>
    </typeAliases>

4. typeHandlers

mybatis中通过typeHandlers完成jdbc类型和java类型的转换。通常情况下,mybatis提供的类型处理器满足日常需要,不需要自定义。具体可参考Mybatis的官方文档。

5. Mappers (映射器)

Mapper配置的几种方法:

      第一种

        <mapper resource=" " /> resource指向的是相对于类路径下的目录

         如:<mapper resource="sqlmap/User.xml" />

       第二种

        <mapper url=" " /> 使用完全限定路径

         如:<mapper url="file:///D:\workspace\mybatis1\config\sqlmap\User.xml" />

       第三种

        <mapper class=" " /> 使用mapper接口类路径

         如:<mapper class="cn.kang.mapper.UserMapper"/>

注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。

       第四种

        <package name=""/> 注册指定包下的所有mapper接口

         如:<package name="cn.kang.mapper"/>

注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。

6.Mapper 映射文件

     Mapper.xml映射文件中定义了操作数据库的sql,每个sql是一个statement,映射文件是mybatis的核心

     Mapper映射文件是一个xml格式文件,必须遵循相应的dtd文件规范

     Mapper映射文件是以<mapper>作为根节点,在根节点中支持9个元素,分别为insert、update、delete、select(增删改查);cache、cache-ref、resultMap、parameterMap、sql

7. select

(1)id (必须配置)

        id是命名空间中的唯一标识符,可被用来代表这条语句。

        一个命名空间(namespace) 对应一个dao接口, 这个id也应该对应dao里面的某个方法(相当于方法的实现),因此id 应该与方法名一致。

(2)parameterType (可选配置, 默认为mybatis自动选择处理)

       将要传入语句的参数的完全限定类名或别名, 如果不配置,mybatis会通过ParameterHandler 根据参数类型默认选择合适的typeHandler进行处理,parameterType 主要指定参数类型,可以是int, short, long, string等类型,也可以是复杂类型。

(3)resultType (resultType 与 resultMap 二选一配置)

         resultType用以指定返回类型,指定的类型可以是基本类型,可以是java容器,也可以是javabean。

(4)resultMap (resultType 与 resultMap 二选一配置)

         resultMap用于引用我们通过 resultMap标签定义的映射类型,这也是mybatis组件高级复杂映射的关键。

(5)flushCache (可选配置)

         将其设置为 true,任何时候只要语句被调用,都会导致本地缓存和二级缓存都会被清空,默认值:false 。

(6)statementType (可选配置)

          STATEMENT,PREPARED 或 CALLABLE 的一个。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。

(7)resultSetType (可选配置)

         FORWARD_ONLY,SCROLL_SENSITIVE 或 SCROLL_INSENSITIVE 中的一个,默认值为 unset (依赖驱动)。

8. parameterType(输入类型)

通过parameterType指定输入参数的类型,类型可以是简单类型、hashmap、pojo的包装类型。

       #{}实现的是向prepareStatement中的预处理语句中设置参数值,sql语句中#{}表示一个占位符即?。

(1)parameterType也可以传递pojo对象。Mybatis使用ognl表达式解析对象字段的值。

(2)parameterType也可以传递hashmap类型的参数

9. resultType(返回值类型)

使用resultType可以进行输出映射,只有查询出来的列名和pojo中的属性名一致,才可以映射成功。如果查询出来的列名和pojo中的属性名全部不一致,就不会创建pojo对象。但是只要查询出来的列名和pojo中的属性有一个一致,就会创建pojo对象。

10. resultMap(输出结果映射)

      mybatis中可以使用resultMap完成高级输出结果映射。如果查询出来的列名和定义的pojo属性名不一致,就可以通过定义一个resultMap对列名和pojo属性名之间作一个映射关系。然后使用resultMap作为statement的输出映射类型。resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list实现一对一查询和一对多查询。

11. Plugins (插件)

啥都先别说,来个例子你就明白了:

    <!-- 配置分页插件 -->
    <plugins>
        <plugin interceptor="com.github.pagehelper.PageHelper">
    <!-- 设置数据库类型 Oracle,Mysql,MariaDB,SQLite,Hsqldb,PostgreSQL六种数据库-->        
            <property name="dialect" value="mysql"/>
        </plugin>
    </plugins>

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值