Mybatis框架学习笔记

概述

可重用设计,软件开发一套解方案,封装了很多细节这里插入图片描述
Mybatis封装了jdbc,使开发者只需要关注SQLyujv本身。
使用ORM(Object Relational Mapping 对象关系映射)思想,简单来说就是将数据库的数据表及其中的列名和实体类及实体类的属性对应起来。这样,我们就能通过操作实体类来操作数据表。(实体类的属性名必须和数据表的列名一致)
在这里插入图片描述

三层架构

1、数据访问层(持久层):主要是对非原始数据(数据库或者文本文件等存放数据的形式)的操作层,而不是指原始数据,也就是说,是对数据库的操作,而不是数据,具体为业务逻辑层或表示层提供数据服务。
(Mybatic)

2、业务逻辑层(业务层):主要是针对具体的问题的操作,也可以理解成对数据层的操作,对数据业务逻辑处理,如果说数据层是积木,那逻辑层就是对这些积木的搭建。
(spring)

3、界面层(表现层):主要表示WEB方式,也可以表示成WINFORM方式,WEB方式也可以表现成:aspx,如果逻辑层相当强大和完善,无论表现层如何定义和更改,逻辑层都能完善地提供服务。
(springmvc (MVC: model view controller)模块 视图 控制)

在这里插入图片描述

关于事务泄露

在这里插入图片描述

入门案例

配置mybatis

  1. 添加依赖
    在这里插入图片描述

  2. 在resources中添加配置文件SqlMapConfig(名字随意,一般为这个)。设置约束、配置环境、指定映射配置文件(每个dao独立的配置文件)的路径。在这里插入图片描述

  3. 创建映射配置文件,文件位置与dao文件需要对应。在这里插入图片描述

  4. 映射配置文件mapper的标签namespace属性的取值必须为dao接口的全限定名

  5. 映射配置文件的操作配置(select)中的id属性取值必须为dao接口中对应的方法名。在这里插入图片描述

测试

//1.获取配置参数
        InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.创建SqlSessionFactory工厂对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(in);
        //3.通过工厂对象创建SqlSession对象
        SqlSession sqlSession = factory.openSession();
        //4.使用SqlSession对象创建dao代理对象
        IUserDao dao = sqlSession.getMapper(IUserDao.class);
        //5.使用dao代理对象执行方法
        List<User> users = dao.findAll();
        //6.释放资源
        sqlSession.close();
        in.close();

自定义Mybatis框架

mabitis在使用dao方式实现查询时做什me事呢?

  1. 创建代理对
  2. 在代理对象中调用selectList
  • 简单的查询需要如下信息,将他们封装成一个mapper。
    在这里插入图片描述
  • 因为每一个方法都有一个mapper。为了区分将所有mapper放入一个map集合中。

在这里插入图片描述

  • 如何创建代理对象
    在这里插入图片描述

创建所需类

在这里插入图片描述
依次创建
在这里插入图片描述
删除mabatis依赖后配置文件中会出现如下错误,将报错部分约束删除即可
在这里插入图片描述
解析xml的工具类
需要Configuration类在这里插入图片描述
通过源码可知创建该类需要包含参数driver、url、username、password、mappers
在这里插入图片描述
需要注意的是在构造器中给mappers赋值采用的是putall方法,此时map对象必须new出来,否则会报错

在这里插入图片描述

mapper类需要创建用于存储数据库语句sqlString和返回结果的实体类resultType在这里插入图片描述
回到SqlSessionFactoryBuilder编写build方法

public SqlSessionFactory build(InputStream config){
        Configuration configuration = XMLConfigBuilder.loadConfiguration(config);

        return new DefaultSqlSessionFactory(configuration);
    }

创建DefaultSqlSessionFactory类实SqlSessionFactory接口

public class DefaultSqlSessionFactory implements SqlSessionFactory {
    //工厂需要操作数据库,需要有数据库的连接等信息
    private Configuration cfg;

    public DefaultSqlSessionFactory(Configuration cfg) {
        this.cfg = cfg;
    }

    public SqlSession openSession() {
        return new DefaultSqlSession();
    }
}

创建DefaultSqlSession类实SqlSession接口用于创建代理对象

public class DefaultSqlSession implements SqlSession {

    /**
     * 获取代理对象
     * @param daoInterfaceClass dao的接口字节码
     * @param <T>
     * @return
     */
    public <T> T getMapper(Class<T> daoInterfaceClass) {
        return null;
    }

    /**
     * 关闭资源
     */
    public void close() {

    }
}

编写getmapper方法创建代理对象
通过Proxy创建方法如下

Proxy.newProxyInstance(被代理对象的类加载器, 被代理对象实现的接口, 如何实现)
Proxy.newProxyInstance(daoInterfaceClass.getClassLoader(),
                    new Class[]{daoInterfaceClass},
                    new MapperProxy(cfg.getMappers(), DataSourceUtil.getConnection(cfg)));

在如何实现处,需要创建一个实体类MapperProxy实现InvocationHandle接口用于编写代理对象的增强方法

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //获取方法名
        String name = method.getName();
        //获取方法所在类的名称
        String className = method.getDeclaringClass().getName();
        //组合key值
        String key = className + "." + name;
        //通过key值获取mapper
        Mapper mapper = map.get(key);

        if(mapper == null){
            throw new IllegalArgumentException("传入的参数有误");
        }

        //调用工具类查询所有
        return new Executor().selectList(mapper,conn);
    }

反向生成工具

官网http://mybatis.org/generator/
创建配置文件generatorConfig.xml
在这里插入图片描述
添加依赖在这里插入图片描述
在pom中添加插件在这里插入图片描述
在这里插入图片描述
忽略注释
在这里插入图片描述
修改配置文件
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
运行
在这里插入图片描述

使用注解方式

1.修改配置文件SqlMapConfig.xml
在这里插入图片描述
2.在接口中的方法上添加select注解
在这里插入图片描述
3.创建注解类
在这里插入图片描述
注解方式解析:在这里插入图片描述
在这里插入图片描述

mybatis中的crud(通过代理方式)

  • 增加用户

IUserDao.xml配置

<!--保存用户 #{}为mybatis通过反射获取参数,内容为User中get后的名字-->
    <insert id="saveUser" parameterType="com.jc.domain.User">
        insert into user (username,address,sex,birthday) 
        values(#{username},#{address},#{sex},#{birthday});
    </insert>

注意保存删除等操作需要手动提交事务
在这里插入图片描述
在这里插入图片描述

  • 更新和删除
    删除
    在这里插入图片描述
    更新
   <!--修改用户-->
    <update id="updateUser" parameterType="com.jc.domain.User">
        update user set username=#{username},sex=#{sex},birthday=#{birthday},address=#{address} where id=#{id};
    </update>
  • 模糊查询
    在这里插入图片描述
    在这里插入图片描述

在插入数据时,如何获取自增属性的值,如user的id

在配置插入操作时添加如下代码
![在这里插入图片描述](https://img-blog.csdnimg.cn/20191205170456128.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0Nfc3VpeGlu,size_16,color_FFFFFF,t_70
或者 mysql可以如下:
在这里插入图片描述

使用实体类的包装对象作为查询条件

1.创建QueryVo类将实体类User封装

public class QueryVo {
    private User user;

    public QueryVo(User user) {
        this.user = user;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }
}

2.配置xml
在这里插入图片描述
3.测试

@org.junit.Test
    public void findByVo(){
        User u = new User();
        u.setName("%王%");
        QueryVo vo = new QueryVo(u);

        System.out.println(userDao.findByVo(vo));
    }

当实体类属性名和数据库列名不一致时,如何应对

方法1、使用as作为列名的别名。(最快,但是每一条配置的sql语句都需要写一次)
在这里插入图片描述
方法2、单独配置属性名和列名的对应关系
在这里插入图片描述
使用该关系
在这里插入图片描述
显然此方法只需要定义一次,开发效率更高。但是要多解析一段xml相对于as更慢。

编写dao实现类的使用方式

1、创建dao实现类IUserDaoImpl,包含参数 SqlSessionFactory
在这里插入图片描述
2、编写dao实现方法,方法中参数为mapper的key值,如

public List<User> findAll() {
        SqlSession sqlSession = factory.openSession();
        List<User> list = sqlSession.selectList("com.jc.dao.IUserDao.findAll");

        //关闭资源
        sqlSession.close();
        return list;
    }

3、在测试类中将初始化好的factory对象传递至实现类对象
在这里插入图片描述
4、调用方法。

添加操作需注意:
在调用session的insert方法时,注意传递user。

在这里插入图片描述
编写dao 实现类的执行过程 分析
在这里插入图片描述

使用代理dao方式的执行过程分析
在这里插入图片描述
properties标签的使用
作用

  • 可以在标签内部配置连接数据库的信息.
    在这里插入图片描述

  • 也可以通过属性引用外部文件的信息

在这里插入图片描述

    <!--resource
        用于指定配置文件的位置,路径按照类的路径写
        url:(uniform resource locator) 协议     主机      端口    uri    统一资源定位符,唯一标识一个资源的位置
        uri: (uniform resource identifier    统一资源标识符,用于在一个应用内定位一个资源.
    -->
    <properties url="file:\\\D:\idealProject\day02_eesy_01mabatisCRUD\src\main\resources\jdbcConfig.properties"></properties>
    <!--<properties resource="jdbcConfig.properties">-->
    <!--</properties>-->

typeAliases标签的使用

typeAliases标签的作用为domain中类配置别名。
在这里插入图片描述

    <typeAliases>
        <!--type属性为要配置别名的类的全限定名, alias为别名,指定了别名后可不区分大小写。如UsEr等-->
        <typeAlias type="com.jc.domain.User" alias="user"></typeAlias>

        <!--指定要配置别名的包,为该包自动配置别名,且类名就是别名,同样不区分大小写。-->
        <package name="com.jc.domain"></package>
    </typeAliases>

配置映射文件的位置


    <!--配置映射文件的位置-->
    <mappers>
        <!--<mapper resource="com/jc/dao/IUserDao.xml"></mapper>-->
        <!--指定dao接口所在的包,指定后就不需要写mapper 和 resource、class-->
        <package name="com.jc.dao"></package>
    </mappers>

连接池及事务控制
连接池
1、连接池:实际开发中都会使用连接池,可以减少获取连接所需要的时间。
2、 mybatis的连接池配置在SqlMapConfig.xml中的datesource标签,其中type属性表示的就是采用何种连接池的方式。
type属性值有:

  • POOLED 采用传统的javax.sql.DataSource规范中的连接池,mybatis中 有针对规范的实现
  • UNPOOLED 采用传统的获取连接的方式,虽然也实现Javax.sql.DataSource接口,但是并没有使用池的思想。
  • JNDI 采用服务器提供的JNDI技术实现,来获取DataSource对象,不同的服务器所能拿到DataSource是不一样。注意:如果不是web或者maven的war工程,是不能使用的。
    我们课程中使用的是tomcat服务器,采用连接池就是dbcp连接池。

事务
mybatis在oppensession时可以设置事务自动提交,不过一般不采用此种方式。应为只有一次crud操作的时候才适合自动提交。
在这里插入图片描述
动态sql语句
1、if标签
在这里插入图片描述
2、where标签
在这里插入图片描述
3、foreach标签
在这里插入图片描述
#和$的区别
在这里插入图片描述
在这里插入图片描述
一般存在用户输入的时候使用# (不能拼接)
在这里插入图片描述
多表查询

  • 表之间关系
    在这里插入图片描述
    建立多表之间的关系
  • 一对一的情况

1、方法1(不常用),新建实体类,包含两个表中的字段
表关系如图:在这里插入图片描述
现有需求 :查询所有账号信息,并且附带账户所有者姓名和地址

  • 新建实体类AccountUser类继承Account类,添加属性username,address。注意toString方法可以在方法体前加上super.toString()
public class AccountUser extends Account {
    private String username;
    private String address;

    public String getUsername() {
        return username;
    }

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

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return  super.toString() + "AccountUser{" +
                "username='" + username + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}
  • 配置xml
    在这里插入图片描述
    方法2、利用从表封装主表的信息
    例如在account表中封装user的信息:在这里插入图片描述
    在IAccount.xml中定义封装account和user的result的resutMap。
    在这里插入图片描述
  • 一对多的情况(一个用户可以拥有多个账户)
    主表拥有从表的信息即 user类有 account参数(List集合)
    在这里插入图片描述
    配置映射信息
    在这里插入图片描述
    或者
    在这里插入图片描述
  • 多对多的情况(用户可以有多个角色,一个角色可以有多个用户)在这里插入图片描述
    步骤 :
    1、
    在这里插入图片描述
    注意当结果集中有两个列名相同时需要起别名,否则封装的时候数据会出错。
    在这里插入图片描述
    JNDL使用
    注意要通过tomcat启动

延迟加载、缓存

延迟加载
在这里插入图片描述

  • 一对一:根据账户查询用户

配置
在这里插入图片描述
测试发现并没有延迟加载。在这里插入图片描述
原因是mybatis未配置延迟加载,默认为不延,
配置方法:
官方文档 》 xml配置
在这里插入图片描述
在SqlMapConfig中 添加配置

 <settings>
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="true"/>
    </settings>

执行情况

在这里插入图片描述

  • 一对多:根据用户查询账户,方法类似
    <resultMap id="userAccountMap" type="user">
        <id property="id" column="id"></id>
        <result property="username" column="username"></result>
        <result property="sex" column="sex"></result>
        <result property="address" column="address"></result>
        <result property="birthday" column="birthday"></result>

        <collection property="accounts" column="id" ofType="account" select="com.jc.dao.IAccountDao.findByUid"></collection>

    </resultMap>
<select id="findByUid" resultType="account" parameterType="int">
        select * from account where id = #{uid};
    </select>

将测试类中原来打印的内容注释
在这里插入图片描述
发现已经启用延迟加载(只执行了一个sql语句)
在这里插入图片描述
缓存
在这里插入图片描述

  • 一级缓存(sqlsession范围的缓存)
    在这里插入图片描述

测试sqlsession缓存
在这里插入图片描述
结果
在这里插入图片描述
日志中也只发起了一次请求在这里插入图片描述
清空一级缓存的情况:
使用增删改方法自动清空一二级缓存若将flashCache设置为false则不会清空二级缓存
使用commit()会清空一级缓存并提交到二级缓存
在这里插入图片描述
当调用update

  • 二级缓存
    session在关闭的时候才会同步到二级缓存。在这里插入图片描述在这里插入图片描述
    size:查询的次数

在这里插入图片描述
执行测试函数。
在这里插入图片描述
会发现只发起了一次请求,但是两次的user对象并不是同一个。因为当readOnly为false(默认)时二级缓存并不是缓存对象,而是缓存所有的值。当再次查询时,会通过值重新创建对象。当为true时,则不同。
直接去数据库找 在这里插入图片描述
全局关闭一级缓存在这里插入图片描述

注解开发

在这里插入图片描述
在模糊查询时,如果不在查询的参数上加%,可以在配置时用如下方法,注意{}里的内容必须是value,且用的是$。
在这里插入图片描述
实体类属性和数据库列名对应关系
![在这里插入图片描述](https://img-blog.csdnimg.cn/20191217100004457.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0Nfc3VpeGlu,size_16,color_FFFFFF,t_70
一对一的查询配置
在这里插入图片描述
一对多的配置
在这里插入图片描述
注解开发的二级缓存
一级缓存不需要打开,二级需要配置
1、在SqlSessionMap.xml中配置(不配也行,默认是开启的)

    <settings>
        <setting name="cacheEnabled" value="true"/>
    </settings>

2、在dao中添加注解
在这里插入图片描述
只发起了一起请求
在这里插入图片描述
但是结果为false,因为二级缓存存储的为对应的信息。需要再次使用时,通过这些信息创建一个对象。在这里插入图片描述

分页

mysql 使用limit 开始,条数
oracle select * from (select t.* , rownum rn from student t where rownum<10) where rn >3
使用插件
导包

 <dependency>
      <groupId>com.github.pagehelper</groupId>
      <artifactId>pagehelper</artifactId>
      <version>5.1.2</version>
    </dependency>

修改mybatis.xml配置文件
在这里插入图片描述
在查询之前使用PageHelper
在这里插入图片描述

事务

方式方式1(申明式事务) 通过AOP 在spring配置文件中配置

<!--配置声明式事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"></property>
</bean>
<!--配置事务通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager"/>
<!--AOP增强-->
<aop:config>
    <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.jc.service.impl.*ServiceImpl.*(..))"></aop:advisor>
</aop:config>

方式2(注解式事务)
service.impl 包下的实现类的增、删、改方法上添加 @Transactional 注解,表示开启事务
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是MyBatis框架学习笔记MyBatis是一种基于Java的持久层框架,它通过XML描述符或注解将对象映射到数据库中。它提供了自定义SQL、存储过程和高级映射等功能,使得开发人员可以更加灵活地控制SQL语句的执行过程。 MyBatis的核心组件包括SqlSessionFactory、SqlSession和Mapper。其中,SqlSessionFactory是MyBatis的核心接口,它负责创建SqlSession对象。SqlSession是MyBatis的核心类,它提供了执行SQL语句、获取Mapper接口等功能。Mapper是MyBatis的映射器接口,它定义了SQL语句和Java方法之间的映射关系。 MyBatis的优点包括: 1. 灵活性高:MyBatis提供了自定义SQL、存储过程和高级映射等功能,使得开发人员可以更加灵活地控制SQL语句的执行过程。 2. 易于使用:MyBatis的API简单易用,开发人员可以快速上手。 3. 易于维护:MyBatis的SQL语句和Java方法之间的映射关系清晰明了,易于维护。 4. 性能高:MyBatis采用了预编译和缓存等技术,可以提高SQL语句的执行效率。 以下是一个使用MyBatis框架的Java代码示例: ```java // 创建SqlSessionFactory对象 String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); // 创建SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(); try { // 获取Mapper接口 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); // 执行SQL语句 User user = userMapper.selectUserById(1); // 输出结果 System.out.println(user); } finally { // 关闭SqlSession对象 sqlSession.close(); } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值