Day14JavaWeb【Mybatis一】

学习目标

  1. Mybatis的介绍
  2. Mybatis的入门
    a)使用jdbc操作数据库存在的问题 (回顾jdbc)
    b)Mybatis的架构
    c)Mybatis的入门程序 (重点)
  3. Dao的开发方法
    a)原始dao的开发方法 (了解)
    b)接口的动态代理方式 (重点)

Jdbc介绍

  • 案例: jdbc 做一个根据名称查询用户的操作
  • 什么是jdbc?
    Java Database Connectivity ,Java数据库连接 ,简称JDBC
    Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法
  • 什么是数据库驱动?
    数据库提供商对JDBC接口的实现类,如mysql,oracle,sqlserver
//接口
public interface JdbcApi{
	public void update();
}

//接口不能直接创建对象
JdbcApi api = new JdbcApi();
api.update();

//Myql厂商
public class MysqlJdbc implements JdbcApi{
	public void update(){
		//Mysql写了代码
	}
}
MysqlJdbc api = new MysqlJdbc();
api.update();
//Oracle 厂商
public class OracleJdbc implements JdbcApi{
	public void update(){
		//OracleJdbc写了代码
	}
}
OracleJdbc api = new OracleJdbc();
api.update();

Jdbc操作数据库原理图

  • Jdbc如何操作Mysql?
  1. 加载数据库驱动
  2. 创建并获取数据库链接
  3. 创建jdbc statement对象
  4. 设置sql语句
  5. 设置sql语句中的参数(使用preparedStatement)
  6. 通过statement执行sql并获取结果
  7. 对sql执行结果进行解析处理
  8. 释放资源(resultSet、preparedstatement、connection)
    在这里插入图片描述

Jdbc连接池原理图

  • 频繁创建连接,销毁连接造成极大资源开销
  • 连接池,即一个集合,可以管理连接对象
  • 有什么特点?
  1. 可以初始化指定数量的连接
  2. 可以指定集合的最大元素个数
  3. 可以申请连接池的连接
  4. 不用的连接可以放回连接池
    在这里插入图片描述

Jdbc代码分析总结

  1. jdbc 做一个根据名称查询用户的操作 搜索
  2. 初始化数据库
create database mybatis01;
use mybatis01;

drop table if exists `user`;
create table `user` (
  `id` int(11) primary key  auto_increment,
  `username` varchar(32) ,
  `birthday` date,
  `sex` char(1) ,
  `address` varchar(256)
) 
insert into `user` values ('1', '王五', '2014-07-10', '2', null);
insert into `user` values ('10', '张三', '2014-08-11', '1', '北京市');
insert into `user` values ('16', '张小明', '2015-07-10', '1', '河南郑州');
insert into `user` values ('22', '陈小明', '2016-07-10', '2', '重庆');
insert into `user` values ('24', '张三丰', '2019-07-10', '1', '天津');
insert into `user` values ('25', '陈小明', '2019-07-10', '1', '杭州');
insert into `user` values ('26', '王五', '2018-07-10', null, null);
  1. 配置mysql驱动的依赖
  • 创建maven工程,再创建web01模块
  • 配置依赖
  • pom.xml
<properties>
    <mysql.version>5.1.32</mysql.version>
  </properties>
 <!-- MySql -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>${mysql.version}</version>
    </dependency>
  1. 分析jdbc编写操作数据库代码的可改进地方
  • 频繁创建、释放数据库连接 ,性能开销大,没有自带连接池
  • Sql语句写在java代码中 ,硬编码
  • sql语句的where条件与占位符赋值没有写判断逻辑
  • 数据库记录需封装成pojo对象 User类 大量的编写 转换代码
public class TestJdbc {
    @Test
    public void test01() throws Exception {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        // 加载数据库驱动
        Class.forName("com.mysql.jdbc.Driver");
        // 通过驱动管理类获取数据库链接
        connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis01?characterEncoding=utf-8", "root", "123456");
        // 定义sql语句 ?表示占位符
        String sql = "select * from user where username = ?";
        // 获取预处理statement
        preparedStatement = connection.prepareStatement(sql);
        // 设置参数,第一个参数为sql语句中参数的序号(从1开始),第二个参数为设置的参数值
        preparedStatement.setString(1, "王五");
        // 向数据库发出sql执行查询,查询出结果集
        resultSet = preparedStatement.executeQuery();//将sql发送给数据库
        // 遍历查询结果集
        while (resultSet.next()) {
            System.out.println(resultSet.getString("id") + "  " + resultSet.getString("username"));
        }
        // 释放资源
        resultSet.close();
        preparedStatement.close();
        connection.close();
    }

}

Mybatis介绍

  1. Mybatis是什么?
    MyBatis 本是apache的一个开源项目iBatis,是一个基于Java的持久层框架,用来写dao
  2. Mybatis有什么特点?
  • 最简单安装只要两个jar文件+配置几个sql映射文件,自带连接池
  • sql写在xml里,便于统一管理和优化
  • sql和代码的分离,提高了可维护性
  • 提供映射标签,支持对象与数据库的orm字段关系映射
  • 提供对象关系映射标签,支持对象关系组建维护
  • 提供xml标签,支持编写动态sql
    总结一句,重点在xml配置,很少写java代码。

Mybatis架构

  1. mybaits 是对jdbc的封装
  2. 重点在配置文件xml
    在这里插入图片描述
  3. 架构图
    在这里插入图片描述
  • 核心 配置文件,放四大信息
    ip,port,username,password
  • 映射文件
    select
    update
    delete
    insert
  • SqlSessionFactory
    使用了工厂设计模式的生成session的对象

SqlSessionFactory是MyBatis的关键对象,它是个单个数据库映射关系经过编译后的内存镜像。
SqlSessionFactory对象的实例可以通过SqlSessionFactoryBuilder对象类获得,而SqlSessionFactoryBuilder则可以从XML配置文件或一个预先定制的Configuration的实例构建出SqlSessionFactory的实例。
每一个MyBatis的应用程序都以一个SqlSessionFactory对象的实例为核心.同时SqlSessionFactory也是线程安全的,SqlSessionFactory一旦被创建,应该在应用执行期间都存在,在应用运行期间不要重复创建多次
建议使用单例模式.SqlSessionFactory是创建SqlSession的工厂。

  • SqlSession对象
    支持增删改查,连接

SqlSession是MyBatis的关键对象,类似于JDBC中的Connection。
SqlSession对象完全包含以数据库为背景的所有执行SQL操作的方法,它的底层封装了JDBC连接,可以用SqlSession实例来直接执行被映射的SQL语句。每个线程都应该有它自己的SqlSession实例.SqlSession的实例不能被共享

同时SqlSession也是线程不安全的,绝对不能将SqlSeesion实例的引用放在一个类的静态字段甚至是实例字段中.也绝不能将SqlSession实例的引用放在任何类型的管理范围中
比如Servlet当中的HttpSession对象中.使用完SqlSeesion之后关闭Session很重要,应该确保使用finally块来关闭它.

由于JDBC的Connection对象本身不是线程安全的,而session中又只有一个connection,所以不是线程安全的

  1. 线程安全:
    指多个线程在执行同一段代码的时候采用加锁机制,使每次的执行结果和单线程执行的结果都是一样的,不存在执行程序时出现意外结果。
  2. 线程不安全:
    是指不提供加锁机制保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据。

Mybatis环境搭建

  • mybatis下载
    mybaits的代码由github.com管理
    下载地址:https://github.com/mybatis/mybatis-3/releases
  • 导入jar包
    测试相关的包: junit hamcrest
    日志相关的包:log4j-1.2.16 slf4-api slf4j-log4j12
    数据库相关jar包: mysql-connector
    Mybatis先关jar包: mybaits-3.4.5

因为有了Maven所以直接去仓库找gav即可
pom.xml

<dependencies>
        <!-- junit-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
        <!-- MySql -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.32</version>
        </dependency>
        <!-- Mybatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.5</version>
        </dependency>
        <!--日志包-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.25</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
    </dependencies>
  • 导入jar包log4j.properties
  • 创建log4j.properties文件
    在这里插入图片描述
    在这里插入图片描述
# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

Mybatis的操作步骤

  • mybatis开发流程
  1. 创建SqlSessionFactoryBuilder对象
  2. 创建SqlSessionFactory对象
  3. 加载SqlMapConfig.xml配置文件
  4. 创建SqlSession对象
  5. 执行SqlSession对象执行删除
  6. 打印结果
  7. 释放资源

Mybatis的入门案例-Java代码编写

(1)先获取Session
(2)再进行增删改查操作

src\main\resources\ 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">
<!-- map的约束文件-->
<!-- namespace 命名空间 防止id冲突找不到正确的id-->
<!-- id Mybatis是将sql语句写在xml文件中,以后session根据namesapce.id 合在一起获取sql-->
<!-- 在jdbc中,sql语句使用?作占位符,但在mybatis #{id}-->
<mapper namespace="com.vission.bean.User">
    <delete id="deleteById" parameterType="int" >
        delete from user where id = #{id}
    </delete>
</mapper>

src\main\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">
<!--dtd是对xml配置标签与属性的约束-->
<configuration>
<!--    environments环境  开发环境,生产环境-->
    <environments default="development">
        <environment id="development">
            <!--    使用jdbc的事务管理  -->
            <transactionManager type="JDBC"/>
            <!--    dataSource Mybatis自带数据源连接池-->
            <dataSource type="POOLED">
                <!--    四大信息 -->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis01?characterEncoding=utf-8"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <!-- 配置多个映射文件-->
    <mappers>
     <mapper resource="UserMapper.xml"/>
    </mappers>
</configuration>

src\test\java\com\vission\pack01\Test01Myabatis.java

public class Test01Myabatis {
    @Test
    public void test01(){
//        》1 创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
//        》2 创建SqlSessionFactory对象
        InputStream inputStream = Test01Myabatis.class.getClassLoader().getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactory sessionFactory = sqlSessionFactoryBuilder.build(inputStream);//加载核心配置文件 参1 输入流
//        》3 加载SqlMapConfig.xml配置文件
//        》4 创建SqlSession对象
        SqlSession sqlSession = sessionFactory.openSession();
//        》5 执行SqlSession对象执行删除
        System.out.println(sqlSession);
        //delete from user where id = ?
        sqlSession.delete("com.vission.bean.User.deleteById",1);//执行删除 参1 是namespace.id 参2 参数值
//        》6 打印结果
//        》7 释放资源
        sqlSession.commit();//mybatis的session不会自动提交,必须手动提交
        sqlSession.close();
    }
}

在这里插入图片描述

封装 MySessionUtil

(1)静态代码块
(2)getSession方法
src\main\java\com\vission\util\MySessionUtils.java

//Session工具类
public class MySessionUtils {
    private static SqlSessionFactory sessionFactory;
    //static 静态代码,在类加载的时候执行一次,且只执行一次
    static{
//  》1 创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// 》2 创建SqlSessionFactory对象
        InputStream inputStream = MySessionUtils.class.getClassLoader().getResourceAsStream("SqlMapConfig.xml");
         sessionFactory = sqlSessionFactoryBuilder.build(inputStream);//加载核心配置文件 参1 输入流
//        》3 加载SqlMapConfig.xml配置文件
    }
    public static SqlSession getSession() {
//        》4 创建SqlSession对象
        SqlSession sqlSession = sessionFactory.openSession();
        return sqlSession;
    }
}
  • 测试类
    src\test\java\com\vission\pack01\Test02Myabatis.java
public class Test02Myabatis {
    @Test
    public void test01(){
        SqlSession sqlSession = MySessionUtils.getSession();
//        》5 执行SqlSession对象执行删除
        System.out.println(sqlSession);
         //delete from user where id = ?
        sqlSession.delete("com.vission.bean.User.deleteById",24);//执行删除 参1 是namespace.id 参2 参数值
//        》6 打印结果
//        》7 释放资源
        sqlSession.commit();//mybatis的session不会自动提交,必须手动提交
        sqlSession.close();
    }
}

getMapper 实现增删改查

动态代理-根据id查询

  1. 传统DAO需要接口,需要实现类

实现类需要sqlSession.selectOne(“getUserById”,id),传统dao的问题就是当xml中的id变动的时候,需要在实现类中去修改代码,当成很大的不方便。

SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSessionFactory().openSession();
User user =sqlSession.selectOne("getUserById",id);
sqlSession.close();
  1. 动态代理dao只要接口不再需要实现类
    只要保证xml中的id和接口的方法名一致,所以只要改接口的方法名和xml中的id名字对应就可以了,大大增加了代码的灵活性。耦合度低

动态代理dao开发规则

  • namespace必需是接口的全路径名
  • 接口的方法名必需与映射文件的sql id一致
  • 接口的输入参数必需与映射文件的parameterType类型一致
  • 接口的返回类型必须与映射文件的resultType类型一致
SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSessionFactory().openSession();
		UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
		User user = userMapper.getUserById(30);
		System.out.println(user);
		sqlSession.close();
  • 接口与类是实现关系
public interface MyDao{
	public void save();
}
//编写实现类文件
public class MyDaoClass implements MyDao{
	public void save(){
		System.out.println("Hello");
		//sql
		//jdbc
	}
}
  • 动态代理生成实现类
    在这里插入图片描述
    src\main\java\com\vission\dao\UserDao.java
//com.vission.dao.UserDao.findById
public interface UserDao {
    public User findById(int id);
}

src\main\resources\com\vission\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">
<!--
使用代理以后 当前的映射文件要与接口同名,并且放在同一个位置
使用代理以后 namespace要求写接口的全类名 包名+类名=全类名
UserDao-->
<mapper namespace="com.vission.dao.UserDao">
    <!-- 使用代理以后id必须是方法名-->
    <select id="findById" parameterType="int" resultType="com.wzx.bean.User">
        select * from user where id =#{id};
    </select>

</mapper>

src\test\java\com\vission\pack02\Test01Proxy.java

public class Test01Proxy {
    @Test
    public void test01(){
        SqlSession sqlSession = MySessionUtils.getSession();

        //select * from user where id =1;
        UserDao dao = sqlSession.getMapper(UserDao.class);//内部就使用你编写接口来生成代理对象
        //代理对象的方法内部 查询sql,并且执行jdbc代码
        User user = dao.findById(1);
        System.out.println(user);
        //定义接口
        sqlSession.close();
    }

}

src\main\resources\SqlMapConfig.xml

<!-- 配置多个映射文件-->
    <mappers>
         <mapper resource="UserMapper.xml"/>
         <mapper resource="com/vission/dao/UserDao.xml"/> 
         <--!> 
    </mappers>

根据用户名模糊查询

(1)定义接口中的方法
(2)语句
(3)配置
(4)通过session.getMapper()返回的对象不是实现类对象

 @Test
    public void test02(){
        SqlSession sqlSession = MySessionUtils.getSession();

        //返回的是实现接口的实现类对象
        UserDao dao = sqlSession.getMapper(UserDao.class);

        //搜索名字
        List<User>list=dao.findByKeyWord("张%");
        System.out.println(list);
        //定义接口
        sqlSession.close();
    }

UserDao .java

//com.wzx.dao.UserDao.findById
public interface UserDao {
    public User findById(int id);
    //select * from user where username like '张%'
    List<User> findByKeyWord(String s);
}

UserDao .xml

<select id="findByKeyWord" parameterType="string" resultType="com.wzx.bean.User">
        select * from user where username like #{keyword}
    </select>

删除数据
(1)定义接口中的方法
(2)语句
(3)配置
(4)通过session.getMapper()返回的对象不是实现类对象

@Test
    public void test03(){
        SqlSession sqlSession = MySessionUtils.getSession();

        //返回的是实现接口的实现类对象
        UserDao dao = sqlSession.getMapper(UserDao.class);

        //删除
        dao.deleteById(16);
        //
        sqlSession.commit();
        sqlSession.close();
    }
//com.wzx.dao.UserDao.findById
public interface UserDao {
  
    //delete from user where id = 16;
    void deleteById(int id);
}
 <delete id="deleteById" parameterType="int">
        delete from user where id = #{id};
    </delete>

插入数据

  1. 定义接口中的方法
  2. 语句
  3. 配置
  4. 通过session.getMapper()返回的对象不是实现类对象
@Test
    public void test04(){
        SqlSession sqlSession = MySessionUtils.getSession();

        //返回的是实现接口的实现类对象
        UserDao dao = sqlSession.getMapper(UserDao.class);

        User user = new User();
        user.setId(100);
        user.setUsername("jackjhone");
        user.setAddress("北京");
        user.setBirthday(new Date());
        dao.saveUser(user);
        //
        sqlSession.commit();
        sqlSession.close();
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值