MyBatis配置文件编写及CRUD操作


实验要求:
掌握MyBatis的配置文件的编写与使用。

实验内容:
实验1:参考教材2.1、2.2和2.3小节的内容,配置文件中<properties>、<typeAliases>、<environments>以及<mappers>元素的使用,完成SqlSession工具类的编写。总结核心配置文件及映射文件各种属性的使用方法。
实验2:完成教材案例2.4,员工管理系统的员工信息的CRUD。
实验3:完成教材案例3.5,学生信息查询功能。
实验4:(选)利用Mybatis完成银行转账系统的DAO层的功能改造

实验分析:

实验操作所用工具(软件):
IntelliJ IDEA 2021.2.1

实验1

一、Mybatis的全局配置文件

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

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

environments
  MyBatis 可以配置多种环境。这会帮助你将 SQL 映射应用于多种数据库之中。但是要记得一个很重要的问题:你可以配置多种环境,但每个数据库对应一个 SqlSessionFactory。所以,如果你想连接两个数据库,你需要创建两个 SqlSessionFactory 实例,每个数据库对应一个。而如果是三个数据库,你就需要三个实例,以此类推。

mappers
Mapper配置的几种方法:

     第一种(常用)
        <mapper resource=" " /> resource指向的是相对于类路径下的目录
         如:<mapper resource="xxx/User.xml" />
     第二种
        <mapper url=" " /> 使用完全限定路径
         如:<mapper url="file:///D:\xxxxx\xxx\User.xml" />
     第三种
        <mapper class=" " /> 使用mapper接口类路径
         如:<mapper class="cn.xx.mapper.UserMapper"/>
注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。
     第四种(推荐)
        <package name=""/> 注册指定包下的所有mapper接口
         如:<package name="cn.xx.mapper"/>
注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。
  使用示例:
    <mappers>
        <mapper resource="xxx/User.xml"/>
        <package name="cn.xx.mapper"/>
    </mappers>

二、Mapper映射文件

  Mapper.xml映射文件中定义了操作数据库的sql,每个sql是一个statement,映射文件是mybatis的核心
Mapper映射文件是一个xml格式文件,必须遵循相应的dtd文件规范,如ibatis-3-mapper.dtd
Mapper映射文件是以作为根节点,在根节点中支持9个元素,分别为insert、update、delete、select(增删改查);cache、cache-ref、resultMap、parameterMap、sql。
(一)select、parameterMap、resultType、resultMap

 
    
     1、<select
         <!-- (1)id (必须配置)
        id是命名空间中的唯一标识符,可被用来代表这条语句。
        一个命名空间(namespace) 对应一个dao接口,
        这个id也应该对应dao里面的某个方法(相当于方法的实现),因此id 应该与方法名一致  
         -->
     
        id="findUserById"  --- 对应接口中的方法名
     
         <!--(2)parameterType (可选配置, 默认为mybatis自动选择处理)
        将要传入语句的参数的完全限定类名或别名, 如果不配置,mybatis会通过ParameterHandler 根据参数类型默认选择合适的typeHandler进行处理
          parameterType 主要指定参数类型,可以是int, short, long, string等类型,也可以是复杂类型(如对象) 
         -->
        parameterType="int"
     
          <!-- (3)resultType (resultType 与 resultMap 二选一配置)
         resultType用以指定返回类型,指定的类型可以是基本类型,可以是java容器,也可以是javabean 
          -->
        resultType="User"
     
          <!--(4)resultMap (resultType 与 resultMap 二选一配置)
              resultMap用于引用我们通过 resultMap标签定义的映射类型,这也是mybatis组件高级复杂映射的关键 
          -->
        resultMap="userResultMap"
     
          <!--(5)flushCache (可选配置)
         将其设置为 true,任何时候只要语句被调用,都会导致本地缓存和二级缓存都会被清空,默认值:false 
          -->
        flushCache="false"
     
          <!--(6)useCache (可选配置)
         将其设置为 true,将会导致本条语句的结果被二级缓存,默认值:对 select 元素为 true 
          -->
        useCache="true"
     
          <!--(7)timeout (可选配置)
         这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为 unset(依赖驱动)
          -->
        timeout="10000"
     
          <!-- (8)fetchSize (可选配置)
         这是尝试影响驱动程序每次批量返回的结果行数和这个设置值相等。默认值为 unset(依赖驱动)
          -->
        fetchSize="256"
     
          <!--(9)statementType (可选配置)
          STATEMENT,PREPARED 或 CALLABLE 的一个。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED
          -->
     statementType="PREPARED"
     
          <!--(10)resultSetType (可选配置)
         FORWARD_ONLY,SCROLL_SENSITIVE 或 SCROLL_INSENSITIVE 中的一个,默认值为 unset (依赖驱动)
          -->
     resultSetType="FORWARD_ONLY"
      >

2、parameterType(输入类型)
  通过parameterType指定输入参数的类型,类型可以是简单类型、hashmap、pojo的包装类型。
#{}实现的是向prepareStatement中的预处理语句中设置参数值,sql语句中#{}表示一个占位符即?。
例如:

<select id="findUserById" parameterType="int" resultType="user">
  select * from user where id = #{id}
  </select>

  1. 使用占位符#{}可以有效防止sql注入,在使用时不需要关心参数值的类型,mybatis会自动进行java类型和jdbc类型的转换。
  2. #{}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。

${}和#{}的区别

  • ${}和#{}不同,通过${}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换,可 以 接 收 简 单类 型 值 或 pojo属 性 值 , 如 果 parameterType 传 输 单 个 简 单 类 型 值 ,{}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,{}括号中只能是value。使用不能防止sql注入 ,但 是 有 时 用 {}不能防止sql注入,但是有时用不能防止sql注入,但是有时用{}会非常方便,如下的例子:
<select id="selectUserByName" parameterType="string" resultType="user">
select * from user where username like '%${value}%'
</select>

  使用#{}则传入的字符串中必须有%号,而%是人为拼接在参数中,显然有点麻烦,如果采用在 s q l 中 拼 接 为 传 递 参 数 就 方 便 很 多 。 如 果 使 用 {}在sql中拼接为%的方式则在调用mapper接口 传递参数就方便很多。如果使用在sql中拼接为传递参数就方便很多。如果使用{}原始符号则必须人为在传参数中加%。
使用#的如下:

  List<User> list = userMapper.selectUserByName("%管理员%");

3、resultType(返回值类型)

  • 使用resultType可以进行输出映射,只有查询出来的列名和pojo中的属性名一致,才可以映射成功。如果查询出来的列名和pojo中的属性名全部不一致,就不会创建pojo对象。但是只要查询出来的列名和pojo中的属性有一个一致,就会创建pojo对象。
  • resultType可以输出简单类型。例如查询用户信息的综合查询列表总数,通过查询总数和上边用户综合查询列表才可以实现分页。
   <!-- 获取用户列表总数 -->
   <select id="findUserCount" parameterType="user" resultType="int">
       select count(*) from user
     </select>

  resultType可以输出pojo对象和pojo列表。当使用动态代理时,输出pojo对象和输出pojo列表在xml映射文件中定义的resultType是一样的,而生成的动态代理对象中是根据mapper方法的返回值类型确定是调用selectOne(返回单个对象调用)还是selectList (返回集合对象调用 )。

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

实验2

员工管理系统

实验3

学生信息查询系统

实验4

Resource

db.properties(数据库连接配置文件)

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/test?serverTimezone=UTC&\ characterEncoding=utf8&useUnicode=true&useSSL=false
username=root
password=1

mybatis-config.xml(MyBatis的核心配置文件)

<?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="db.properties"> </properties>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <!--    数据库连接相关配置,db.properties文件中的内容    -->
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="mapper/AccountMapper.xml"/>
        <mapper resource="mapper/LogMapper.xml"/>
    </mappers>
</configuration>

AccountMapper.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.cqust.pojo.Account">
    <insert id="addAccount" parameterType="com.cqust.pojo.Account">
        insert into tb_account (username,cardID,balance) values (#{username},#{cardID},#{balance})
    </insert>
    <update id="deposit" parameterType="com.cqust.pojo.Account">
        update tb_account set balance = balance + #{balance} where cardID=#{cardID}
    </update>
    <update id="withdrawal" parameterType="com.cqust.pojo.Account">
        update tb_account set balance = balance - #{balance} where cardID=#{cardID}
    </update>
    <update id="transfer" parameterType="com.cqust.pojo.Account">
        update tb_account set balance = balance - #{balance} where cardID=#{cardID}
    </update>
</mapper>

LogMapper.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.cqust.pojo.Log">
    <insert id="addLog" parameterType="com.cqust.pojo.Log">
        insert into tb_log (name,type,amount,time) values (#{name},#{type},#{amount},#{time})
    </insert>
    <insert id="transferLog" parameterType="com.cqust.pojo.Log">
        insert into tb_log (name,type,amount,outUser,inUser,time) values (#{name},#{type},#{amount},#{outUser},#{inUser},#{time})
    </insert>
</mapper>

pojo层

Account类

package com.cqust.pojo;

public class Account {
    private int id;
    private String username;
    private String cardID;
    private double balance;


    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getCardID() {
        return cardID;
    }

    public void setCardID(String cardID) {
        this.cardID = cardID;
    }

    public double getBalance() {
        return balance;
    }

    public void setBalance(double balance) {
        this.balance = balance;
    }

    @Override
    public String toString() {
        return "账户{" +
                "id=" + id +
                ", 用户名='" + username + '\'' +
                ", cardID='" + cardID + '\'' +
                ", 余额=" + balance +
                '}';
    }

}

Log类

package com.cqust.pojo;

import java.util.Date;

public class Log {
    private int id;
    private String name;
    private String type;
    private double amount;
    private String outUser;
    private String inUser;
    private Date time;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public double getAmount() {
        return amount;
    }

    public void setAmount(double amount) {
        this.amount = amount;
    }

    public String getOutUser() {
        return outUser;
    }

    public void setOutUser(String outUser) {
        this.outUser = outUser;
    }

    public String getInUser() {
        return inUser;
    }

    public void setInUser(String inUser) {
        this.inUser = inUser;
    }

    public Date getTime() {
        return time;
    }

    public void setTime(Date time) {
        this.time = time;
    }

    @Override
    public String toString() {
        return "Log{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", type='" + type + '\'' +
                ", amount=" + amount +
                ", outUser='" + outUser + '\'' +
                ", inUser='" + inUser + '\'' +
                ", time=" + time +
                '}';
    }

}

utils层

MyBatisUtils类

package com.cqust.utils;

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.Reader;

/**
 * 工具类
 */
public class MyBatisUtils {
    private static SqlSessionFactory sqlSessionFactory = null;
    //初始化SQLSessionFactory对象
    static {
        try{
            //使用MyBatis提供的Resource类加载MyBatis的配置文件
            Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
            //构建SQLSessionFactory
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
        } catch (Exception e){
            e.printStackTrace();
        }
    }
    //获取SqlSession对象的方法
    public static SqlSession getSession(){
        //若传入true表示关闭事务控制,自动提交;false表示开启事务控制
        return sqlSessionFactory.openSession(true);
    }
}

测试层

Test2(测试类)

import com.cqust.pojo.Account;
import com.cqust.pojo.Log;
import com.cqust.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.text.SimpleDateFormat;
import java.util.Date;


public class Test2 {
    @Test
    public void addAccountTest(){
        SqlSession session = MyBatisUtils.getSession();
        System.out.println("正在开户...");
        Account account = new Account();
        Log log = new Log();
        Date date=new Date(System.currentTimeMillis());                                                         //获取当前时间并实例化
//        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");   //定义时间格式并初始化
//        System.out.println(sdf.format(date));
        account.setUsername("八戒");
        account.setCardID("002");
        account.setBalance(99.99);
        session.insert("addAccount",account);
        log.setName("八戒");
        log.setType("addAccount");
        log.setAmount(99.99);
        log.setTime(date);
        session.insert("addLog",log);
        System.out.println("开户成功!");
        session.close();
    }
    @Test
    public void depositTest(){
        SqlSession session = MyBatisUtils.getSession();
        System.out.println("正在存款...");
        Account account = new Account();
        Log log = new Log();
        Date date=new Date(System.currentTimeMillis());                                                         //获取当前时间并实例化
        account.setBalance(100.00);
        account.setCardID("985211");
        session.update("deposit",account);
        log.setName("Hades");
        log.setType("deposit");
        log.setAmount(100.00);
        log.setTime(date);
        session.insert("addLog",log);
        System.out.println("存款成功!");
        session.close();
    }
    @Test
    public void withdrawalTest(){
        SqlSession session = MyBatisUtils.getSession();
        System.out.println("正在取款...");
        Account account = new Account();
        Log log = new Log();
        Date date=new Date(System.currentTimeMillis());                                                         //获取当前时间并实例化
        account.setBalance(100.00);
        account.setCardID("985211");
        session.update("withdrawal",account);
        log.setName("Hades");
        log.setType("withdrawal");
        log.setAmount(10.00);
        log.setTime(date);
        session.insert("addLog",log);
        System.out.println("取款成功!");
        session.close();
    }
    @Test
    public void transferTest(){
        SqlSession session = MyBatisUtils.getSession();
        System.out.println("正在转账...");
        Account account1 = new Account();
        Account account2 = new Account();
        Log log = new Log();
        Date date=new Date(System.currentTimeMillis());                                                         //获取当前时间并实例化
        account1.setBalance(100.00);
        account1.setCardID("985211");
        session.update("withdrawal",account1);
        account2.setBalance(100.00);
        account2.setCardID("000");
        session.update("deposit",account2);
        log.setName("Hades");
        log.setType("transfer");
        log.setAmount(10.00);
        log.setOutUser("Hades");
        log.setInUser("ikun");
        log.setTime(date);
        session.insert("transferLog",log);
        System.out.println("转账成功!");
        session.close();
    }
}

程序运行结果:
实验4:

在这里插入图片描述

实验总结:
本次实验主要是对实验4的书写,即对银行转账系统的DAO层的功能改造,主要是对MyBatis的核心配置内容和动态SQL内容的综合运用,其中数据库的时间与显示相差8个小时的问题弄了很久,非常感谢我的老师,不厌其烦地为我一一解答,终于解决了所有的问题,让程序顺利运行。这个版本的代码是初稿,写的非常的粗糙鄙陋,希望后期学到新知识后能进行改进(本人很懒!)。

写在最后各位看到此博客的小伙伴,如有不对的地方请及时通过私信我或者评论此博客的方式指出,以免误人子弟。多谢!
  
谢谢浏览!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值