栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

mybatis学习总结

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

mybatis学习总结

文章目录
  • 注意点 有坑
    • 相关博文
      • 1. MyBatis使用
      • 2. mybatis参数传递
  • 简介:什么是MyBatis?
  • 入门
    • 安装
    • 从 XML 中构建 SqlSessionFactory
    • 不使用 XML 构建 SqlSessionFactory
    • 从 SqlSessionFactory 中获取 SqlSession
    • 第一个MyBatis程序
    • 命名空间:
    • 作用域(Scope)和生命周期
  • XML配置
    • 属性(properties)
    • 设置(settings)
      • 日志 logilpl
        • STDOUT_LOGGING (Mybatis-04)
        • Log4j (Mybatis-04)
    • 类型别名(typeAliases)
    • 环境配置(environments)
      • 事务管理器 (transactionManager)
      • datasource 数据源 (连接数据库)
        • UNPOOLED POOLED
    • 映射器(mappers)(有一个小坑)
    • 其他配置
  • XML 映射器
    • 参数
      • 使用map传递参数
      • 字符串替换
    • 结果映射 resultmap (解决数据库中的字段名和实体类中的属性名不匹配)
      • 高级结果映射 (重点是一对多和多对一)
    • 缓存
  • 动态SQL
  • 思考
    • 模糊查询怎么写?
    • mybatis怎样防止sql注入
      • 什么是SQL注入
      • Mybatis如何防止SQL注入
      • 弃用$可以吗
    • 解决属性名和字段名不一致的问题
      • 为什么不一致会出现问题
  • 动态sql
  • 日志工厂
  • 分页实现
    • 使用limit
    • 使用RowBounds

注意点 有坑

1.mybatis 默认开启事务,如果进行了增,删,改等操作,需要手动提交事务。
2. 在和spring整合之后,就不再需要手动处理事务了。

相关博文 1. MyBatis使用

MyBatis使用

2. mybatis参数传递

mybatis传递参数的方法;

简介:什么是MyBatis?
  1. MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。
  2. MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。
  3. MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

源码可以在github上看到。。。

入门 安装

  org.mybatis
  mybatis
  x.x.x

从 XML 中构建 SqlSessionFactory

这里一般被放在一个工具类中。 详见Mybatis-01

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

mybatis-config.xml:




  
    
      
      
        
        
        
        
      
    
  
  
    
  

不使用 XML 构建 SqlSessionFactory
DataSource dataSource = BlogDataSourceFactory.getBlogDataSource();
TransactionFactory transactionFactory = new JdbcTransactionFactory();
Environment environment = new Environment("development", transactionFactory, dataSource);
Configuration configuration = new Configuration(environment);
configuration.addMapper(BlogMapper.class);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
从 SqlSessionFactory 中获取 SqlSession

之前的

try (SqlSession session = sqlSessionFactory.openSession()) {
  Blog blog = (Blog) session.selectOne("org.mybatis.example.BlogMapper.selectBlog", 101);
}

但现在有了一种更简洁的方式——使用和指定语句的参数和返回值相匹配的接口(比如 BlogMapper.class),现在你的代码不仅更清晰,更加类型安全,还不用担心可能出错的字符串字面值以及强制类型转换。

try (SqlSession session = sqlSessionFactory.openSession()) {
  BlogMapper mapper = session.getMapper(BlogMapper.class);
  Blog blog = mapper.selectBlog(101);
}
第一个MyBatis程序 命名空间:

即 mapper对应的mapper.xml中的 namespace,用来绑定接口和对应的xml配置文件。。。。

作用域(Scope)和生命周期

提示:
依赖注入框架可以创建线程安全的、基于事务的 SqlSession 和映射器,并将它们直接注入到你的 bean 中,因此可以直接忽略它们的生命周期。

SqlSessionFactoryBuilder
这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。 因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)。 你可以重用 SqlSessionFactoryBuilder 来创建多个 SqlSessionFactory 实例,但最好还是不要一直保留着它,以保证所有的 XML 解析资源可以被释放给更重要的事情。

解释:一旦创建之后就不再需要了
局不变量

SqlSessionFactory
SqlSessionFactory ==一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。 ==

使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,多次重建 SqlSessionFactory 被视为一种代码“坏习惯”。
因此 SqlSessionFactory 的最佳作用域是应用作用域。 有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。

解释:

  1. 可以想象为:数据库连接池
  2. SqlSessionFactory一旦被创建就应该在应用运行前进一直存在,没有任何理由丢弃它或重新创建另一个实例。
  3. 因此SqSessionFactory的最佳作用域是应用作用域
  4. 最简单的就是使用单例模式或者静态单例模式。。。

SqlSession
每个线程都应该有它自己的 SqlSession 实例。
SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。 绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。 也绝不能将 SqlSession 实例的引用放在任何类型的托管作用域中,比如 Servlet 框架中的 HttpSession。 如果你现在正在使用一种 Web 框架,考虑将 SqlSession 放在一个和 HTTP 请求相似的作用域中。 换句话说,==每次收到 HTTP 请求,就可以打开一个 SqlSession,返回一个响应后,就关闭它。 ==

解释:

  1. 连接到池的一个请求!
  2. SqlSession的实例不是线程安全的,因此是不能被共享的,所以最佳的所用于是请求或方法作用域
  3. 用完之后需要立即关闭

这里的每一个Mapper都代表了一个业务。

XML配置

针对的就是mybatis-config.xml中的配置。

mybatis-config.xml 中的各项配置的顺序必须如上图所示,否则会报错。。。

属性(properties)

我们可以通过properties属性来实现引用配置文件。

这些属性可以在外部进行配置,并可以进行动态替换。你既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设置。例如:

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306useSSL=true&useUnicode=true&characterEncoding=UTF-8
username=root
password=123456


                
                
                
                
            

注意:

如果一个属性在不只一个地方进行了配置,那么,MyBatis 将按照下面的顺序来加载:

1.首先读取在 properties 元素体内指定的属性。
2.然后根据 properties 元素中的 resource 属性读取类路径下属性文件,或根据 url 属性指定的路径读取属性文件,并覆盖之前读取过的同名属性。
3.最后读取作为方法参数传递的属性,并覆盖之前读取过的同名属性。

因此,通过方法参数传递的属性具有最高优先级,resource/url 属性中指定的配置文件次之,最低优先级的则是 properties 元素中指定的属性。

设置(settings)

MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。 比如日志相关设置就在里面。。。

例如:懒加载,缓存,驼峰命名自动映射

日志 logilpl

指定Mybatis日志的具体实现,未指定时将自动查找。

STDOUT_LOGGING 掌握
SLF4J
LOG4J 掌握
LOG4J2
JDK_LOGGING
COMMONS_LOGGING
NO_LOGGING

STDOUT_LOGGING (Mybatis-04)

标准日志输出,不需要配置,即可实现。

Log4j (Mybatis-04)

简介:

  1. Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件,

使用:

  1. 先导入包

            log4j
            log4j
            1.2.17
        
  1. log4j.properties
log4j.rootLogger=DEBUG,console,file

#控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n

#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/zhx.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n

#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
类型别名(typeAliases)

1.类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。例如:


  
  
  
  
  
  

当这样配置时,Blog 可以用在任何使用 domain.blog.Blog 的地方。

2.也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean,比如:


  

每一个在包 domain.blog 中的 Java Bean,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。 比如 domain.blog.Author 的别名为 author;

3.若有注解,则别名为其注解值。见下面的例子:

@Alias("author")
public class Author {
    ...
}
环境配置(environments)

注意:同一个xml文件中,可以配置多个environment

MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中, 现实情况下有多种理由需要这么做。例如,开发、测试和生产环境需要有不同的配置;或者想在具有相同 Schema 的多个生产数据库中使用相同的 SQL 映射。还有许多类似的使用场景。

不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。

所以,如果你想连接两个数据库,就需要创建两个 SqlSessionFactory 实例,每个数据库对应一个。而如果是三个数据库,就需要三个实例,依此类推,记起来很简单:

每个数据库对应一个 SqlSessionFactory 实例
为了指定创建哪种环境,只要将它作为可选的参数传递给 SqlSessionFactoryBuilder 即可。可以接受环境配置的两个方法签名是:

SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment, properties);

如果忽略了环境参数,那么将会加载默认环境,如下所示:

SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, properties);

environments 元素定义了如何配置环境:


  
    
      
    
    
      
      
      
      
    
  

提示: 如果你正在使用 Spring + MyBatis,则没有必要配置事务管理器,因为 Spring 模块会使用自带的管理器来覆盖前面的配置。

事务管理器 (transactionManager)

在 MyBatis 中有两种类型的事务管理器(也就是 type="[JDBC|MANAGED]"):

  1. JDBC – 这个配置直接使用了 JDBC 的提交和回滚设施,它依赖从数据源获得的连接来管理事务作用域。
  2. MANAGED – 这个配置几乎没做什么。它从不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。 默认情况下它会关闭连接。然而一些容器并不希望连接被关闭,因此需要将 closeConnection 属性设置为 false 来阻止默认的关闭行为。例如:

  

datasource 数据源 (连接数据库)

dataSource 元素使用标准的 JDBC 数据源接口来配置 JDBC 连接对象的资源。

常用的数据源:dbcp,c3p0,druid

有三种内建的数据源类型(也就是 type=[UNPOOLED|POOLED|JNDI]"):

UNPOOLED POOLED 映射器(mappers)(有一个小坑)

作用:告诉MyBatis在哪里找到SQL映射语句。


  
  
  


  
  
  

注意点:1.接口和他的mapper配置文件必须同名!
2.接口和他的mapper配置文件必须在同一个包下。。。


  

这些配置会告诉 MyBatis 去哪里找映射文件。。。。。。

// 已经废弃


  
  
  

其他配置

plugins 插件
mybatis-generator-core
mybatis-plus
通用吗 mapper

XML 映射器

cache – 该命名空间的缓存配置。
cache-ref – 引用其它命名空间的缓存配置。
resultMap – 描述如何从数据库结果集中加载对象,是最复杂也是最强大的元素。
parameterMap – 老式风格的参数映射。此元素已被废弃,并可能在将来被移除!请使用行内参数映射。文档中不会介绍此元素。
sql – 可被其它语句引用的可重用语句块。
insert – 映射插入语句。
update – 映射更新语句。
delete – 映射删除语句。
select – 映射查询语句。

参数

mybatis传递参数

之前见到的所有语句都使用了简单的参数形式。但实际上,参数是 MyBatis 非常强大的元素。对于大多数简单的使用场景,你都不需要使用复杂的参数,不需要指定 paramType比如:


  select id, username, hashedPassword
  from some_table
  where id = #{id}

上述语句只是简单地将所有的列映射到 HashMap 的键上,这由 resultType 属性指定。虽然在大部分情况下都够用,但是 HashMap 并不是一个很好的领域模型。你的程序更可能会使用 JavaBean 或 POJO(Plain Old Java Objects,普通老式 Java 对象)作为领域模型。MyBatis 对两者都提供了支持。看看下面这个 JavaBean:

package com.someapp.model;
public class User {
  private int id;
  private String username;
  private String hashedPassword;

  public int getId() {
    return id;
  }
  public void setId(int id) {
    this.id = id;
  }
  public String getUsername() {
    return username;
  }
  public void setUsername(String username) {
    this.username = username;
  }
  public String getHashedPassword() {
    return hashedPassword;
  }
  public void setHashedPassword(String hashedPassword) {
    this.hashedPassword = hashedPassword;
  }
}

基于 JavaBean 的规范,上面这个类有 3 个属性:id,username 和 hashedPassword。这些属性会对应到 select 语句中的列名。






  select
    user_id             as "id",
    user_name           as "userName",
    hashed_password     as "hashedPassword"
  from some_table
  where id = #{id}

方法2:
你会发现上面的例子没有一个需要显式配置 ResultMap,这里显示配置ResultMap

注意:可以只需要配置不匹配的字段即可,匹配的不用管。。。


  
  
  

然后在引用它的语句中设置 resultMap 属性就行了(注意我们去掉了 resultType 属性)。比如:


        select * from mybatis.user where name like #{value}
    
@Test
    public void getUserLike(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        //模糊查询
        List list = userMapper.getUserLike("%张%");
        for (User user : list) {
            System.out.println(user);
        }

        sqlSession.close();
    }
  1. 在sql拼接中使用通配符
mybatis怎样防止sql注入

Mybatis这个框架在日常开发中用的很多,比如面试中经常有一个问题:$和#的区别,它们的区别是使用#可以防止SQL注入,今天就来看一下它是如何实现SQL注入的

什么是SQL注入

在讨论怎么实现之前,首先了解一下什么是SQL注入,我们有一个简单的查询操作:根据id查询一个用户信息。
它的sql语句应该是这样:select * from user where id = 。
我们根据传入条件填入id进行查询。
如果正常操作,传入一个正常的id,比如说2,那么这条语句变成
select * from user where id =2。
这条语句是可以正常运行并且符合我们预期的。
但是如果传入的参数变成’’ or 1=1,这时这条语句变成select * from user where id = ‘’ or 1=1。
让我们想一下这条语句的执行结果会是怎么?
它会将我们用户表中所有的数据查询出来,显然这是一个大的错误。这就是SQL注入。

Mybatis如何防止SQL注入

在开头讲过,可以使用 # 来防止SQL注入,它的写法如下:

SELECt * FROM user where id = #{id} 在mybatis中查询还有一个写法是使用$,它的写法如下:

select * from user where id = ${id}

当我们在外部对这两个方法继续调用时,发现如果传入安全的参数时,两者结果并无不同,如果传入不安全的参数时,第一种使用#的方法查询不到结果(select * from user where id = ‘’ or 1=1),但这个参数在第二种也就是$下会得到全部的结果。

并且如果我们将sql进行打印,会发现添加#时,向数据库执行的sql为:select * from user where id = ’ ‘’ or 1=1 ',它会在我们的参数外再加一层引号,在使用$时,它的执行sql是select * from user where id = ‘’ or 1=1。

弃用$可以吗

我们使用#也能完成的作用,并且使用的作用,并且使用还有危险,那么我们以后不使用$不就行了吗。

并不是,它只是在我们这种场景下会有问题,但是在有一些动态查询的场景中还是有不可代替的作用的,比如,动态修改表名select * from ${table} where id = #{id}。我们就可以在返回信息一致的情况下进行动态的更改查询的表,这也是mybatis动态强大的地方。

解决属性名和字段名不一致的问题 为什么不一致会出现问题

1.MyBatis 会在幕后自动创建一个 ResultMap,再根据属性名来映射列到 JavaBean 的属性上。如果列名和属性名不能匹配上。查出来的值就会NULL。
2.可以在 SELECt 语句中设置列别名(这是一个基本的 SQL 特性)来完成匹配

对应的实体类:

	private int id;
    private String name;
    private String password;

        select id,name,pwd as password from mybatis.user where id = #{id}
    

结果:User{id=1, name=‘张’, password=‘123456’}

动态sql

什么是动态sql:动态sql就是根据不同的条件生成不同的SQL语句

日志工厂 分页实现

mybatis-04

思考:为什么要分页?
1.减少每一次的数据处理量

使用limit

使用limit分页
公式:

SELECT * from user limit startIndex, endIndex;
使用RowBounds
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/315510.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号