mybatis基础

1,mybatis;和数据库进行交互;持久化层框架(sql映射框架);

 

  1),从原始的JDBC----dbutils(QueryRunner)---JdbcTemplate---xxx;(纯手工)

  称为工具;

    * 工具:一些功能的简单封装

    * 框架:某些领域的整体解决方案;缓存,考虑异常处理问题,考虑部分字段映射问题。不用原生jdbc

    缺点: 1)麻烦。

           2)sql是硬编码;耦合(数据库层和java编码层)

  2),hibernate (orm框架)object relation mapping 对象关系映射。(全自动)

  比如创建个bean 叫 Employee

  @Table("t_employee")

  class Employee{

    private Integer empId;

    private String empName;

  }

  然后去数据库建一个表t_employee,一 一对应字段。实现自动化操作,甚至不需要写sql语句。

    缺点:1,没办法自己编写sql,定制sql。

       2,hql。

       3,全映射框架;做部分字段映射很难。

  

mybatis 

1,mybatis将重要的步骤抽取出来可以人工定制,其他步骤自动化;

2,重要步骤都是写在配置文件中(好维护);

3,完全解决数据库的优化问题。

4,mybatis底层就是对原生jdbc的一个简单封装;

5,既将java编码与sql抽取了出来,还不会失去自动化功能;半自动的持久层框架。

 

1)环境搭建

  1),创建一个java工程;

  2),创建测试库,测试表,以及封装数据的Javabean,和操作数据库的dao接口

      创建表:自己用工具创建

      创建javabean:Employee ( 封装表的数据 )。

      创建一个dao接口,用来操作数据库。

  3),开始使用mybatis

      1)导包

        

      2)写配置(可以去官方文档,入门级,看如何配置xml文件)

        1,第一个配置文件;(称为mybatis的全局配置文件,指导mybatis如何正确运行,比如连接向哪个数据库)

        2,第二个配置文件;(编写每一个方法都如何向数据库发送sql语句,如何执行。。。相当于接口实现)

          1,将mapper的namespace属性改为接口全类名。

          2,配置细节

          3,写dao接口的实现文件,mybatis默认是不知道的,需要在全局配置文件中注册;

    <!--引入我们自己编写的每一个接口的实现文件-->
    <mappers>
    <mapper resource="EmployeeDao.xml"/>
    </mappers>

      3)测试

        1,根据全局配置文件先创建一个。

        String resource = "conf/mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory Factory = new SqlSessionFactoryBuilder().build(inputStream);

 

        2,SqlSessionFactory 中获取 SqlSession 对象操作数据库即可。

        //2,获取和数据库的一次会话;getConnection();
        SqlSession openSession = Factory.openSession();

        //3,使用SqlSession 操作数据库,获取到dao接口的实现。
        EmployeeDao mapper = openSession.getMapper(EmployeeDao.class);

        Employee empById = mapper.getEmpById(1);
        System.out.println(empById);

 

--------------------------下面是一套crud的具体代码------------------------

 

 

 配置文件 和 控制层 的写法都可以在官方文档入门里找到。

package com.atguigu.bean;

/**
 * Created by Zhuxiang on 2020/6/7.
 */
public class Employee {
    private Integer id;
    private String empName;
    private String email;
    private Integer gender;

    public Integer getId() {
        return id;
    }

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

    public String getEmpName() {
        return empName;
    }

    public void setEmpName(String empName) {
        this.empName = empName;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Integer getGender() {
        return gender;
    }

    public void setGender(Integer gender) {
        this.gender = gender;
    }

    public Employee(Integer id, String empName, String email, Integer gender) {
        this.id = id;
        this.empName = empName;
        this.email = email;
        this.gender = gender;
    }

    public Employee() {
    }

    public Employee(String empName, String email, Integer gender) {
        this.empName = empName;
        this.email = email;
        this.gender = gender;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "id=" + id +
                ", empName=" + empName +
                ", email=" + email +
                ", gender=" + gender +
                '}';
    }
}
Employee
package com.atguigu.dao;

import com.atguigu.bean.Employee;

/**
 * Created by Zhuxiang on 2020/6/7.
 */
public interface EmployeeDao {
    public Employee getEmpById(Integer i);
    public int addEmp(Employee emp);
    public boolean deleteEmp(Integer i);
    public int updateEmp(Employee emp);
}
EmployeeDao
package com.atguigu.test;

import com.atguigu.bean.Employee;
import com.atguigu.dao.EmployeeDao;
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.Before;
import org.junit.Test;

import java.io.InputStream;

/**
 * Created by Zhuxiang on 2020/6/7.
 */
public class MyBatisTest {
    @Test
    public void test() throws Exception{
        //看文档,入门,复制代码。
        //1.根据全局配置文件创建出一个SQLSessionFactory
        //SQLSessionFactory,是SQLSession工厂,复制创建SQLSession对象;
        //SQLSession:sql会话(代表与数据库的一次会话);
        String resource = "conf/mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory Factory = new SqlSessionFactoryBuilder().build(inputStream);

        //2,获取和数据库的一次会话;getConnection();
        SqlSession openSession = Factory.openSession();

        //3,使用SqlSession 操作数据库,获取到dao接口的实现(映射器)。
        EmployeeDao mapper = openSession.getMapper(EmployeeDao.class);

        Employee empById = mapper.getEmpById(1);
        System.out.println(empById);
    }
    //---------------增删改查--------------------
    SqlSessionFactory Factory;
    //junit的before
    @Before
    public void initSqlSessionFactory() throws Exception{
        String resource = "conf/mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
         Factory = new SqlSessionFactoryBuilder().build(inputStream);
    }
    @Test
    public void test2 ()throws Exception{
        SqlSession openSession = Factory.openSession();
        EmployeeDao mapper = openSession.getMapper(EmployeeDao.class);
        try {
            Employee empById = mapper.getEmpById(1);
            System.out.println(empById);
        } finally {
            openSession.close();
        }
    }
    @Test
    public void test3add (){
        //方法二:自动提交,参数给个true
        SqlSession openSession = Factory.openSession(true);
        EmployeeDao mapper = openSession.getMapper(EmployeeDao.class);
        try {
            Employee zx = new Employee("zx", "@qq.123", 0);
            int i = mapper.addEmp(zx);
            System.out.println(i);
        } finally {
            //方法一:手动提交
            //openSession.commit();
            openSession.close();
        }
    }
    @Test
    public void test3del (){
        SqlSession openSession = Factory.openSession(true);
        EmployeeDao mapper = openSession.getMapper(EmployeeDao.class);
        try {
            boolean i = mapper.deleteEmp(2);
            System.out.println(i);
        } finally {
            openSession.close();
        }
    }
    @Test
    public void test3update (){
        SqlSession openSession = Factory.openSession(true);
        EmployeeDao mapper = openSession.getMapper(EmployeeDao.class);
        try {
            Employee emp = new Employee();
            emp.setEmpName("sss");
            emp.setId(1);
            int i = mapper.updateEmp(emp);
            System.out.println(i);
        } finally {
            openSession.close();
        }
    }
}
MyBatisTest
<?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 名称空间:写接口的全类名,相当于告诉 mybatis 这个配置文件是实现哪个接口的-->
<mapper namespace="com.atguigu.dao.EmployeeDao">
    <!--select 用来定义一个查询操作
        id 方法名,相当于这个配置是对于某个方法的实现
        resultType 指定方法运行后的返回值类型(查询操作必须指定的)
        #{属性名} 代表取出传递过来的某个参数的值 -->
    <select id="getEmpById" resultType="com.atguigu.bean.Employee">
    <!--sql语句不要写分号-->
    select * from t_employee where id=#{id}
    </select>

    <!--增删改不用写返回值类型,增删改是返回影响多少行-->
    <!--mybatis自动判断,如果是数字(int,long),如果是boolean(影响0行自动封装false,否则true)-->
    <update id="updateEmp">
        update t_employee set empname=#{empName} where id=#{id}
    </update>
    <delete id="deleteEmp">
        delete from t_employee where id=#{id}
    </delete>
    <insert id="addEmp">
        insert into t_employee(empName,email,gender) values (#{empName},#{email},#{gender})
    </insert>
</mapper>
EmployeeDao.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="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <!--配置连接池-->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/spring1"/>
                <property name="username" value="root"/>
                <property name="password" value=""/>
            </dataSource>
        </environment>
    </environments>
    <!--引入我们自己编写的每一个接口的实现文件-->
    <mappers>
        <mapper resource="conf/EmployeeDao.xml"/>
    </mappers>
</configuration>
mybatis-config.xml

 -------------------------------官方文档里看完入门,该看配置了------------------------------------

  1,全局配置文件:mybatis-config.xml;指导mybatis正确运行的一些全局设置;

  2,sql映射文件:EmployeeDao.xml;相当于是对dao接口的一个实现描述。

 

  • configuration 配置

    • properties 属性

    • settings 设置

    • typeAliases 类型命名(起别名,不太用)

    • typeHandlers 类型处理器(不用)

    • objectFactory 对象工厂(不用)

    • plugins 插件(用的不多)

    • environments 环境databaseIdProvider 数据库厂商标识( 不用 )

      • environment 环境变量
        • transactionManager 事务管理器
        • dataSource 数据源
    • mappers 映射器

  去官方文档看,有例子。

<?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>
    <!--引入外部配置文件-->

    <!--1.properties
        resource:从类路径下开始引用
        url:引用磁盘路径或者网络路径的资源
    -->
    <properties resource="conf/dbconfig.properties"></properties>

    <!--2.settings 这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。下表描述了设置中各项的意图、默认值等。

     mapUnderscoreToCamelCase  是否开启自动驼峰命名规则(camel case)映射,
     即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射。

     说得简单点就是,根据这个规则,数据库列名里 _ 后面的第一个字母,在javabean里是大写,然后可以匹配。
     如: javabean里属性名叫:loginAccount   数据库列名为:login_account 可以匹配-->
    <!--name:配置项的key   value:配置项的值 -->
    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
    <!--3.(不推荐用!!!!知道就行)类型别名,为常用的类型(如javabean)起别名-->
    <typeAliases>
        <!--typeAlias:就是为一个javabean起别名,别名默认就是类名(不区分大小写),配置文件中就可以用别名了
            alias:指定一个别名。-->
<!--        <typeAlias type="com.atguigu.bean.Employee" alias="Employee"></typeAlias>-->
        <!--批量起别名,name="" 指定包名,默认别名就是类名.到javabean里用注解自定义别名-->
<!--        <package name="com.atguigu.bean"></package>-->
    </typeAliases>
<!--4.typeHandlers。(不用!!!)无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,
    还是从结果集中取出一个值时, 都会用类型处理器将获取的值以合适的方式转换成
    Java 类型。-->
    <!--5,插件是mybatis中的一个强大功能?(不用)-->
    <!--environments 配置环境们
        environment:配置一个具体的环境,都需要一个事务管理器和一个数据源。
        transactionManager:
        后来数据源和事务管理都是spring来做。
    -->
    <!--default="" 默认使用哪个环境。-->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <!--配置连接池-->
            <!--用${}取值-->
            <dataSource type="POOLED">
                <property name="driver" value="${driverclass}"/>
                <property name="url" value="${jdbcurl}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
    <!--6.(不用!)mybatis用来考虑数据库移植性的。比如从mysql移植到Oracle数据库-->
    <databaseIdProvider type="DB_VENDOR">
        <!--name="" ,数据库厂商标识 value 给这个标识起一个好用的名字-->
        <property name="MySQL" value="mysql"/>
        <property name="SQL Server" value="sqlserver"/>
        <property name="Oracle" value="oracle"/>
    </databaseIdProvider>
    <!--引入我们自己编写的每一个接口的实现文件-->

    <mappers>
    <!--7.注册映射文件
    7.1 resource:从类路径下开始引用(推荐)
        url:引用磁盘路径或者网络路径的资源
        class:直接引用接口的全类名
        (需要将xml文件放在dao接口同目录下,而且文件名和接口名一致)
-->
        <mapper resource="conf/EmployeeDao.xml"/>
    <!--7.2 批量注册 name="", dao所在的包名
        (需要将xml文件放在dao接口同目录下,而且文件名和接口名一致)-->
<!--        <package name="com.atguigu.dao"/>-->
    </mappers>
</configuration>
mybatis-config.xml

 objectFactory 对象工厂 配置 dao.xml 文件

<!--数据库切换,如果能精确匹配就精确,不能就用模糊的-->
<!-- <select id="getEmpById" resultType="com.atguigu.bean.Employee" databaseId="oracle">-->
<!-- &lt;!&ndash;sql语句不要写分号&ndash;&gt;-->
<!-- select * from t_employee where id=#{id}-->
<!-- </select>-->

------------------------全局配置文件介绍完毕,现在介绍sql映射文件--------------------------------

 

 

 -----------------关于动态sql我们可以直接去mybatis官网上看,内容是一样的。--------------------

 ------------------------------------------缓存----------------------------------------------

暂时的储存一些数据,加快系统的查询速度。

cpu:会把数据先放在内存条里,这就算缓存。

  cpu还有自己的缓存区,一级缓存,二级缓存;

数据库交互:

  比如去数据库查一个类;mybatis缓存机制;存在map里;能保存查询出的一些数据。

  一级缓存:线程级别的缓存;本地缓存;sqlsession级别的缓存。(sqlsession就是开启一次连接)

  二级缓存:全局范围的缓存;除过当前线程,或者说,sqlsession能用外其他也可以使用。

 

一级缓存:mybatis:

  默认存在。证明:连续写查询同一个类2次。1,日志中只打印一次sql语句。2,(第一次查询结果==第二次查询结果)结果为true,证明内存一致。

  1)只要之前查询过的数据,mybatis就会保存在一个缓存中(map);下次获取直接从缓存中拿。

  一级缓存失效的情况:

  1)因为是sqlsession级别的缓存,所以不同的sqlsession,使用不同的一级缓存。

     只有在同一个sqlsession期间查询到的数据会保存在这个sqlsession的缓存中。

  2)同一个sqlsession期间,同一个方法,但是不同参数,会发新的sql。

  3)同一个sqlsession期间,执行上任何一次增删改操作,增删改操作会把之前的缓存清空。

  4)手动清空缓存。

 

二级缓存:

 

 

1,不会出现一级缓存和二级缓存中有同一个数据。

    二级缓存中:一级缓存关闭了就有了;

    一级缓存中:二级缓存中没有此数据,就会看一级缓存,一级缓存也没有,就去查数据库;

          查询后的结果放在一级缓存里。

2,优先查看顺序,口诀:二——一——库。

 

 ------------------------整合第三方缓存------------------------

因为mybatis是专业做数据库的,他的缓存做的不太行,所以他给了接口和实现。用接口来整合第三方包,可以用专业的内存数据库。

比如:整合ehcache;ehcache是非常专业的java进程内的缓存框架。

 

3,(补充)在mapper.xml中配置使用cache标签。

  (补充)<cache-ref namespace="和别的dao,共用一块缓存,填dao路径 "/>

 建议:ehcache.xml要放在类路径的根目录下。

 

posted @ 2020-06-07 13:57  天才淇露洛  阅读(111)  评论(0)    收藏  举报