zoukankan      html  css  js  c++  java
  • 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>
    

      

      

    坚持就是胜利
  • 相关阅读:
    Lucene in action 笔记 case study
    关于Restful Web Service的一些理解
    Lucene in action 笔记 analysis篇
    Lucene in action 笔记 index篇
    Lucene in action 笔记 term vector
    Lucene in action 笔记 search篇
    博客园开博记录
    数论(算法概述)
    DIV, IFRAME, Select, Span标签入门
    记一个较困难的SharePoint性能问题的分析和解决
  • 原文地址:https://www.cnblogs.com/xiaotieblog/p/8276816.html
Copyright © 2011-2022 走看看