Mybatis入门案例

搭建环境

创建表

CREATE TABLE `users` ( `userid` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(20) DEFAULT NULL, `usersex` varchar(10) DEFAULT NULL, PRIMARY KEY (`userid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

在这里插入图片描述

添加DTD文件

添加DTD约束文件

在没有联网的情况下,如果让 dtd 约束继续起作用,并且出现标签提示,可以通过引入 本地 dtd 文件来实现。
下 载 dtd : 在 浏 览 器 中 输 入 dtd 的 网 络 地 址 即 可 实 现 下 载 。 比 如 : http://mybatis.org/dtd/mybatis-3-config.dtd
将下载的 dtd 拷贝到本地的一个目录下
Idea 操作路径:File—Settings—Languages & Frameworks
在这里插入图片描述
在这里插入图片描述

其中 URL 复制 dtd 的网络地址即可。File 选择 dtd 文件在本地的地址。OK!
注:在 MyBatis 的核心 jar 包中就提供了 mybatis-3-config.dtd
在这里插入图片描述

添加映射配置DTD文件

在这里插入图片描述
在这里插入图片描述
其中 URL 复制映射文件的网络地址即可。File 选择 映射文件在本地的地址。OK!
在这里插入图片描述

创建项目

创建一个java project的项目即可
在这里插入图片描述
在这里插入图片描述

添加jar包

一共需要添加12个jar包
一个mybatis的核心jar包,位置在下载的mybatis文件夹内:
在这里插入图片描述
在lib文件夹下,有10个辅助jar包:
在这里插入图片描述
同时还需要一个数据库的驱动jar包:
在这里插入图片描述

我们将其整合到一个文件夹下:
在这里插入图片描述
一共12个jar包
将其导入到项目内:
在这里插入图片描述

创建实体

在这里插入图片描述

package com.bjsxt.pojo;

public class Users {
    private int userid;
    private String username;
    private String usersex;

    public int getUserid() {
        return userid;
    }

    public void setUserid(int userid) {
        this.userid = userid;
    }

    public String getUsername() {
        return username;
    }

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

    public String getUsersex() {
        return usersex;
    }

    public void setUsersex(String usersex) {
        this.usersex = usersex;
    }
}


创建 properties 文件

将其放到src的根目录下
在这里插入图片描述

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3307/sys
jdbc.username=root
jdbc.password=1234567

创建全局配置文件

将其放到src的根目录下
在这里插入图片描述

<?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文件-->
    <properties resource="db.properties"/>

    <!-- 开启SLF4J做日志处理-->
    <settings>
        <setting name="logImpl" value="SLF4J"/>
    </settings>
    <!--配置别名-->
    <typeAliases>
        <typeAlias type="com.bjsxt.pojo.Users" alias="u"/>
        <package name="com.bjsxt.pojo"/>
    </typeAliases>
    <!--环境的配置-->
    <environments default="development">
        <environment id="development">
            <!-- 配置事务-->
            <transactionManager type="JDBC"></transactionManager>
            <!-- 配置数据源-->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>

    <!--引入映射配置文件-->
    <mappers>
        <!-- 使用相对路径方式引入-->
        <mapper resource="com/bjsxt/mapper/UsersMapper.xml"/>
    </mappers> 
    
</configuration>

我们需要创建一个映射配置文件,并将其引入到全局配置文件内
关键代码为:

    <!--引入映射配置文件-->
    <mappers>
        <!-- 使用相对路径方式将映射配置文件引入-->
        <mapper resource="com/bjsxt/mapper/UsersMapper.xml"/>
    </mappers>

创建映射配置文件

在这里插入图片描述
创建的映射配置文件的名字和实体类有关

<?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.bjsxt.mapper.UserMapper">
  
</mapper>

查询所有数据

修改映射配置文件UsersMapper.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.bjsxt.mapper.UserMapper">

    <!--查询所有用户-->
    <select id="selectUsersAll" resultType="com.bjsxt.pojo.Users">
         select * from users
    </select>
  
</mapper>

创建UserDao接口

package com.bjsxt.dao;

import com.bjsxt.pojo.Users;

import java.io.IOException;
import java.util.List;

public interface UsersDao {
    List<Users> selectUsersAll() throws IOException;
}

创建UserDao接口实现类

package com.bjsxt.dao.impl;

import com.bjsxt.dao.UsersDao;
import com.bjsxt.pojo.Users;
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 UsersDaoImpl implements UsersDao {
    @Override
    public List<Users> selectUsersAll()throws IOException {
        //创建SqlSessionFactory对象
        InputStream inputStream = Resources.getResourceAsStream("mybatis-cfg.xml");
        SqlSessionFactory sqlSessionFacotry = new SqlSessionFactoryBuilder().build(inputStream);
        //获取SqlSession对象
        SqlSession sqlSession = sqlSessionFacotry.openSession();
        //通过SqlSession对象下的API完成对数据库的操作
        List<Users> list = sqlSession.selectList("com.bjsxt.mapper.UserMapper.selectUsersAll");
        //关闭SqlSession对象
        sqlSession.close();
        return list;
    }
  
}


创建测试类

package com.bjsxt.test;

import com.bjsxt.dao.UsersDao;
import com.bjsxt.dao.impl.UsersDaoImpl;
import com.bjsxt.pojo.Users;

import java.io.IOException;
import java.util.List;

public class Test {
    public static void main(String[] args) throws IOException {
        UsersDao usersDao = new UsersDaoImpl();
        List<Users> list = usersDao.selectUsersAll();
        for(Users users:list){
            System.out.println(users.getUserid()    +"\t"+users.getUsername()+"\t "+users.getUsersex());
        }
    }
}

在这里插入图片描述

注意:

  1. 当控制台爆出如下异常:
    在这里插入图片描述
    这是因为没有在db.properties文件内jdbc.url后添加?useSSL=false
    添加后异常消失

  2. 如果爆出如下异常:
    在这里插入图片描述
    也就是java.sql.SQLException: Unknown error 1045
    这是密码jdbc.password前后有空格导致的。
    去除后正常

  3. 出现如下问题
    在这里插入图片描述
    说明没有添加log4j的输出日志
    创建一个log4j的输出日志文件
    在这里插入图片描述

log4j.rootLogger=debug,console,logfile

### appender.console输出到控制台 ###
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=<%d> %5p (%F:%L) [%t] (%c) - %m%n
log4j.appender.console.Target=System.out

### appender.logfile输出到日志文件 ###
log4j.appender.logfile=org.apache.log4j.RollingFileAppender
log4j.appender.logfile.File=SysLog.log
log4j.appender.logfile.MaxFileSize=500KB
log4j.appender.logfile.MaxBackupIndex=7
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=<%d> %p (%F:%L) [%t] %c - %m%n

在这里插入图片描述
异常消失

根据用户的id去查询数据

修改映射配置文件UsersMapper.xml

    <!--根据用户ID查询用户-->
    <select id="selectUsersById" parameterType="int" resultType="users">
         select * from users where userid = #{suibian}
    </select>

修改UsersDao接口

package com.bjsxt.dao;

import com.bjsxt.pojo.Users;

import java.io.IOException;
import java.util.List;
import java.util.Map;

public interface UsersDao {
    List<Users> selectUsersAll()throws IOException;
    //添加根据id查询用户的抽象方法
    Users selectUsersById(int userid)throws IOException;
}

修改 UsersDao 接口实现类

    /**
     *  根据用户ID查询用户
     * @param userid
     * @return
     * @throws IOException
     */
    @Override
    public Users selectUsersById(int userid) throws IOException {
        //创建SqlSessionFactory对象
        InputStream inputStream = Resources.getResourceAsStream("mybatis-cfg.xml");
        SqlSessionFactory sqlSessionFacotry = new SqlSessionFactoryBuilder().build(inputStream);
        //获取SqlSession对象
        SqlSession sqlSession = sqlSessionFacotry.openSession();
        Users users = sqlSession.selectOne("com.bjsxt.mapper.UserMapper.selectUsersById",userid);
        sqlSession.close();
        return users;
    }

修改测试类

package test;

import com.bjsxt.dao.UsersDao;
import com.bjsxt.dao.impl.UsersDaoImpl;
import com.bjsxt.pojo.Users;

import java.io.IOException; 

public class Test {
    public static void main(String[] args)throws IOException {
        UsersDao usersDao = new UsersDaoImpl();
        Users users = usersDao.selectUsersById(1);
        System.out.println(users.getUserid()+"\t"+users.getUsername()+"\t"+users.getUsersex());
    }
}

在这里插入图片描述

Mybatis中的参数绑定的方式

在映射配置文件中向 SQL 语句中绑定参数的语法结构为#{ }和${ }。
#{ } 和 ${ }的区别:
#{ } 解析为一个 JDBC 预编译语句(PreparedStatement)的参数标记符占位符 ?。使 用该方式可避免 SQL 注入。
仅 仅 为 一 个 纯 碎 的 S t r i n g 替 换 , 在 M y b a t i s 的 动 态 S Q L 解 析 阶 段 将 会 进 行 变 量 替 换 。 { } 仅仅为一个纯碎的 String 替换,在 Mybatis 的动态 SQL 解析阶段将会进行变量替 换。 StringMybatisSQL{ } 在预编译之前已经被变量替换了,这会存在 SQL 注入问题。

创建 Mybatis 的工具类

为什么要使用Mybatis的工具类

因为对比上面的接口实现类内的两个查询方法,我们可以发现代码可以被进一步简化

用到的知识

ThreadLocal介绍
ThreadLocal提供了线程内存储变量的能力,这些变量的不同之处在于每一个线程读取的变量是对应的,相互独立的。通过get和set方法就可以得到当前线程对应的值。
使用ThreadLocal去存储SqlSession
如果多个DML操作属于一个事务,因为commit()和rollback()都是由SqlSession完成,所以必须保证使用一个SQLSession。但是多个不同的DML操作可能在不同类的不同方法内,每个方法中要单独的获取SqlSession。比如商城下订单时,其实涉及商品库存变化、订单添加、订单明细添加、付款、日志添加等多个 DML 操作,分布在不同类中。

如何在多个 DML 操作之间使用同一个 SqlSession 呢,可以使用 ThreadLocal 来存储。保 证一个线程中的操作使用的都是一个 SqlSession。

创建Mybatis工具类

package com.bjsxt.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.IOException;
import java.io.InputStream;

public class MybatisUtils {
    private static ThreadLocal<SqlSession> threadLocal = new ThreadLocal<>();
    private static SqlSessionFactory sqlSessionFactory = null;
    static{
        //创建SqlSessionFactory
        InputStream is = null;
        try{
            //读取mybatis-cfg.xml文件
            is = Resources.getResourceAsStream("mybatis-cfg.xml");
        }catch (IOException e){
            e.printStackTrace();
        }
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
    }

    //获取SqlSession
    public static SqlSession getSqlSession(){
        SqlSession sqlSession = threadLocal.get();
        //在当前线程内没有找到的时候(也就是第一次通过工具类在sqlsession内查找没有找到)
        if(sqlSession == null){
            sqlSession = sqlSessionFactory.openSession();
            threadLocal.set(sqlSession);
        }
        return sqlSession;
    }

    //关闭SqlSession
    public static void closeSqlSession(){
        SqlSession sqlSession = threadLocal.get();
        //如果找到
        if(sqlSession != null){
            sqlSession.close();
            threadLocal.set(null);
        }
    }
}

有这个工具类,mybatis框架不需要被频繁启动;第二个是通过threadLocal缓存了SqlSession ,可以保证再一个线程内对数据库的操作可以拿到一样的SqlSession 。

完成DML操作

Mybatis的事务提交方式

在 Mybatis 中事务提交方式默认为手动提交,这与 JDBC 是不同的。在 JDBC 中事务默认 提交方式为自动提交。
在这里插入图片描述
主流是对事务进行手动提交

添加用户操作

修改映射配置文件

    <!--添加用户-->
    <insert id="insertUsers" >
        insert into users value(default ,#{username},#{usersex})
    </insert>

修改UsersDao接口


    //添加用户的抽象方法
    void insertUsers(Users users);

修改UsersDao接口实现类


    @Override
    public void insertUsers(Users users) {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        sqlSession.insert("com.bjsxt.mapper.UserMapper.insertUsers", users);
    }

创建业务层的接口UsersService

package com.bjsxt.service;

import com.bjsxt.pojo.Users;
//业务层的抽象方法
public interface UsersService {
    //添加的抽象方法
    void addUsers(Users users);
}

创建业务层的接口实现类

package com.bjsxt.service.impl;

import com.bjsxt.dao.UsersDao;
import com.bjsxt.dao.impl.UsersDaoImpl;
import com.bjsxt.pojo.Users;
import com.bjsxt.service.UsersService;
import com.bjsxt.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;

import java.util.Map;

public class UsersServiceImpl implements UsersService {
    /**
     * 添加用户
     * @param users
     */
    @Override
    public void addUsers(Users users) {
        //使用自定义的mybatis抽象类
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        try{
            UsersDao usersDao =  new UsersDaoImpl();
            usersDao.insertUsers(users);
            //启动sqlsession
            sqlSession.commit();
        }catch (Exception e){
            e.printStackTrace();
            sqlSession.rollback();
        }finally{
            //使用工具类关闭sqlsession
            MybatisUtils.closeSqlSession();
        }
    }
}

创建新的测试类AddUsersTest

package test;

import com.bjsxt.pojo.Users;
import com.bjsxt.service.UsersService;
import com.bjsxt.service.impl.UsersServiceImpl;
 

public class AddUsersTest {
    public static void main(String[]args){
    
        UsersService usersService = new UsersServiceImpl();
        Users users = new Users();
        users.setUsername("zhangsan");
        users.setUsersex("womale");
        usersService.addUsers(users);
    }
 
}

在这里插入图片描述
在这里插入图片描述
也可以使用Scanner将其改为控制台输入

案例:


    public static void ScannerTest(){
        Scanner sc = new Scanner(System.in);
        System.out.println("ScannerTest, Please Enter Name:");
        String name = sc.nextLine();  //读取字符串型输入
        System.out.println("ScannerTest, Please Enter Age:");
        int age = sc.nextInt();    //读取整型输入
        System.out.println("ScannerTest, Please Enter Salary:");
        float salary = sc.nextFloat(); //读取float型输入
        System.out.println("Your Information is as below:");
        System.out.println("Name:" + name +"\n" + "Age:"+age + "\n"+"Salary:"+salary);
    }

更新用户操作

有两个行为,先查到用户的数据,再将修改后的内容存放在数据表数据原先的位置

修改映射配置文件

    <!--预更新用户的查询--> 
    <select id="selectUserById2" resultType="com.bjsxt.pojo.Users">
 		select * from users where userid = ${userid}
   </select>
   <!--更新用户操作-->
    <update id="updateUsersById" >
        update users set username = #{username},usersex=#{usersex} where userid = #{userid}
    </update>

修改 UsersDao 接口

	//预更新用户的抽象方法
    Users selectUsersById2(int userid);
    //更新用户的抽象方法
    void updateUsersById(Users users);

修改UsersDao的接口实现类

    //预更新用户的查询
    @Override
    public Users selectUsersById2(int userid) {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        Users users =  sqlSession.selectOne("com.bjsxt.mapper.UserMapper.selectUserById2",userid);
        return users;
    }

    //更新用户
    @Override
    public void updateUsersById(Users users) {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        sqlSession.update("com.bjsxt.mapper.UserMapper.updateUsersById", users);
    }

修改UsersService接口


    //获取预更新的用户信息的抽象方法
    Users preUpdateUsers(int userid);
    //更新的抽象方法
    void modifyUsers(Users users);

修改UsersService接口实现类


    /**
     * 获取预更新用户的信息
     * @param userid
     * @return
     */
    @Override
    public Users preUpdateUsers(int userid) {
        Users users = null;
        try{
            SqlSession sqlSession = MybatisUtils.getSqlSession();
            UsersDao usersDao = new UsersDaoImpl();
            users = usersDao.selectUsersById2(userid);
        }catch(Exception e){
            e.printStackTrace();
        }finally {
            MybatisUtils.closeSqlSession();
        }
        return users;
    }

    /**
     * 更新用户的信息
     * @param users
     */
    @Override
    public void modifyUsers(Users users) {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        try{
            UsersDao usersDao = new UsersDaoImpl();
            usersDao.updateUsersById(users);
            sqlSession.commit();
        }catch(Exception e){
            e.printStackTrace();
            //将异常回滚
            sqlSession.rollback();
        }finally {
            MybatisUtils.closeSqlSession();
        }
    }

创建测试类

package test;

import com.bjsxt.pojo.Users;
import com.bjsxt.service.UsersService;
import com.bjsxt.service.impl.UsersServiceImpl;

public class UpdateUsersTest {
    public static void main(String[] args) {
        UsersService usersService = new UsersServiceImpl();
        Users users = usersService.preUpdateUsers(2);
        System.out.println("更新前:"+users.getUserid() +"  "+users.getUsername()+"  "+users.getUsersex());
        users.setUsername("OLDLU");
        users.setUsersex("MALE");
        usersService.modifyUsers(users);

        Users users2 = usersService.preUpdateUsers(2);
        System.out.println("更新后:"+users2.getUserid() +"  "+users2.getUsername()+"  "+users2.getUsersex());
    }
}


在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
mybatis框架只启动了一次, 我们获取了两次SqlSession,是在主线程内先关闭了一次sqlsession,又在主线程内拿了一次sqlsession,又将这两个sqlsession都放到了同一个threadLocal内

删除用户操作

修改映射配置文件

修改UsersDao接口


   <!-- 根据用户ID删除用户-->
    <delete id="deleteUsersById">
        delete from users where userid = #{userid}
    </delete>

修改UsersDaoImpl实现类


    @Override
    public void deleteUsersById(int userid) {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        final int delete = sqlSession.delete("com.bjsxt.mapper.UserMapper.deleteUsersById", userid);
    }

修改UsersServlet接口


    //根据id删除的抽象方法
    void dropUsersById(int userid);

修改UsersServletImpl接口实现类


    @Override
    public void dropUsersById(int userid) {
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        try{
            UsersDao usersDao = new UsersDaoImpl();
            usersDao.deleteUsersById(userid);
            sqlSession.commit();
        }catch(Exception e){
            e.printStackTrace();
            sqlSession.rollback();
        }finally{
            MybatisUtils.closeSqlSession();
        }
    }

创建测试类

package com.bjsxt.test;

import com.bjsxt.service.UsersService;
import com.bjsxt.service.impl.UsersServiceImpl;

public class DeleteUsersTest {
    public static void main(String[] args) {
        UsersService usersService = new UsersServiceImpl();
        usersService.dropUsersById(3);
    }
}

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值