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

目录

回顾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>

 

 

 

 

发布了45 篇原创文章 · 获赞 11 · 访问量 4808

猜你喜欢

转载自blog.csdn.net/weixin_44187963/article/details/104975306