Mybatis(一)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群版 2核4GB 100GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用版 2核4GB 50GB
简介: Mybatis相关介绍

1.mybatis基础知识

①. Jdbc的缺点

1.原始Jdbc的缺点所在(了解)

1>.原始jdbc操作(查询数据)

20190926200937701.png

2>.原始jdbc操作(插入数据)

20190926200949908.png

3>. 原始jdbc操作的分析

1.原始jdbc开发存在的问题如下:

  • ①. 数据库连接创建、释放频繁造成系统资源浪费从而影响系统性能
  • ②. sql 语句在代码中硬编码,造成代码不易维护,实际应用 sql 变化的可能较大,sql 变动需要改变java代码
  • ③. 查询操作时,需要手动将结果集中的数据手动封装到实体中。插入操作时,需要手动将实体的数据设置到sql语句的占位符位置

2.应对上述问题给出的解决方案:

  • ①. 使用数据库连接池初始化连接资源
  • ②. 将sql语句抽取到xml配置文件中
  • ③. 使用反射、内省等底层技术,自动将实体与表进行属性与字段的自动映射

②. Mybatis入门介绍

http://www.mybatis.org/mybatis-3/

1>. 什么是Mybatis

  • ①. mybatis 是一个优秀的基于java的持久层框架
  • ②. mybatis 可以隐藏jdbc繁杂的api
  • ③. 我们只需要关注sql语句
  • ④. mybatis自动完成实体对象和数据库表数据的映射关系

2>. Mybatis的工作原理

20190504143649909.png

    1.读取MyBatis配置文件mybatis-config.xml。mybatis-config.xml作为MyBatis的全局配置
文件,配置了MyBatis的运行环境等信息,其中主要内容是获取数据库连接
    2.加载映射文件Mapper.xml。Mapper.xml文件即SQL映射文件,该文件中配置了操作数据库的SQL
语句,需要在mybatis-config.xml中加载才能执行。mybatis-config.xml可以加载多个配置文件,个配置文件对应数据库中的一张表
    3.创建会话工厂。通过MyBatis的环境等配置信息构造会话工厂SqlSessionFactory
    4.创建SqlSession对象。由会话工厂创建SqlSession对象,该对象中包含了执行SQL的所有
方法
    5.MyBatis底层定义了一个Executor接口来操作数据库,它会根据SqlSession传递的形参的所有
方法
    6.在Execuotor接口的执行方法中,包含了一个MappedStatement类型的参数,该参数是对映射信息
的封装,用来存储要映射的SQL语句的id、参数等。Mapper.xml文件中的一个SQL对应一个
MappedStatement对象,SQL的id是MappedStatement的id
    7.输入参数映射。在执行方法时,MapperStatement对象会对用户执行SQL语句的输入参数进行定义
(可以定义为Map、List、基本数据类型和POJO类型),Executor执行器会通过MappedStatement对象在
执行SQL前,将输入的Java对象映射到SQL语句中。这里对输入参数的映射过程就类似于JDBC编程中对
PreparedStatement对象设置参数的过程
    8.输出结果映射。在数据库中执行完SQL语句后,MappedStatement对象会对SQL执行输出的结果进
行定义(可以定义为Map和List类型、基本类型、POJO类型),Executor执行器会通过MappedStatement
对象在执行SQL语句后,将输出结果映射至Java对象中。这种将输出结果映射到Java对象的过程就类似于
JDBC编程中对结果的解析处理过程

3>. MyBatis入门程序

  • ①. 导入MyBatis的坐标和其他相关坐标
    <!--mybatis坐标-->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.4.5</version>
    </dependency>
    <!--mysql驱动坐标-->
    <dependency>    
        <groupId>mysql</groupId>   
        <artifactId>mysql-connector-java</artifactId>    
        <version>5.1.6</version>    
        <scope>runtime</scope>
    </dependency>
    <!--单元测试坐标-->
    <dependency>    
        <groupId>junit</groupId>    
        <artifactId>junit</artifactId>    
        <version>4.12</version>    
        <scope>test</scope>
    </dependency>
    <!--日志坐标-->
    <dependency>    
        <groupId>log4j</groupId>    
        <artifactId>log4j</artifactId>    
        <version>1.2.12</version>
    </dependency>
  • ②. 编写User实体
public class User {
    private int id;
    private String username;
    private String password;
    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 getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}
  • ③.编写UserMapper映射文件
  <?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">    
    <select id="findAll" resultType="com.itheima.domain.User">        
      select * from User    
    </select>
  </mapper>
  • ④. 编写MyBatis核心文件
<!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:///test"/>                
        <property name="username" value="root"/>
        <property name="password" value="root"/>            
      </dataSource>        
    </environment>    
  </environments>    
  <mappers> 
    <mapper resource="com/itheima/mapper/UserMapper.xml"/> 
  </mappers>
</configuration>
  • ⑤. 编写测试代码
    /*查询所有*/
    @Test
    public void test1()throws Exception{
        //1.加载配置文件
        InputStream inputStream=Resources.getResourceAsStream("sqlMapConfig.xml");
        //2.获取工厂对象
        SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
        //3.创建会话对象
        SqlSession sqlSession=sqlSessionFactory.openSession();
        //4.执行操作
        List<User>list=sqlSession.selectList("userMapper.findAll");
        System.out.println(list);
        //5.释放资源
        sqlSession.close();
    }
  • ⑥. log4j.properties
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=c:/mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### set log levels - for more verbose logging change 'info' to 'debug' ###
log4j.rootLogger=debug, stdout

4>. MyBatis的增删改查操作

20190926233530933.png


1. 抽取工具类


public class MybatisUtils {
    /*私有构造方法*/
    private MybatisUtils(){}
    private static SqlSessionFactory sqlSessionFactory;
    static {
        try {
            //1.加载配置文件
            InputStream inputStream= Resources.getResourceAsStream("sqlMapConfig.xml");
            //2.给SqlSessionFactory工厂赋值
            sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //3.获取sqlSession会话对象
    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession();
    }
}

2. 查询[ 查询所有、通过id进行查询、模糊查询 ]

    <!--查询所有的对象-->
    <select id="findAll" resultType="com.itheima.domain.User">
        select * from user
    </select>
    <!--根据id进行查询-->
    <select id="findUserById" parameterType="Integer" resultType="com.itheima.domain.User">
        select * from user where id=#{id}
    </select>
    <!--模糊查询-->
    <select id="findUserByName" parameterType="String" resultType="com.itheima.domain.User">
        select * from user where username like concat('%',#{value},'%')
    </select>
        /*1.查询所有*/
        @Test
        public void SelectAll()throws Exception{
            //1.加载配置文件
            InputStream inputStream=Resources.getResourceAsStream("sqlMapConfig.xml");
            //2.获取SqlSesiionFactory会话工厂
            SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
            //3.创建sqlSession会话对象
            SqlSession sqlSession=sqlSessionFactory.openSession();
            //4.执行操作
            List<User>list=sqlSession.selectList("userMapper.findAll");
            System.out.println(list);
            //5.释放资源
            sqlSession.close();
        }
        /*2.通过id查询用户信息*/
        @Test
        public void selectById()throws Exception{
            //1.加载配置文件
            InputStream inputStream=Resources.getResourceAsStream("sqlMapConfig.xml");
            //2.创建SqlSessionFactory工厂对象
            SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
            //3.创建SqlSession会话对象
            SqlSession sqlSession = sqlSessionFactory.openSession();
            //4.执行sql
            User user=sqlSession.selectOne("userMapper.findUserById",1);
            System.out.println(user);
            //5.释放资源
            sqlSession.close();
        }
        /*3.根据姓名进行模糊查询*/
        @Test
        public void selectByName()throws Exception{
            //1.获取会话对象
            SqlSession sqlSession = MybatisUtils.getSqlSession();
            //2.执行sql
            List<User> list = sqlSession.selectList("userMapper.findUserByName", "x");
            System.out.println(list);
        }

3. 添加一个用户

  • #{id}:从输入user对象中获取id属性值
    <!--插入数据-->
    <insert id="insertUser" parameterType="com.itheima.domain.User">
        insert into user(id,username,password)values(#{id},#{username},#{password})
    </insert>
        /*4.新增一条User记录*/
        @Test
        public void add()throws Exception{
            //1.获取会话对象
            SqlSession sqlSession = MybatisUtils.getSqlSession();
            //2.执行sql
              //2.1 创建User对象
              User user=new User();
              user.setId(5);
              user.setUsername("xiaozhi");
              user.setPassword("123");
              int row=sqlSession.insert("userMapper.insertUser",user);
              System.out.println(row);
            //3.进行事务的提交
            sqlSession.commit();
            //4.释放资源
            sqlSession.close();
        }

4. 修改

    <!--修改-->
    <update id="updateUser" parameterType="com.itheima.domain.User">
          update user set username=#{username},password=#{password} where id=#{id}
    </update>
         /*5.修改*/
        @Test
        public void update()throws Exception{
            //1.获取会话对象
            SqlSession sqlSession = MybatisUtils.getSqlSession();
            //2.执行sql
            User user=new User();
            user.setId(1);
            user.setUsername("xiaoxing");
            user.setPassword("123456");
            int result=sqlSession.update("userMapper.updateUser",user);
            System.out.println(result);
            //3.进行事务的提交
            sqlSession.commit();
            //4.释放资源
            sqlSession.close();
        }

5. 通过id进行删除

    <!--删除-->
    <delete id="deleteById" parameterType="java.lang.Integer">
        delete from user where id=#{id}
    </delete>
    /*6.删除*/
    @Test
    public void delete()throws Exception{
        //1.获取会话对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        //2.执行sql
        int result=sqlSession.delete("userMapper.deleteById",5);
        System.out.println(result);
        //3.进行事务的提交
        sqlSession.commit();
        //4.释放资源
        sqlSession.close();
    }

5>. 知识点总结[ 掌握 ]

1. 映射文件[ UserMapper.xml]

<mapper namespace="test">
    <select id="findCustomerById" parameterType="Integer"
  resultType="com.itcast.mybatis.po.User">
  select * from user where id = #{id}
  </select>
</mapper>
  • ①. namespace命名空间:作用就是对sql进行分类化管理,理解sql隔离。通常会设置成包名+sql映射文件名注意:使用namespace代理方式开发,namespace有特殊的作用
  • ②. 通过select执行数据查询<select id="" parameterType="" resultType="">
1.id:标识映射文件的sql,称为statement的id
[将sql语句封装mappedStatement对象中,所以将id称为statement的id ]
2.#{}:表示占位符,相当于?
3.#{id}:其中的id表示 接收输入的参数,参数名称是id,如果输入参数是简单类型, 
  #{}中的参数名可以任意 ,可以value或其他名称
4.parameterType:指定输入参数类型,这里指定int型
5.resultType:指定sql输出结果的映射的java类型,resultType表示将单条记录映射成的java对象

20190927000131916.png

2. parameterType 和 resultType

  • ①. parameterType:在映射文件中通过parameterType指定输入 参数的类型
  • ②. resultType:在映射文件中通过resultType指定输出结果的类型

3. selectOne(statement,parament)和selectList(statement,parament)

  • ①. 第一个参数statement:映射文件中statement的id,等于=namaspace+statementId
  • ②. 第二个参数parament:指定和映射文件中所匹配paramtype类型的参数(输入参数)
  • ③. session.selectOne 结果是与映射文件中所匹配的resultType类型的对象

4. selectOne和selectList

  • ①. selectOne:表示查询出一条记录进行映射。如果使用了selectOne可以实现,那么使用selectList也可以实现 [ List中只有一个对象 ]
  • ②. selectList:表示查询出一个列表 [ 多个列表 ] 进行映射,如果使用了,如果使用selectList要查询多天记录,不能使用selectOne

5. 模糊查询注意事项

  • ①. 第一种情况是字符串的拼接,会引起sql注入,不推荐使用
  1.select * from user where username like ‘%${value}%’
  2.select * from user where username like concat('%',#{value},'%')
  • ②. #{ } 和 ${ }
  #{ }:
    1.#{}表示一个占位符号,#{}接收输入参数,类型可以是简单类型,pojo等
    2.如果接受简单类型,#{}里面的可以写成value或其他的
    3.#{}接受的是pojo。要通过 user.user.username的形式获取
  ${ }:
    1.表示一个拼接符号,会引起sql注入,所以不建议使用
    2.${ } 接受输入参数,类型可以是简单类型,pojo等  
    3.${ } 接受的是pojo。要通过 user.user.username的形式获取

6>. Mybatis的核心对象

1. SqlSessionFactory

  • 作用:创建SqlSession对象
  String resource = "org/mybatis/builder/mybatis-config.xml"; 
  InputStream inputStream = Resources.getResourceAsStream(resource); 
  SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); 
  SqlSessionFactory factory = builder.build(inputStream);
  SqlSessionFactory对象是线程安全的,它一旦被创建,在整个应用执行期间都会存在。如果我们
多次地创建同一个数据库的SqlSessionFactory,那么数据库的资源将很容易被消耗。为了解决此
问题,通常每一个数据库都只对应同一个SqlSessionFactory,所以在构建SqlSessionFactory实
例时,建议使用单列模式

20190926235731707.png

2. SqlSession会话对象

    SqlSession 是一个加强版的Connection,所以用完后要关闭资源
  1.执行语句的方法主要有:
  <T> T selectOne(String statement, Object parameter) 
  <E> List<E> selectList(String statement, Object parameter) 
  int insert(String statement, Object parameter) 
  int update(String statement, Object parameter) 
  int delete(String statement, Object parameter)
  2.操作事务的方法主要有:
  void commit()  
  void rollback() 
  注意:在增删改中都要进行事务的提交
  3.<T>T getMapper(Class<T>type):[重点]
  该方法会返回Mapper接口的代理对象,该对象关联了SqlSession对象,开发人员可以使用该对象
直接调用方法操作数据库。参数type是Mapper接口类型。Mybatis官方推荐通过Mapper对象访问Mybatis  

3. 使用工具类创建SqlSession

  public class MybatisUtils {
      /*私有构造方法*/
      private MybatisUtils(){}
      private static SqlSessionFactory sqlSessionFactory;
      static {
          try {
              //1.加载配置文件
              InputStream inputStream= Resources.getResourceAsStream("sqlMapConfig.xml");
              //2.给SqlSessionFactory工厂赋值
              sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
          } catch (IOException e) {
              e.printStackTrace();
          }
      }
      //3.获取sqlSession会话对象
      public static SqlSession getSqlSession(){
          return sqlSessionFactory.openSession();
      }
  }

7>. MyBatis常用配置解析

1. environments标签

  • 数据库环境的配置,支持多环境配置

20190927000928663.png

  1.其中,事务管理器(transactionManager)类型有两种:[掌握JDBC]
  •JDBC:这个配置就是直接使用了JDBC 的提交和回滚设置,它依赖于从数据源得到的连接来管理事务作
  用域。
  •MANAGED:这个配置几乎没做什么。它从来不提交或回滚一个连接,而是让容器来管理事务的整个生命
  周期(比如 JEE 应用服务器的上下文)。 默认情况下它会关闭连接,然而一些容器并不希望这样,因
  此需要将 closeConnection 属性设置为 false 来阻止它默认的关闭行为。
  2.其中,数据源(dataSource)类型有三种:[掌握POOLED]
  •UNPOOLED:这个数据源的实现只是每次被请求时打开和关闭连接。
  •POOLED:这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来。
  •JNDI:这个数据源的实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部
  配置数据源,然后放置一个 JNDI 上下文的引用。

2. mapper标签

  • 该标签的作用是加载映射的,加载方式有如下几种:
  <mappers><mappers>
  1.使用相对于类路径的资源引用,例如:[重点掌握]
  <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
  2.使用映射器接口实现类的完全限定类名,例如:
  <mapper class="org.mybatis.builder.AuthorMapper"/>
  3.将包内的映射器接口实现全部注册为映射器,例如:
  <package name="org.mybatis.builder"/>
  4.使用完全限定资源定位符(URL),例如:
  <mapper url="file:///var/mappers/AuthorMapper.xml"/>

3. Properties标签

  • 实际开发中,习惯将数据源的配置信息单独抽取成一个properties文件,该标签可以加载额外配置的properties文件

20190927001536321.png


4. typeAliases标签

  • ①. 类型别名是为Java 类型设置一个短的名字。原来的类型名称配置如下

20190927001612558.png

  • ②. 配置typeAliases,为com.itheima.domain.User定义别名为user。如果省略alias,mybatis会默认将类名首字母小写后的名称作为别名

20190927001630347.png

  • ③. 当pojo类过多时,还可以通过自动扫描包的形式自定义别名,具体如下
   //mybatis会将所有的com.itheima.domain下的类以首字母变小写为它的包名。
   //比如com.itheima.domain.User 那么它的别名是user
   <typeAliases>
      <package name="com.itheima.domain">
   </typeAliases>
  • ④. 上面我们是自定义的别名,mybatis框架已经为我们设置好的一些常用的类型的别名

20190927001651614.png


<?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>
    <!--通过properties标签加载外部properties文件-->
    <properties resource="jdbc.properties"></properties>
    <!--自定义别名-->
    <typeAliases>
        <typeAlias type="com.itheima.domain.User" alias="user"></typeAlias>
    </typeAliases>
     <!--数据源环境-->
         <environments default="developement">
             <environment id="developement">
                 <transactionManager type="JDBC"></transactionManager>
                 <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="com/itheima/mapper/UserMapper.xml"></mapper>
    </mappers>
</configuration>


























相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
9月前
|
XML Java 数据库连接
|
9月前
|
SQL Java 数据库连接
|
9月前
|
SQL Java 数据库连接
|
9月前
|
SQL Java 数据库连接
|
10月前
|
Java 数据库连接 测试技术
Mybatis-PLUS详解
Mybatis-PLUS详解
191 0
|
9月前
|
XML Java 数据库连接
|
10月前
|
SQL XML 存储
MyBatis(上)
MyBatis(上)
|
11月前
|
SQL XML Java
什么是 Mybatis?
什么是 Mybatis?
54 0
|
SQL Oracle Java