第三十四天:Mybatis框架基础+快速入门配置文件

0. 相关概念

0.1 框架和工具类

  • 工具类
    • 对程序中一小段代码的封装。项目中大多数代码还是需要我们写。
  • 框架
    • 通俗理解框架
    • 可以看做一个半成品的软件/项目。使用框架开发项目,项目中半数以上代码就不需要 我们编写了。
    • 我们一般需要配置(大多数框架都是重配置轻编码的)+少量编码,就可完成项目中的需求。
    • 框架的目的 就是为了简化编码eg:Mybatis
      我们在学习完Mybatis之后,dao层会更简单。你只需要写一个dao接口,然后写一个SQL语句,dao层就已经写完了。
  • 学习步骤
    • 这个框架能干什么?
    • 导包+配置
    • 框架少量的API,少量编码

0.2 ORM

  • Object Relational Mapping 对象关系映射的思想

  • 对象 - Java中的对象 关系-关系型数据库中表的记录 映射 - 一对一关联起来

  • java项目中的每一个实体类,对应数据库中的一个
    java类中的属性,对应数据库表中的字段
    java类中的一个实体对象,对应一个数据表中的一条记录

  • 全自动ORM框架:hibernate

    通过操作实体对象,就可以完成对数据库表中记录的操作。复杂业务性能低下,不可定制,学习成本高。

  • 半自动的ORM框架:Mybatis,ibatis

    基于ORM,但是SQL语句需要我们自己编写。自己优化SQL,可定制性强,效率高。

0.3 Mybatis&原生JDBC

  • 原生jdbc

    • 注册驱动,设置连接参数
    • 获取连接
    • 获取执行对象
    • 设置SQL参数并执行SQL语句
    • 封装结果集并封装成实体对象
    • 释放资源

    相同的内容已经抽取到工具类中(上述删除线标识的步骤)

    模板化(步骤不变,部分步骤相同,上述加粗的内容)的操作,也是可以抽取封装的。

    但是相同的步骤中又有不同的地方,不同的地方如果也要实现解耦,需要通过配置来实现

  • Mybatis解决方案

    • 连接复用:使用数据库连接池初始化并管理连接
    • 解耦:将SQL语句和设置到SQL中的参数抽取到xml配置文件中
    • 自动封装:通过反射内省等技术,实现查询结果集字段实体属性自动映射并赋值
  • Mybatis框架抽取后的样子

    第三十四天:Mybatis框架基础+快速入门配置文件_第1张图片

  • Mybatis简介

    • 是一个数据持久层(DAO)框架,封装共性内容让使用者只关注SQL本身。结合了ORM思想,是一个ORM半自动的框架。
    • 使用Mybatis之后,我们只需要定义一个Dao层接口+存储SQL的配置文件(Mybatis映射配置文件),就可以完成Dao层内容。

1. Mybatis快速入门

1.1 Mybatis快速入门步骤

  • 导入Jar包

    • mybatis-3.5.3.jar
    • mysql-connector-java-5.1.37-bin.jar
    • junit-4.12.jar
  • 编写Mybatis核心配置文件:mybatis-config.xml

    • 连接数据库四要素
    • 标签中映射文件路径不是./ 建议复制,不要手敲
  • 编写POJO类和Dao层接口,初始化数据库表及数据

  • 编写映射文件:StudentDao.xml,在映射文件中编写SQL语句

  • 测试

  • 小经验

    • 直接生成mybatis的两类xml文件

    • Mybatis映射配置文件和接口之间相互跳转

核心配置文件



<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql:///web17_mybatis01"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            dataSource>
        environment>
    environments>


    
    <mappers>
        <mapper resource="dao/StudentDao.xml"/>
    mappers>
configuration>

映射配置文件






<mapper namespace=".dao.StudentDao">
    
        <select id="findById" resultType="domain.Student">
            select * from student where  id = 1;
        select>
mapper>

接口StudentDao.java

public interface StudentDao {
    Student findById();
}

测试类MybatisTest.ava

public class MybatisTest {

    @Test
    public void test01() throws IOException {
        // 配置文件位置
        String resource = "mybatis-config.xml";
        // 加载配置文件
        InputStream inputStream = Resources.getResourceAsStream(resource);

        // 通过构建的方式创建了SqlSessionFactory对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        // 获取session对象
        // SqlSession session = sqlSessionFactory.openSession();

        // JDK7 新特性  try-with-resources
        /**
         * try(创建各种连接对象){
         *  使用连接
         * }
         * 不需要自己关闭连接,这个结构会在执行完代码之后自动帮你关闭
         */
        // 获取session对象
        try (SqlSession session = sqlSessionFactory.openSession()) {
            // 通过连接对象,获取dao层实现类对象
            StudentDao studentDao = session.getMapper(StudentDao.class);

            // 调用dao层实现类对象中的方法
            Student student = studentDao.findById();
            System.out.println("student = " + student);

            // 提示让删除,因为已经关闭过了
            // session.close();
        }
    }
}

2. API

2.1 Resources

读取配置的文件的工具类,底层使用的是classLoad对象.getResourceAsStream

InputStream getResourceAsStream(“配置文件相对于类路径的相对路径”);

2.2 SqlSessionFactoryBuilder

获取SqlSessionFactory工厂对象的功能类。

// 通过构建的方式构建了一个SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

//xxxBuilder.build()

2.3 SqlSessionFactory

org.apache.ibatis.session.SqlSessionFactory:获取 SqlSession 对象的工厂接口。

SqlSession openSession() 获取SqlSession对象,并开启事务,需要手动提交事务

SqlSession openSession(boolean autoCommit) 获取SqlSession对象,true表示自动提交

2.4SqlSession

org.apache.ibatis.session.SqlSession:sql会话对象接口。用于执行SQL管理事务接口代理

void commit() 提交事务
void rollback() 回滚事务
T getMapper(Class cls) 获取指定接口的代理实现类对象
void close() 释放资源

3. 映射配置文件

3.1 基本讲解





<mapper namespace="dao.StudentDao">
    
    
    <select id="findById"  resultType="domain.Student">
        select  * from student where  id = 2
    select>

mapper>

参数相关

编码完成如下需求:

// 需求1:查询id为1的学生(强制要求)
// 需求2:创建一个Student对象并保存到数据库(参数和成员变量名保持一致)(成功了吗?)
// 需求3:根据学生姓名和年龄查询用户,传两个参数(多个参数怎么办?)
// 需求4:完成需求3,传一个参数。

映射配置文件StudentDao.xml保证这个文件的名字和接口名完全一致,且在同一个包下。



<mapper namespace="dao.StudentDao">

    

    

    

    
    
    <insert id="save">
        insert  into student values(#{id},#{firstName},#{age})
    insert>


    
    <select id="findByNameAndAge" resultType="domain.Student">
        select * from  student where  name = #{namex} and age = #{agex}
    select>


    
    <select id="findByCondition"
            resultType="domain.Student">
        select  * from  student where name = #{name} and age = #{age}
    select>


    

    
    
    <select id="findByConditionMap" resultType="domain.Student">
        select * from student where name = #{namex} and age = #{agex}
    select>

mapper>

核心配置文件


<mappers>
    <mapper resource="dao/StudentDao.xml"/>
mappers>

Dao层接口StudentDao

public interface StudentDao {
    @Select("select * from student where  id = 1")
    Student findById();

    // 需求1:查询id为1的学生(强制要求)
    Student findById2(@Param("id") Integer id);

    // 需求2:创建一个Student对象并保存到数据库
    void save(Student stu);

    // 需求3:根据学生姓名和年龄查询用户,传两个参数(多个参数怎么办?)
    List<Student> findByNameAndAge(@Param("name") String name, @Param("agex") Integer age);

    // 需求4:完成需求3,传一个参数。
    // 4.1 把两个参数封装成一个实体对象
    // 如果把多个参数封装到一个实体对象中,参数类型有局限性,不能是两个一样的条件做范围查询
    List<Student> findByStudent(Student stu);

    // 4.2 把两个参数封装到Map集合中
    List<Student> findByMap(Map<String,Object> map);
}

测试类

/**
 * @Author Vsunks.v
 * @Date 2020/8/7 11:19
 * @Description:
 */
public class MybatisDemo {
    public static void main(String[] args) throws Exception {

        // 指定核心配置文件
        String resource = "mybatis-config.xml";
        // 把核心配置文件加载成流  Resources为我们提供的方便读取配置文件的工具类
        InputStream inputStream = Resources.getResourceAsStream(resource);

        // 通过构建的方式构建了一个SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        // SqlSession 就相当于我们之前的 Connection
        // JDK7新特性  try-with-resource
        // 需要释放资源的动作,自动释放在try()中开启的一些流、会话......
        try (SqlSession session = sqlSessionFactory.openSession(true)) {

            // getMapper  getDao   获取一个指定接口的实现类对象
            // 底层是动态代理
            // 动态代理可以增强有接口的类、接口(增强接口,就是现实接口)
            // 就相当于我们自己new StudentDaoImpl();
            // 这个StudentDaoImpl是Mybatis通过动态代理帮我们自动生成并且赋值给了studentDao
            StudentDao studentDao = session.getMapper(StudentDao.class);

            /*List students = studentDao.findAll();
            System.out.println("students = " + students);*/


            // 测试根据id查询
            /*Student student = studentDao.findById(1);
            System.out.println("student = " + student);*/

            // 测试添加学生
            //studentDao.saveStudent(new Student(null,"凤姐",20));

            // 根据名称和年龄查询用户,参数是两个基本类型
            //List students = studentDao.findByNameAndAge("美女", 20);
            //System.out.println("students = " + students);

            // 根据名称和年龄查询用户,参数是一个student对象
            //List students = studentDao.findByUser(new Student(null, "凤姐", 20));
            //System.out.println("students = " + students);

            // 根据名称和年龄查询用户,参数是一个map集合

            HashMap<String, Object> map = new HashMap<>();
            map.put("name", "王二蛋");
            map.put("age", 20);

            System.out.println("studentDao.findByMap(map) = " + studentDao.findByMap(map));


            // 手动提交
            //session.commit();

            // session.close();
        }

    }
}

4. 核心配置文件

4.0 注意

核心配置文件中各种配置的顺序,需要符合官方要求,否则(运行时)会报错。错误提示如下:


4.1 properties(重要)

引入外部的properties文件,一般用作引入数据库链接参数的配置。

核心配置文件




<configuration>
    
    <properties resource="jdbc.properties"/>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <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="dao/StudentDao.xml"/>
    mappers>
configuration>

jdbc.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://192.168.115.130:3306/db1
# 数据库用户名可以是username之外任意名称
jdbc.username=root
jdbc.password=root

4.2 Settings(重要)


<settings>
    
    <setting name="mapUnderscoreToCamelCase" value="true"/>
    
    <setting name="logImpl" value="LOG4J"/>
settings>

4.3 TypeAliases(了解)


<typeAliases>
    
    

    
    <package name="domain"/>

typeAliases>

起别名后,在映射配置文件中类型处可以直接使用别名(不区分大小写)

<select id="findByMap" resultType="Student">
       select * from student where first_username=#{name}
       and
       age=#{age}
select>

系统为常见的类型起好了别名,详见官方文档

别名 映射的类型
_byte byte
_long long
_short short
_int int
_integer int
_double double
_float float
_boolean boolean
string String
byte Byte
long Long
short Short
int Integer
integer Integer
double Double
float Float
boolean Boolean
date Date
decimal BigDecimal
bigdecimal BigDecimal
object Object
map Map
hashmap HashMap
list List
arraylist ArrayList
collection Collection
iterator Iterator

整体使用频率不高,因为插件会自动生成,而且写全的更好理解。

4.4 Environments(了解)

会配置连接四要素即可

<environments default="dev">
    <environment id="dev">
        <transactionManager type="JDBC"/>
        <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>
    <environment id="test">
        <transactionManager type="JDBC"/>
        <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>

4.5 Mappers(重点)


<mappers>
    
    <package name="dao"/>

    
    
    

    
    

    
    
mappers>

5. 经验分享

5.1 生成Mybatis配置文件

本质是新建了一个文件模板,按照下面的方式新建两个模板即可(Mybatis-configMybatis-Mapper

第三十四天:Mybatis框架基础+快速入门配置文件_第2张图片

5.2 接口映射配置文件跳转

使用一个插件free-idea-mybatis

这个插件是个zip包,不要解压,直接安装即可。

已知bug:

​ 多个模块之间有相同内容会提示/跳转错误,卸载其他模块即可。

5.3 ${}和#{}区别(面试题)

#{} MyBatis 会创建 PreparedStatement 参数占位符,并通过占位符安全地设置参数(就像使用 ? 一样)。 这样做更安全,更迅速,通常也是首选做法。

${} 会做字符串的拼接,把${参数名}中参数名对应的值拼接进SQL语句,可能会有SQL注入的风险,效率更低。但是,如果你需要在SQL语句中直接插入一个不转义的字符串,可以使用这种方式。一般情况下会把表名或者字段名通过这方方式传递到SQL语句中,比方说 ORDER BY后面的列名。

5.4 MybatisUtils工具类抽取

/**
 * mybatis工具类,可以实现的功能
 * 1. 自动维护SQLSessionFactory
 * 2. 获取SQLSession
 * 3. 获取dao接口代理对象
 *
 * @Author Vsunks.v
 * @Date 2020/12/4 16:30
 * @Blog blog.sunxiaowei.net
 * @Description:
 */
public class MybatisUtils {

    // 私有构造
    private MybatisUtils() {
    }

    // 维护一个SQLSessionFactory对象
    private static SqlSessionFactory ssf;

    // 静态代码块初始化SQLSessionFactory
    static {
        // 加载配置文件
        String resource = "mybatis-config.xml";

        try {
            // 获取流
            InputStream is = Resources.getResourceAsStream(resource);
            // 通过builder build一个SqlSessionFactory
            ssf = new SqlSessionFactoryBuilder().build(is);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //2. 获取SQLSession
    public static SqlSession getSqlSession() {
        return ssf.openSession(true);
    }


    // 3. 获取dao接口代理对象
    public static <T> T getMapper(Class<T> tClass){
        return getSqlSession().getMapper(tClass);
    }
}

tisUtils {

// 私有构造
private MybatisUtils() {
}

// 维护一个SQLSessionFactory对象
private static SqlSessionFactory ssf;

// 静态代码块初始化SQLSessionFactory
static {
    // 加载配置文件
    String resource = "mybatis-config.xml";

    try {
        // 获取流
        InputStream is = Resources.getResourceAsStream(resource);
        // 通过builder build一个SqlSessionFactory
        ssf = new SqlSessionFactoryBuilder().build(is);

    } catch (IOException e) {
        e.printStackTrace();
    }
}

//2. 获取SQLSession
public static SqlSession getSqlSession() {
    return ssf.openSession(true);
}


// 3. 获取dao接口代理对象
public static  T getMapper(Class tClass){
    return getSqlSession().getMapper(tClass);
}

}


你可能感兴趣的:(#,5,mysql,mybatis,数据库,mysql,java)