zoukankan      html  css  js  c++  java
  • MyBatis 学习(一)

    MyBatis 学习(一)

    1、什么是MyBatis? MyBatis有什么作用?

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

    2、如何获得MyBatis?

    3、持久化:

    • (数据持久化)是将程序的数据在持久状态和瞬时状态转化的过程
    • 内存:断电即失
    • 数据库(jdbc),io文件持久化
    • 生活:冷藏食品。。
    • 为什么需要持久化:有些对象不能让他丢掉。需要持久化操作
    4、持久层:
    • Dao层、Service层、Controller层
    • 完成持久化工作的代码块
    • 层的界限十分明显。

    二、第一个MyBatis程序

    思路:搭建环境-》导入MyBatis依赖--》编码--》测试!

    0、创建Maven项目导入mybatis相关依赖

    <!--导入依赖-->
        <dependencies>
            <dependency>
                <!--mysql驱动-->
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.47</version>
            </dependency>
            <!--mybatis-->
            <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.4.6</version>
            </dependency>
            <!--junit测试-->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.12</version>
                <scope>test</scope>
            </dependency>
        </dependencies>
    

    1、在resource资源目录创建mybatis-config.xml :注册mysql驱动连接数据库

    <!--configuration核心配置文件-->
    <configuration>
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <!--注册mysql驱动-->
                    <property name="driver" value="com.mysql.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=ture&amp;useUnicode=ture&amp;characterEncoding=UTF-8"/>
                    <property name="username" value="root"/>
                    <property name="password" value="root"/>
                </dataSource>
            </environment>
        </environments>
    
    </configuration>
    

    2、创建mybatisUtils工具类:通过构建 SqlSessionFactory从而获取SQLSession

    //2、构建 SqlSessionFactory从而获取SQLSession(工厂类-》商品)
    public class MyBatisUtils {
    
        private static  SqlSessionFactory sqlSessionFactory;
    
        // SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得。
        // 而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先配置的 Configuration 实例来构建出 SqlSessionFactory 实例
        static {
            try {
                //获取SqlSqlSessionFactory 对象
                String resource = "mybatis-config.xml";
                InputStream inputStream = Resources.getResourceAsStream(resource);
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        /*有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例。
         SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。
         则可以通过 SqlSession 实例来直接执行已映射的 SQL 语句*/
        public static SqlSession getSqlSession() {
    
          return sqlSessionFactory.openSession();
        }
    
    }
    

    3、User实体类:与数据表的字段一致

    //3、与数据库对应的实体类
    public class User {
        private int id;
        private String username;
        private int password;
        ........
    }  
    

    4、业务行为接口 UserDao

    public interface UserDao {
        List<User> getUserList();
    }
    
    

    5、通过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">
    <!--5、通过xml使用SqlSession-->
    <!--namespace绑定一个对应的UseDao/Mapper接口-->
    <mapper namespace="com.study.dao.UserDao">
        <!--select查询语句:id:接口中的方法名;resultType:返回结果类型(实体类的全限定名)-->
        <select id="getUserList" resultType="com.study.pojo.User">
            select  * from mybatis.user
        </select>
    </mapper>
    
    
    ===================================================================
    //原来的JDBC写法对比xml
    public class UserDaoImpl  implements UserDao{
    
        @Override
        public List<User> getUserList() {
           //连接数据库驱动
            //sql语句
            String str ="select  * from mybatis.user" ;
            // 返回 Resultset 结果集
           return  .....;
        }
    }
    

    6、测试类:

    public class UserDaoTest {
        @Test
        public  void test(){
            //第一步:获取SqlSession对象
            SqlSession sqlSession = MyBatisUtils.getSqlSession();
             //第二步:执行SQL(如何拿到Sql,获取接口的class对象)
            UserDao userDao = sqlSession.getMapper(UserDao.class);
            //获得UserList集合
            List<User> userList = userDao.getUserList();
            //遍历输出
            for (User user : userList) {
                System.out.println(user);
            }
    
            //关闭SQLSession
            sqlSession.close();
    
        }
    }
    

    7、在运行mybatis是出现的错误及解决方法

    mybatis报错2
    • 解决:原因是在构建SqlSession失败,在config.xml中找到没有将配置好的Mapper.xml添加到核心配置文件中去

      即在configuration加入下面语句:

      <!--每一个Mapper.xml都需要在mybatis核心配置文件中注册!-->
      <mappers>
           <mapper resource="com/study/dao/UserMapper.xml"/>
      </mappers>
      

    问题二:

    image-20210310233558372

    解决:这是运行时没有发现创建在java下的xml文件,则需要在Maven配置(最好在父子工程下的poml文件都配置)

    <!--maven由于他的约定大于配置,我们之后再写配置,无法被导出或者生效的问题-->
        <!--在build中配置resource,来防止我们资源导出失败的问题-->
        <build>
            <resources>
                <resource>
                    <directory>src/main/resources</directory>
                    <includes>
                        <include>**/*.properties</include>
                        <include>**/*.xml</include>
                    </includes>
                    <filtering>true</filtering>
                </resource>
                <resource>
                    <directory>src/main/java</directory>
                    <includes>
                        <include>**/*.properties</include>
                        <include>**/*.xml</include>
                    </includes>
                    <filtering>true</filtering>
                </resource>
           </resources>
    

    问题三:

    image-20210310234107527

    解决:这个问题解决了好长时间是由于粗心编码错误问题(公共变量的定义),因为SQLSessionFactory在外面已经定义,里面无需再定义,否侧拿到到的一直是null值

    image-20210310234402954

    问题四:【true】

    image-20210310234708092

    成功运行:

    image-20210310235441070

    问题五

    IDEA打包是遇到的错误(package:主要是为了看清楚Taget目录下有多少文件可以编译运行)

    image-20210310234847635

    image-20210310235154217

    • 在使用打包是应该在pom中添加maven在

      //build标签中
      <!--package打包插件-->
              <plugins>
                  <plugin>
                      <groupId>org.apache.maven.plugins</groupId>
                      <artifactId>maven-surefire-plugin</artifactId>
                      <version>2.4.2</version>
                      <configuration>
                          <skipTests>true</skipTests>
                      </configuration>
                  </plugin>
              </plugins>
      
      <properties>
              <!--Maven 打包时有标题中警告,需要在pom.xml文件中添加-->
              <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
       </properties>
      

    三、基本理论

    1、SqlSessionFactoryBuilder
    • 这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。

      因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)。

    • 可以重用 SqlSessionFactoryBuilder 来创建多个 SqlSessionFactory 实例,但最好还是不要一直保留着它,以保证所有的 XML 解析资源可以被释放给更重要的事情。

    2、SqlSessionFactory
    • sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
      
    • SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。

    • 使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次。因此 SqlSessionFactory 的最佳作用域是应用作用域。 有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。

    3、SqlSession
    • SqlSession sqlSession = sqlSessionFactory.openSession();
      
    • 每个线程都应该有它自己的 SqlSession 实例。

    • SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域

    • 绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。 也绝不能将 SqlSession 实例的引用放在任何类型的托管作用域中,这个关闭操作很重要,为了确保每次都能执行关闭操作,你应该把这个关闭操作放到 finally 块中。

    四、CRUD

    1、namespace
    • 命名空间的作用有两个,一个是利用更长的全限定名来将不同的语句隔离开来,同时也实现了你上面见到的接口绑定

    • 长远来看,只要将命名空间置于合适的 Java 包命名空间之中,你的代码会变得更加整洁,也有利于你更方便地使用 MyBatis。

    • 命名解析:

      • 全限定名(比如 “com.mypackage.MyMapper.selectAllThings)将被直接用于查找及使用。
    • 注:namespace的命名就是dao/mapper接口的全限定名

    2、Select 查询
    • id:就是对应的namespace(接口)中的方法名;
    • resultType:Sql语句执行的返回值类型;
    • parameterType:传参的类型;

    UserMapper接口:所要实现的功能

    • /*4、功能接口*/
      public interface UserDaoMapper {
          //查询所有用户
          List<User> getUserList();
          //通过id查询用户
          User getUserById(int id);
          //添加用户
          boolean insertUser(User user);
          //修改用户
          boolean updataUser(User user);
          //删除用户
          boolean deleteUser(int id);
      }
      

    UserMapper.xml:查询语句(实现接口)

    •   <!--select查询语句:id:接口中的方法名;resultType:返回结果类型(实体类的全限定名)-->
          <select id="getUserList" resultType="com.study.pojo.User">
              select  * from mybatis.user
          </select>
          <!--通过id查询用户-->
          <select id="getUserById"  parameterType="int" resultType="com.study.pojo.User" >
              select * from mybatis.user where id = #{id}
          </select>
      

    UserTest测试:

    •  /*通过id查询用户*/
          @Test
          public void getUserById(){
              //1.获取sqlsession
              SqlSession sqlSession = MyBatisUtils.getSqlSession();
              //获得Mapper对象(获得接口)
              UserDaoMapper mapper = sqlSession.getMapper(UserDaoMapper.class);
              //执行sql并返回结果
              User user = mapper.getUserById(1);
              System.out.println(user);
      
              //关闭
              sqlSession.close();
          }
      
    3、Insert 插入

    UserMapper.xml:查询语句(实现接口)

    •  <!--添加用户(User对象的属性可以直接取出来)-->
          <insert id="insertUser" parameterType="com.study.pojo.User" >
              insert  into mybatis.user (id,username,password) values (#{id},#{username},#{password})
          </insert>
      

    UserTest测试:

    •  /*增删改都需要提交事务*/
          /*添加用户*/
          @Test
          public void insertUser(){
              SqlSession sqlSession = MyBatisUtils.getSqlSession();
      
              UserDaoMapper mapper = sqlSession.getMapper(UserDaoMapper.class);
              boolean user = mapper.insertUser(new User(6,"lijing2",2444));
              System.out.println(user);
      
              sqlSession.commit();
              sqlSession.close();
          }
      
    4、Delete 删除

    UserMapper.xml:查询语句(实现接口)

    • <!--删除用户-->
          <delete id="deleteUser" parameterType="int">
              delete from  mybatis.user where id=#{id}
          </delete>
      

    UserTest测试:

    •   /*删除用户*/
          @Test
          public void deleteUser(){
              SqlSession sqlSession = MyBatisUtils.getSqlSession();
              UserDaoMapper mapper = sqlSession.getMapper(UserDaoMapper.class);
      
              boolean user = mapper.deleteUser(6);
              System.out.println(user);
      
              sqlSession.commit();
              sqlSession.close();
      
          }
      
    5、Update 修改

    UserMapper.xml:查询语句(实现接口)

    •  <!--通过id修改用户-->
          <update id="updataUser" parameterType="com.study.pojo.User" >
              update mybatis.user set username = #{username},password= #{password} where id =#{id}
          </update>
      

    UserTest测试:

    •  /*更新用户*/
          @Test
          public  void updataUser(){
              SqlSession sqlSession = MyBatisUtils.getSqlSession();
      
              UserDaoMapper mapper = sqlSession.getMapper(UserDaoMapper.class);
              boolean user = mapper.updataUser(new User(5, "哈哈", 00000000));
              System.out.println(user);
      
              sqlSession.commit();
              sqlSession.close();
      
          }
      

    注: 增删改都需要提交事务commit,数据库才会更新。

    6、万能的Map

    假设,我们的实体类有很多属性,或者数据库中的表,字段或者参数过多,就应当考虑使用Map!

    • 使用map作为参数传递是不需要知道数据有什么子段。

    • 在Sql语句编写是字段可以自定义不必和数据的字段一致。

    • //通过map查询用户
          boolean addUserMap(Map<String,Object> map);
      
      <!--使用map添加用户(不用静User的所有属性写出来也不用new User)-->
          <insert id="addUserMap" parameterType="map" >
              insert into mybatis.user (id,username,password) values (#{userid},#{name},#{pwd})
          </insert>
      
       /*通过map添加用户*/
          @Test
          public  void addUserMap(){
              SqlSession sqlSession = MyBatisUtils.getSqlSession();
              UserDaoMapper mapper = sqlSession.getMapper(UserDaoMapper.class);
      
              /*创建Map对象*/
              Map<String, Object> map = new HashMap();
              map.put("userid",6);
              map.put("name","opop");
              map.put("pwd",88888);
      
              boolean userMap = mapper.addUserMap(map);
              System.out.println(userMap);
      
              sqlSession.commit();
              sqlSession.close();
          }
      
    • Map传递参数,直接在sql中取出key即可 【parameterType="map"】

    • 而对象传递参数,直接在sql中取对象的属性即可【parameterType="类的全限定名"】

    • 只有一个基本类型参数的情况下,可以直接在sql取到!

    • 多个参数用Map,或者注解!

    7、Like模糊查询
    • 第一种:java代码执行的时候,传递通配符%%

      List<User> userLike = mapper.getUserLike("%哈%");
      
      <select id="getUserLike" resultType="com.study.pojo.User">
      select  * from mybatis.user where  username LIKE #{value}
      </select>
      
      
    • 第二种:在SQL拼接中使用通配符

      <select id="getUserLike" resultType="com.study.pojo.User">
              select  * from mybatis.user where  username LIKE  "%"#{value}"%"
       </select>
      
      List<User> userLike = mapper.getUserLike("哈");
      

    五、配置解析

    • MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息

    环境配置:

    • MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中, 现实情况下有多种理由需要这么做。
    • 不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。
    • 事务管理器(transactionManager)
      • 在 MyBatis 中有两种类型的事务管理器(也就是 type="[JDBC|MANAGED]"):
      • JDBC – 这个配置直接使用了 JDBC 的提交和回滚设施,它依赖从数据源获得的连接来管理事务作用域。
      • MANAGED – 这个配置几乎没做什么。默认情况下它会关闭连接。然而一些容器并不希望连接被关闭,因此需要将 closeConnection 属性设置为 false 来阻止默认的关闭行为。
    • 连接池:POOLED
    • 如果你想连接两个数据库,就需要创建两个 SqlSessionFactory 实例,每个数据库对应一个
    configuration(配置)
    properties(属性)
    settings(设置)
    typeAliases(类型别名)
    environments(环境配置)
    environment(环境变量)
    transactionManager(事务管理器)
    dataSource(数据源)
    databaseIdProvider(数据库厂商标识)
    mappers(映射器)
    
    1、属性设置之配置优化
    • 属性(properties)

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

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

    • 1、db.properties

    driver=com.mysql.jdbc.Driver
    url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8
    username=root
    password=root
    
    • 2、在配置文件中引入

    • 注:配置文件中引入要注意其顺序

    • image-20210313231142467
      <!--1、configuration核心配置文件-->
      <configuration>
          <!--引入外部配置文件-->
           <properties resource="db.properties"/>
          <!--默认环境-->
          <environments default="development">
              <environment id="development">
                  <transactionManager type="JDBC"/>
                  <!--连接的数据源-->
                  <dataSource type="POOLED">
                      <!--注册mysql驱动-->
                      <property name="driver" value="${driver}"/>
                      <property name="url" value="${url}"/>
                      <property name="username" value="${username}"/>
                      <property name="password" value="${password}"/>
                  </dataSource>
              </environment>
          </environments>
          <!--每一个Mapper.xml都需要在Mybatis核心配置文件注册!-->
          <mappers>
              <mapper resource="com/study/dao/UserMapper.xml"/>
          </mappers>
      </configuration>
      
      
      或:这样的写法
      <properties resource="db.properties">
              <property name="username" value="root"/>
              <property name="password" value="root"/>
      </properties>
      
    • 可以直接引入外部文件

    • 可以在其中增加一些属性配置】

    • 如果两个文件有同一个字段,优先使用外部引用的文件!

    2、类型别名(typeAliases)
    • 类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写

    • 我们在xml编写sql时需要指定resultType就是全限定类名这是就可以简化

    • 第一种方式:

       <!--简化全限定类名,起别名-->
          <typeAliases>
              <typeAlias type="com.study.pojo.User" alias="User"/>
          </typeAliases>
      
      <select id="getUserList" resultType="User">
              select  * from mybatis.user
       </select>
      
      
    • 第二种:也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean,比如:

      <!--扫描包名,会默认使用 Bean 的首字母小写的非限定类名来作为它的别名-->
          <typeAliases>
              <package name="com.study.pojo"/>
          </typeAliases>
      
      <select id="getUserList" resultType="user">
              select  * from mybatis.user
       </select>
      

      每一个在包com.study.pojo 中的 Java Bean,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。

      • 在实体类比较少的时候,使用第一种方式
      • 如果实体类非常多的情况下,建议使用第二种。
      • 第一种可以diy别名,第二种需要diy的则需加在类上加注解@@Alias()
    @Alias("UserPoJo")
    public class User {
        private int id;
        private String username;
        private int password;
    ......
    }
    
    <!--扫描包名,会默认使用 Bean 的首字母小写的非限定类名来作为它的别名-->
        <typeAliases>
            <package name="com.study.pojo"/>
        </typeAliases>
    
    
    <select id="getUserList" resultType="UserPoJo">
            select  * from mybatis.user
        </select>
    
    3设置(settings)
    • 这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为
    设置名 描述 有效值 默认值
    cacheEnabled 全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。 true | false true
    lazyLoadingEnabled 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。 true | false false
    useGeneratedKeys 允许 JDBC 支持自动生成主键,需要数据库驱动支持。如果设置为 true,将强制使用自动生成主键。 true | false False
    mapUnderscoreToCamelCase 是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。 true | false False
    image-20210316223504656
    4、其他配置

    typeHandlers(类型处理器)
    objectFactory(对象工厂)
    plugins(插件)

    • maven:mybatis-generator_core
    • mybatis-plus
    • 通用mapper
    5、映射器(Mapper)
    • 你可以使用相对于类路径的资源引用,或完全限定资源定位符(包括 file:/// 形式的 URL),或类名和包名等。
    • MapperRegistry:注册绑定我们的Mapper文件

    方式一:

    • <!--每一个Mapper.xml都需要在mybatis核心配置文件中注册!-->
      <mappers>
           <mapper resource="com/study/dao/UserMapper.xml"/>
      </mappers>
      

    方式二:使用class文件绑定注册

    • <!--每一个Mapper.xml都需要在mybatis核心配置文件中注册!-->
      <mappers>
           <mapper class="com.study.dao.UserMapper"/>
      </mappers>
      
    • 注意点:

      • 1、接口和他的Mapper配置文件必须同名!
      • 2、接口和他的Mapper配置文件必须在同一个包下!

    方式三:使用扫描包进行注入绑定

    • <mappers>
              <package name="com.study.dao"/>
       </mappers>
      

    注意点:

    • 1、接口和他的Mapper配置文件必须同名!
    • 2、接口和他的Mapper配置文件必须在同一个包下!
    6、作用域(Scope)和生命周期

    SqlSessionFactoryBuilder

    • 这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。

      因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)。

    SqlSessionFactory

    • 使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次。因此 SqlSessionFactory 的最佳作用域是应用作用域

    SqlSession

    • SqlSession sqlSession = sqlSessionFactory.openSession();
      
    • 每个线程都应该有它自己的 SqlSession 实例。

    • SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域

    image-20210316231958303image-20210316233952132

    image-20210316234032214
  • 相关阅读:
    第12组 Beta冲刺 (3/5)
    第12组 Beta冲刺 (2/5)
    第12组 Beta冲刺 (1/5)
    每周小结(1/3)
    第03组 Beta冲刺 (4/5)
    第03组 Beta冲刺 (3/5)
    第03组 Beta冲刺 (1/5)
    第03组 Alpha冲刺 总结
    第03组 Alpha冲刺 (6/6)
    第03组 Alpha冲刺 (4/6)
  • 原文地址:https://www.cnblogs.com/yyb6/p/14590075.html
Copyright © 2011-2022 走看看