• MyBatis学习之一----基础了解


    1、MyBatis

      数据库有几个表,MyBatis就有多少个mapper.xml文件。可以更方便的对数据库进行增删改查。

      MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。

      

     根据上图来编写demo

      导入依赖:

      

            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.21</version>
            </dependency>
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.2.7</version>
            </dependency>

      首先创建一个SqlMapConfig.xml,可以比喻为一个食品的配方,记录了连接数据库的信息,以及添加相应的mapper.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>
        <!-- 和spring整合后 environments配置将废除 -->
        <environments default="development">
            <environment id="development">
                <!-- 使用jdbc事务管理 -->
                <transactionManager type="JDBC" />
                <!-- 数据库连接池 -->
                <dataSource type="POOLED">
                    <property name="driver" value="com.mysql.jdbc.Driver" />
                    <property name="url"
                              value="jdbc:mysql://localhost:3306/zero?characterEncoding=utf-8" />
                    <property name="username" value="root" />
                    <property name="password" value="123" />
                </dataSource>
            </environment>
        </environments>
    
        <!--配置Mapper的位置-->
        <mappers>
            <mapper resource="mapper.xml"/>
        </mappers>
    </configuration>
    

      测试Mybatis的类

    package com.back.mybatis;
    
    import com.back.pojo.User;
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    import org.junit.Test;
    
    import java.io.InputStream;
    
    /**
     *
     */
    public class MybatisTest {
    
        @Test
        public void testMybatis()throws Exception{
            //sqlSessionFactory
    //        指定一个xml文件位置
            String  resource = "SqlMapConfig.xml";
            //读取文件的时候。默认就是从classes目录开始寻找
            InputStream in = Resources.getResourceAsStream(resource);
    //        通过SqlSessionFactoryBuilder构建sqlSessionFactory
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
    //        从sqlSessionFactory中获取sqlSession
            SqlSession sqlSession = sqlSessionFactory.openSession();
            //根据ID查询用户,
            // 第一个sql参数:指定sql的唯一标识:名称空间+.对应的sql的id的值
            //第二个参数:传入参数
           User user= sqlSession.selectOne("abc.selectUser",25);
            System.out.println(user);
    
        }
    }
    

      首先读取SqlMapConfig.xml文件

      然后通过Resources读取进来。

      创建SqlSessionFactory工厂    //SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);

      从工厂中获取sqlSession来操作数据库,对其进行增删改查

      mapper.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">
    <!--namespace名称空间:当前的xml的唯一标识,只要满足所有mapper中的名称空间不相同即可-->
    <mapper namespace="abc">
        <!--#{id}表示要接收的参数,相当于一个?
            id:当前的sql的唯一标识
            resultType:结果集映射的对象的类型,默认的情况下需要书写对象的全路径
        -->
        <select id="selectUser" resultType="com.back.pojo.User">
            select * from user where id = #{id}
        </select>
    </mapper>
    

      类似于Hibernate,需要创建一个pojo的类

      User,实现其的getter和setter方法。

    大概步骤:1、创建配置文件   SqlMapConfig.xml

         2、获取SqlSessionFactory

         3、获取sqlSession

         4、通过sqlSession执行curd操作(需要提前创建mapper.xml(很多的statement /sql语句))并且在SqlMapConfig.xml中引入新创建的mapper(sql语句)

         5、关闭连接sqlSession.commit()

         6、关闭连接.session.close();

    当User类里的username在数据库中是user_name时,可以使用别名

    以上两种都可以

    2、mybatis中dao层的命名规则

      在mybatis中dao层的接口不再使用***Dao 而是修改成***Mapper

      例如:UserDao,修改成UserMapper

    思考:像userDao中的代码几乎都只有一行

      

        @Override
        public void addUser(User user) {
            sqlSession.insert("user.addUser",user);
        }
    
        @Override
        public void deleteUserById(int id) {
            sqlSession.delete("user.deleteUser",id);
        }
    

      其中的String和id就相当于statement和需要传入进去的参数

      几乎都是固定的格式,那么是否可以不写了呢?

    3、动态代理mapper实现类

      需要名称空间为接口的全路径,某一个方法对应的方法名,要和select的id一致。满足这两个要求就可以实现动态代理的实现类。

      

    <mapper namespace="com.back.dao.UserDaoService">
    
        <select id="queryUserById" resultType="com.back.pojo.User">
           select * from user where id = #{id}
        </select>
    

      就可以不需要接口的实现类,而是直接使用test类来进行。

      Namespace的作用:

      Mapper中Namespace的定义本身是没有限制的,只要不重复即可,但是如果要想使用Mybatis提供的DAO的动态代理,namespace必须为DAO接口的全路径,例如:cn.mybatis.dao.UserDAO.

      总结:

      1)Mapper的namespace必须和mapper接口的全路径一致。

      2)Mapper接口的方法名必须和sql定义的id一致。

      3)Mapper接口中方法的输入参数类型必须和sql定义的parameterType一致(不一定)。

      4)Mapper接口中方法的输出参数类型必须和sql定义的resultType一致。

    public class UserDaoTest {
    
        UserDaoService userDaoService;
    
        SqlSession sqlSession;
        @Before//执行Test方法之前执行
        public void setUp()throws Exception{
            String resouce="SqlMapConfig.xml";
            InputStream inputStream= Resources.getResourceAsStream(resouce);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            sqlSession=sqlSessionFactory.openSession();
            //userDaoService=new UserDaoImpl(sqlSession);
            userDaoService=sqlSession.getMapper(UserDaoService.class);
        }
    

    4、mybatis-config配置,全局配置信息

    configuration 配置

    MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置(settings)和属性(properties)信息。文档的顶层结构如下:

      引入外部文件,properties

      需要在configuration内的最上面。

      4.1properties引入外部文件

    <configuration>
        <!--引入外部的properties文件,resource指定文件所在路径-->
        <properties resource="jdbc.properties"></properties>
        <!-- 和spring整合后 environments配置将废除 -->
        <environments default="development">
            <environment id="development">
                <!-- 使用jdbc事务管理 -->
                <transactionManager type="JDBC" />
                <!-- 数据库连接池 -->
                <dataSource type="POOLED">
                    <property name="driver" value="${driverClass}" />
                    <property name="url"
                              value="${url}" />
                    <property name="username" value="${username}" />
                    <property name="password" value="${password}" />
                </dataSource>
            </environment>
        </environments>
    

      jdbc.properties

      

    driverClass=com.mysql.jdbc.Driver
    url=jdbc:mysql://localhost:3306/zero
    username=root
    password=123

    4.2settings

      这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。下表描述了设置中各项的意图、默认值等。

      4.2.2    mapUnderscoreToCamelCase   是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射。 

      java命名规则:驼峰书写,大小写区分两个单词的界限。

      数据库的经典命名规则:两个单词之间使用下划线分割。user_name(因为有的数据库是不区分大小写的,所以在数据库中使用驼峰是没有意义的)

      开启驼峰匹配,就相当于去掉数据库中的下划线,然后再与java中的属性名进行对应。

      

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

      4.2.3  typeAliases

      类型别名是为 Java 类型设置一个短的名字。它只和 XML 配置有关,存在的意义仅在于用来减少类完全限定名的冗余。

    <typeAliases>
      <typeAlias alias="Author" type="domain.blog.Author"/>
      <typeAlias alias="Blog" type="domain.blog.Blog"/>
      <typeAlias alias="Comment" type="domain.blog.Comment"/>
      <typeAlias alias="Post" type="domain.blog.Post"/>
      <typeAlias alias="Section" type="domain.blog.Section"/>
      <typeAlias alias="Tag" type="domain.blog.Tag"/>
    </typeAliases>

      type指定类的全路径;alias是别名,简写。

      定义一个别名:

      

        <typeAliases>
            <typeAlias type="com.back.pojo.User" alias="User"></typeAlias>
        </typeAliases>

      为一个pojo类指定一个别名或者简称。然后再mapper.xml中可以直接书写简称即可。

      

        <select id="queryUserById" resultType="User">
           select * from user where id = #{id}
        </select>

      缺点:需要为每一个类都定义一个类型别名。书写麻烦

      

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

      

    <typeAliases>
      <package name="domain.blog"/>
    </typeAliases>

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

     简称就是类的名字,并且不区分大小写。

      所以不管写user还是User都可以,但是建议正常书写类的名字。

      mybatis已经为普通的Java类型內建了许多相应的类型别名。它们都是大小写不敏感的。需要注意的是由于重载原始类型的名称所做的特殊处理。所以基本类型不需要书写全路径。

    4.3   environments

      

     1     <!-- 和spring整合后 environments配置将废除 -->
     2     <environments default="development">
     3         <environment id="development">
     4             <!-- 使用jdbc事务管理 -->
     5             <transactionManager type="JDBC" />
     6             <!-- 数据库连接池 -->
     7             <dataSource type="POOLED">
     8                 <property name="driver" value="${driverClass}" />
     9                 <property name="url"
    10                           value="${url}" />
    11                 <property name="username" value="${username}" />
    12                 <property name="password" value="${password}" />
    13             </dataSource>
    14         </environment>
    15     </environments>

      mybatis允许配置多个连接环境,default是选择加载哪个环境;

      Mybatis允许配置多个环境,比如说开发环境、测试环境、生成环境,但是在构建SqlSessionFactory时只能选择一个。虽然这种方式也可以做到很方便的分离多个环境,但是在实际使用场景下 我们都是更多的使用Spring来管理数据源,做环境的分离。

     

    4.4、mappers映射器

      引入外部的,局部的mappers.xml。告诉MyBatis到哪里去找到这些语句。Java在自动查找这方面没有提供

      

    <mappers>
      <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
      <mapper resource="org/mybatis/builder/BlogMapper.xml"/>
      <mapper resource="org/mybatis/builder/PostMapper.xml"/>
    </mappers>

      resource:指定mapper所在文件路径

      mapper中的url

      

    <mappers>
      <mapper url="file:///var/mappers/AuthorMapper.xml"/>
      <mapper url="file:///var/mappers/BlogMapper.xml"/>
      <mapper url="file:///var/mappers/PostMapper.xml"/>
    </mappers>

      从硬盘上找到xml文件,这种方式基本不用。因为只能在该硬盘上,被定死了。

      

      使用mapper接口类的全路径。

      

    <!-- Using mapper interface classes -->
    <mappers>
      <mapper class="org.mybatis.builder.AuthorMapper"/>
      <mapper class="org.mybatis.builder.BlogMapper"/>
      <mapper class="org.mybatis.builder.PostMapper"/>
    </mappers>
        <mappers>
            <mapper resource="mapper.xml"/>
            <mapper resource="user.xml"/>
            <!--如果使用class方式映射的时候,要求:
            1、mapper.xml和文件的名字和mapper接口的名字一致
            2、要求mapper.xml文件和mapper接口类在一个目录下
            -->
            <mapper class="com.back.dao.UserDaoService"/>
        </mappers>
    

      但是有两个要求,否则是找不到mapper.xml文件的。

    如果接口比较多,配置文件就需要配置多个。

      

      注册所有的接口在一个目录下,

       

    <!-- Register all interfaces in a package as mappers -->
    <mappers>
      <package name="com.mybatis.mapper"/>
    </mappers>

      扫描指定包下面所有的接口,要求:1、要求mapper.xml文件的名字和mapper接口的名字,一致  2、要求mapper.xml文件和mapper接口类在一个目录下

      但是就目前的方法来看还是没有实现xml和java代码分离。需要spring整合后来做处理。

    4.5 mybatis-config.xml整理

      1、properties标签-引入外部properties文件。在环境的位置可以使用${key}直接获取properties中的内容。

      2、setting:开启驼峰匹配。

        从数据的经典命名规则到java经典命名规则的映射;把数据库中的下划线去掉和java中的内容进行映射。

      3、typealiases:

     5、select和insert语句

      如果是insert、update、delete操作,可以直接在方法上定义返回类型Integer。来接受一条sql语句改变的数据库的行数。

      

        /**
         * 增加用户
         */
        public Integer addUser(User user);

      测试代码中
      Integer s=userDaoService.addUser(user1);
      s即为数据库中收到影响的行数

      

        如果想知道addUser的userID是多少可以使用主键回写功能。

      

        <insert id="addUser" useGeneratedKeys="true" keyProperty="id" keyColumn="id">
            INSERT INTO user (id, username, birthday, sex, address) VALUES (NULL, #{username}, NOW(), #{sex}, #{address});
        </insert>

      

    useGeneratedKeys:是否开启主键回写
    keyProperty:java对象主键的属性名
    keyColumn:数据库主键对应的字段的名字
    代码
        @Test
        public void TestAddUser(){
            User user1=new User();
            user1.setAddress("北京");
            user1.setUsername("王强");
            user1.setSex(2);
            userDaoService.addUser(user1);
            sqlSession.commit();
            System.out.println(user1.getId());
        }

     6、#和$

      占位符只能替代指定参数或要传入的值,不能替代表名或者SQL中的关键字。否则会报PersistenceException。

      $属于SQL字符串的拼接。#是指占位符的形式。

      $在取值的时候使用value表示传入的参数的值。所以mapper.xml中

      

        <!--$在取值的时候使用value表示传入的参数的值-->
        <select id="queryUserByTableName" resultType="User">
            select * from ${value}
        </select>

    而如果写

      

        <!--$在取值的时候使用value表示传入的参数的值-->
        <select id="queryUserByTableName" resultType="User">
            select * from ${tableName}
        </select>

     是会报错的。而且value这种方式不建议书写。因为如果后面有where  value=${value}就无法识别谁代表谁

        <!--在取值的时候使用@Param("tableName")为当前的参数指定一个名字-->
        <select id="queryUserById" resultType="User">
               select * from user where id = #{id}
        </select>
        public List<User> queryUserByTableName(@Param("tableName") String tableName);

     7、mybatis传入多个参数parameterType传入参数

      可以使用#{}进行接受一个变量,可以${}接受一个变量

      如果${}没有指定参数名(在方法的参数列表中加入@Param)可以使用${value}表示传递过来的参数

      使用#号的时候是与参数名无关的

       1、使用$去传递参数的时候,使用@Param把参数指定一个名字

       2、如果传入多个参数的时候,使用@Param,一定需要使用为每一个参数都去指定名字

      

        <select id="queryUserById" resultType="User">
               select * from user where id = #{idsfsdafd}
        </select>
    

      传入多个参数

    <!--$在取值的时候使用value表示传入的参数的值
    如果传递多个参数,默认情况下是取不到值的
    1、使用0、1等一些数字表示传入的参数的顺序并且取值
    2、使用param+数字表示传入参数的次序,数字从1开始。
    3、使用@param为参数起名字
    -->
    <select id="queryUserByTableName" resultType="User">
    select * from ${tableName} where username=#{username} and password=#{password}
    </select>

    JAVA代码

      

        public User login(@Param("username"))String username,@Param("password") String password);

    推荐使用第三种

    8、#{}与${}的区别

      #是占位符

      $是字符串的拼接

      #可以随便写(和参数名无关)

      $使用value取值,或者使用@Param指定一个名字再去取值

    在Mybatis的mapper中,参数传递有2种方式,一种是#{}另一种是${},两者有着很大的区别。

      #{}实现的 sql语句的预处理参数。之后执行sql中?号代替,使用时不需要关注数据类型,Mybatis自动实现数据类型的转换。并且可以防止SQL注入。

      ${}实现是sql语句的直接拼接,不做数据类型的转换,需要自行判断数据类型。不能防止SQL注入。

      

    1、$字符串拼接,#参数占位相当于jdbc中的?

    2、$不能够防止sql注入,#可以防止sql注入的。

    3、$可以替换sql语句任何一个内容,#只能替换参数

    4、$如果操作字符串,需要在sql中使用单引号。#不需要(不需要判断数据类型)

     模糊查询

    select * from user where name like '%张%';

     分别用#和$完成一次

    #

        <select id="queryUserLikeName1" resultType="User">
            select * from user where username like #{name}
        </select>
        @Test
        public void queryUserLikeName1(){
            List<User> users=userDaoService.queryUserLikeName1("%小%");
            for(User user:users){
                System.out.println(user);
            }
        }

    $

        <select id="queryUserLikeName1" resultType="User">
            select * from user where username like '%${name}%'
        </select>
    
        @Test
        public void queryUserLikeName1(){
            List<User> users=userDaoService.queryUserLikeName1("明");
            for(User user:users){
                System.out.println(user);
            }
        }
    

      #和$一个是占位符一个是字符串本身的链接操作

      

    字符串的拼接操作不能防止SQL注入

      

     那么什么时候用#什么时候用$?

    不考虑SQL注入的时候使用$

    如果传入的数据,不是sql中的参数的时候,不能够使用#。

    通常使用#。

     选择获取参数的时候,首要选择#的方式(1、可以防止SQL注入 2、可以不用考虑数据类型,简化书写3、sql是参数化的SQL,也是预编译的SQL,速度会快一些)

     当#用不了的时候使用$。例如:sql需要改变的是内容是表名的时候,就可使用$方式。

     9、ResultMap是Mybatis中最重要最强大的元素,使用它可以解决两大问题:

      POJO属性名和表结构字段名不一致的问题(有些情况下也不是标准的驼峰格式)

       完成高级查询,比如说,一对一、一对多、多对多。

      解决表字段名和属性不一致的问题有两种方法:  

      1、如果是驼峰似的命名规则可以在Mybatis配置文件中设置<setting name="mapUnderscoreToCamelCase" value="true"/>解决

      2、使用ResultMap解决。

      

        <!--id:唯一标识
            type:结果集对应的java类型
            autoMapping:完成数据库字段名到属性名的自动映射,并且支持驼峰规则
        -->
        <resultMap id="userResultMap" type="User" autoMapping="true">
            <!--完成数据库字段名到java对象类型的属性的映射
                id:指定主键的,建议不要省略
                column:数据中字段的名字
                property:java中字段的名字
            -->
            <id column="id" property="id"/>
            <!--result完成部署主键的字段的映射-->
            <result column="user_name" property="username"/>
        </resultMap>

      那么怎么给别人使用呢?

      将

        <select id="queryUserLikeName1" resultType="User">
            select * from user where username like '%${name}%'
        </select>

    改为

      

        <select id="queryUserLikeName1" resultMap="userResultMap">
            select * from user where username like '%${name}%'
        </select>

     10、SQL片段

      在java代码中会将公用的一些代码提取出来需要的地方直接调用方法即可,在Mybatis也是有类似的概念,那就是SQL片段。

      在Mybatis中使用<sql id="">标签定义SQL片段,在需要的地方通过<include refid=""/>引用,例如:

      

        <sql id="selectUser">
            select * from user
        </sql>
    
        <select id="queryAllUser" resultType="com.back.pojo.User">
           <include refid="selectUser"></include> where .......
        </select>

      如果我想让其他的mapper.xml文件也使用怎么办。

      可以在外部创建一个xml文件,sql.xml

      不和任何接口映射,只是引入进来。

      sqlMapper.xl文件内容

      

    <?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="abc">
        <sql id="selectAllUser">
            select * from user
        </sql>
    </mapper>
    

      需要的时候

        <select id="queryAllUser" resultType="com.back.pojo.User">
           <include refid="abc.selectAllUser"></include>
        </select>

     不需要在引入进来,只需要在sqlMapperConfig.xml中引入进来即可。

      

        <!--配置Mapper的位置-->
        <mappers>
            <mapper resource="sqlMapper.xml"/>
            <mapper resource="mapper.xml"/>
            <mapper resource="user.xml"/>
            <!--如果使用class方式映射的时候,要求:
            1、mapper.xml和文件的名字和mapper接口的名字一致
            2、要求mapper.xml文件和mapper接口类在一个目录下
            -->
            <!--<mapper class="com.back.dao.UserDaoService"/>-->
        </mappers>
    

      

      

    坚持就是胜利
  • 相关阅读:
    SQL TOP 分页
    C# Word 打印
    Oracle 11g 卸载日志
    用 16G 内存存放 30亿数据(Java Map)转载
    HTMLDivElement.prototype
    在TOMCAT8.5使用 JOSSO 单点登录(Agent 端)
    德哥的PostgreSQL私房菜
    Object-relational impedance mismatch (转载)
    Java性能最后一个领域:去除垃圾回收器
    我们为什么选择Vue.js而不是React(转载)
  • 原文地址:https://www.cnblogs.com/xiaotieblog/p/8276816.html
Copyright © 2020-2023  润新知