Mybatis常见问题
  wMDCgnRK3Ovr 2023年11月17日 44 0

1.JDBC

1.1JDBC是什么

  • 高级语言的应用程序需要特定的方式访问数据库。
  • 特定的方式:JDBC, ODBC

Mybatis常见问题_数据库

  • JDBC本质上是一系列的应用程序接口(API)
  • 通过JAVA语言访问任何结构化数据库
  • 通过JDBC API写出的程序,能够将SQL语句发送到相应的任何一种数据库

Mybatis常见问题_sql_02

  • 通过使用JDBC,开发人员可以很方便地将SQL语句传送给几乎任何一种数据库。也就是说,开发人员可以不必写一个程序访问SyBase,写另一个程序访问Oracle,再写一个程序访问Microsoft的SQLServer。用JDBC写的程序能够自动地将SQL语句传送给相应地数据库管理系统(DBMS)。不但如此,使用JAVA编写的应用程序可以在任何支持JAVA的平台上运行,不必在不同的平台上编写不同的应用。
  • 简单地说,JDBC能完成下列三件事:
  • 同一个数据库建立连接
  • 向数据库发送SQL语句
  • 处理数据库返回的结果

1.2 JDBC基本编程

  • 建立数据库连接

DBConnection

Mybatis常见问题_数据库_03

  • 到数据库中查找是否存在给定id的用户,如果存在,就创建一个Bean,否则返回null

BankBean


Mybatis常见问题_数据库_04

JDBC的使用过程

1.注册驱动

  • 放置JDBC包或配置ODBC
  • 针对提供JDBC包的数据库系统,例如SQLServer2000/2005/2008,JRE6.0运行环境,需要事先把SQLServer的JDBC包sqljdbc4.jar复制到JRE安装目录的\lib\ext下,或者复制到工程项目的lib目录下。其他环境变量的前提设置:已设置好JAVA_HOME和classpath。
  • 针对没有提供JDBC包的数据库系统,例如Access,需要事先配置ODBC数据源,使用sun提供的JDBC-ODBC桥,由JRE安装目录下的\lib\rt.jar提供。
  • 在程序中加载驱动器---Class.forName("数据库驱动器名称")
  • 不同数据库,驱动程序名称不同,例如SQLServer:Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
  • MySQL数据源:Class.forName("com.mysql.jdbc.Driver");
  • ODBC数据源:Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");

2.建立连接(Connection)

  • 声明Connection对象:Connection cnotallow=null;
  • 通过驱动程序建立连接
  • 方式1:cnotallow=DriverManager.getConnection(url, user, password);
    url格式:
    JDBC:子协议:子名称://主机IP地址:端口;数据库名;属性名=属性值; ...
    其他参数如:useUnicode=true&characterEncoding=GBK
  • 方式2:cnotallow=DriverManager.getConnection(url);
    此时,user,password用“属性名=属性值”方式放置在url字符串中
    或者表示没有用户名和密码

建立连接示例(连接MySQL方式):

String url="jdbc:mysql://localhost:3306/loginuser";
conn=DriverManager.getConnection(url,"root","root");

3.创建命令对象(Statement)并执行SQL语句

  • Statement对象,执行不需要参数的SQL语句
Statement st=conn.createStatement();
st.executeQuery("select * from bankaccount");
  • PreparedStatement对象,执行需要传送参数的SQL语句
String sql="select * from bankaccount where bankid=? and balance>?";
PreparedStatement ps=conn.prepareStatement(sql);
ps.setString(1,"101");
ps.setInt(2,100);
ps.executeQuery();

4.处理执行结果(ResultSet)

  • 对查询的结果集进行读取
  • 获取Statement对象st执行查询的结果集
    ResultSet rs=st.executeQuery(sql);
  • 获取PreparedStatement对象ps执行查询的结果集
    ResultSet rs=ps.executeQuery();
  • 依次处理结果集中的每条记录
while(rs.next()){
    //获取当前记录中指定列名的数据
    rs.getString("col_name1");
    rs.getInt("col_name2");
}

5.释放资源

  • 释放ResultSet,Statement,Connection
  • 数据库连接(Connection)是非常稀有的资源,用完后必须马上释放,如果Connection不能及时正确的关闭将导致系统宕机。Connection的使用原则是尽量晚创建,尽量早的释放。
//释放资源
public static void dbClose(Connection conn,PreparedStatement ps,ResultSet rs)
throws SQLException
{
      rs.close();
      ps.close();
      conn.close();
}

6.代码模板

Mybatis常见问题_sql_05

1.3JDBC的缺点

Mybatis常见问题_sql_06

2.MyBatis

2.1MyBatis是什么

MyBatis本是apache的一个开源项目iBatis,2010年这个项目由apache software foundation迁移到了google code,并且改名为MyBatis。

  • 一个基于Java的持久层框架
  • 消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索
  • 将接口和Java的POJOs(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录

2.2MyBatis基本编程

  • mybatis-config.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="test">
      <environment id="test">
         <transactionManager type="JDBC" />
         <dataSource type="POOLED">
            <property name="driver" value="com.mysql.jdbc.Driver" />
            <property name="url" value="jdbc:mysql://localhost:3306/java web" />
            <property name="username" value="root" />
            <property name="password" value="root" />
         </dataSource>
      </environment>
   </environments>
   <mappers>
     <mapper resource="mappers/UserMapper.xml" />
     <mapper resource="dao/UserDaoMapper.xml"/>
   </mappers>
  </configuration>
  • pojo---User.java
public class User {
    private String id;
    private String userName;
    private String password;
    private String name;
    private Integer age;
    private Integer sex;
    private Date birthday;
    private String created;
    private String updated;

    public String getId() {
        return id;
    }

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

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Integer getSex() {
        return sex;
    }

    public void setSex(Integer sex) {
        this.sex = sex;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public String getCreated() {
        return created;
    }

    public void setCreated(String created) {
        this.created = created;
    }

    public String getUpdated() {
        return updated;
    }

    public void setUpdated(String updated) {
        this.updated = updated;
    }

    @Override
    public String toString() {
        return "User{" +
                "id='" + id + '\'' +
                ", userName='" + userName + '\'' +
                ", password='" + password + '\'' +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", sex=" + sex +
                ", birthday='" + new SimpleDateFormat("yyyy-MM-dd").format(birthday) + '\'' +
                ", created='" + created + '\'' +
                ", updated='" + updated + '\'' +
                '}';
    }
}
  • Mapper---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">
<mapper namespace="UserMapper">
	<!-- 根据uid查询一个用户信息 -->
	<select id="selectUserById" parameterType="Integer" resultType="pojo.User">
		select * from user_copy where id = #{id}
	</select>
	
</mapper>
  • Test---MyBatisTest.java
public class MyBatisTest {
   public static void main(String[] args) throws Exception {
      // 指定全局配置文件
      String resource = "mybatis-config.xml";
      // 读取配置文件
      InputStream inputStream = Resources.getResourceAsStream(resource);
      // 构建sqlSessionFactory
      SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
      // 获取sqlSession
      SqlSession sqlSession = sqlSessionFactory.openSession();
      try {
         // 操作CRUD,第一个参数:指定statement,规则:命名空间+“.”+statementId
         // 第二个参数:指定传入sql的参数:这里是用户id
         User user = sqlSession.selectOne("UserMapper.selectUserById", 100);
         System.out.println(user);
      } finally {
         sqlSession.close();
      }
   }
}

2.3MyBatis的优点

1.优化获取和释放

  • 解决了数据库连接创建、释放频繁造成系统资源浪费从而影响系统性能的问题。
  • 解决方法:统一从DataSource里面获取数据库连接,将DataSource的具体实现通过让用户配置来应对变化。在SqlMapConfig.xml中配置数据库连接池,使用连接池管理数据库连接。

2.SQL统一管理,对数据库进行存取操作

  • 使用JDBC对数据库进行操作时,SQL查询语句分布在各个Java类中,可读性差,不利于维护,当我们修改Java类中的SQL语句时需要重新进行编译。
  • MyBatis可以把SQL语句放在配置文件中统一进行管理,以后修改配置文件,也不需要重新编译部署。
  • 解决方法:将SQL语句配置在XXXMapper.xml文件中与java代码分离。

3.传入参数映射和生成动态SQL语句

在查询中可能需要根据一些属性进行组合查询,比如我们进行商品查询,我们可以根据商品名称进行查询,也可以根据发货地进行查询,或者两者组合查询。如果使用JDBC进行查询,这样就需要写多条SQL语句。

Mybatis常见问题_数据库_07

4.能够对结果集进行映射

在使用JDBC进行查询时,返回一个结果集ResultSet,要从结果集中取出结果封装为需要的类型。在Mybatis中可以设置将结果直接映射为自己需要的类型,比如:JavaBean对象,一个Map,一个List等等。

解决方法:MyBatis自动将sql执行结果映射至java对象,通过statement中的resultType定义输出结果的类型。

2.4MyBatis与Spring整合

整合后比MyBatis基本编程多了一个DAO。

Mybatis常见问题_sql_08

3.MyBatis Plus

通用CRUD操作:内置通用Mapper、通用Service,仅仅通过少量配置即可实现单表大部分CRUD操作。

4.#{}和${}的区别

  • #{}是占位符,预编译处理;${}是拼接符,字符串替换,没有预编译处理
  • MyBatis在处理#{}时,#{}传入参数是以字符串传入,会将SQL中的#{}替换为?号,调用PreparedStatement的set方法来赋值
  • MyBatis在处理Mybatis常见问题_SQL_09{}替换成变量的值,相当于JDBC中的Statement编译
  • 变量替换后,#{}对应的变量自动加上单引号'';变量替换后,${}对应的变量不会加上单引号''
  • #{}可以有效防止SQL注入,提高系统安全性;${}不能防止SQL注入
  • #{}的变量替换是在DBMS中;${}的变量替换是在DBMS外

Mybatis常见问题_数据库_10

Mybatis常见问题_sql_11

Mybatis常见问题_数据库_12

5.MyBatis缓存

MyBatis中有一级缓存和二级缓存,默认情况下一级缓存是开启的,而且是不能关闭的。一级缓存是指SqlSession级别的缓存,当在同一个SqlSession中进行相同的sql语句查询时,第二次以后的查询不会从数据库查询,而是直接从缓存中获取,一级缓存最多缓存1024条SQL。二级缓存是指可以跨SqlSession的缓存。是mapper级别的缓存,对于mapper级别的缓存,不同的sqlsession是可以共享的。

Mybatis常见问题_sql_13

Mybatis常见问题_SQL_14

5.1MyBatis的一级缓存原理(sqlsession级别)

第一次发出一个查询sql,sql查询结果写入sqlsession的一级缓存中,缓存使用的数据结构是一个map。

key:MapperID+offset+limit+Sql+所有的入参

value:用户信息

同一个sqlsession再次发出相同的sql,就从缓存中取出数据。如果两次中间出现commit操作(修改、添加、删除),本sqlsession中的一级缓存区域全部清空,下次再去缓存中查询不到所以要从数据库查询,从数据库查询到再写入缓存。

5.2MyBatis的二级缓存原理(mapper级别)

二级缓存的范围是mapper级别(mapper同一个命名空间),mapper以命名空间为单位创建缓存数据结构,结构是map。MyBatis的二级缓存是通过CacheExecutor实现的。CacheExecutor其实是Executor的代理对象。所有的查询操作,在CacheExecutor中都会先匹配缓存中是否存在,不存在则查询数据库。

key:MapperID+offset+limit+sql+所有的入参

具体使用需要配置:

  • MyBatis全局配置中启用二级缓存配置
  • 在对应的Mapper.xml中配置cache节点
  • 在对应的select查询节点中添加useCache=true
【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月17日 0

暂无评论

推荐阅读
  biE3E3UjTjeg   2024年01月22日   36   0   0 SQLSQL
wMDCgnRK3Ovr