快速入门MyBatis

1. 三层架构

  1. 界面层:和用户交互,调用业务逻辑层进行功能处理,显示请求的处理结果

  2. 业务逻辑层:接收传递的数据,完成业务逻辑;向上为界面层提供处理结果,向下问数据访问层要数据

  3. 数据访问层:和数据库交互,向上提供数据

    不可跨层

2.常用的框架SSM

  1. Spring:是整合其他框架的框架,核心是IOC(控制翻转)和AOP(面向切面编程),它由20多个模块构成(大佬)。
  2. SpringMVC:Spring家族的一员,专门用来优化控制器(Servlet)的,提供了极简的数据提交、数据携带、页面跳转等功能。
  3. MyBatis:是持久化层(就是数据访问层)的一个框架,用来进行数据库访问的优化,专注Sql语句,极简化JDBC的访问。

3.什么是框架

​ 它是一个半成品软件,将所有的公共的、重复的功能解决掉,帮助程序快速高效的进行开发,它是可复用的,可扩展的。

4.MyBatis框架

  1. 原是Apache的开源项目iBatis,2010迁移到Google code 改名为MyBatis,2013年迁移Git是基于Java的持久层框架。

  2. 主要解决的问题:

    减轻JDBC的复杂性,直接使用java对象表示结果数据,让开发者更专注SQL的处理,其他工作由MyBatis完成。

5.Mybatis框架结构

在这里插入图片描述

6.添加框架步骤

  1. )添加依赖

  2. )添加配置文件

    具体步骤:

    • 新建库、表
    • 新建maven项目,quickstart模板
    • 修改目录,添加缺失目录和属性
    • 修改pom.xml,添加Mybatis依赖、mysql依赖、添加资源文件指定
    • 在idear中添加数据库的可视化
    • 添加jdbc.properties数据库配置文件
    • 添加SqlMapConfig.xml文件(MYbatis的核心配置文件)
    • 添加完成表增删改查的功能配置文件StudentMapper.xml
    • 创建测试类 测试

7.代码实现

  1. 配置MyBatis核心配置文件

    <?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>
        <!--读取属性文件jdbc.properties
        resource:从resource资源目录下找对应文件加载
        url:绝对路径D:\cd...-->
        <properties resource="jdbc.properties"></properties>
    
    <!--    配置数据库的环境变量(连接配置)-->
        <environments default="development">
    <!--        开发时在公司使用的-->
            <environment id="development">
    <!--           配置事务管理器
                    type:事务管理的方式
                        JDBC:事务的控制交给程序员处理
                        MANAGED: 由容器(Spring)来管理事务-->
                <transactionManager type="JDBC"></transactionManager>
    <!--            配置数据源
                    type:指定不同的配置方式
                       JNDI:java命名目录接口,在服务器端进行数据库连接池的管理
                       POOLED:使用数据库连接池
                       UNPOOLED:不使用数据库连接池-->
                <dataSource type="POOLED">
    <!--            配置数据库的基本参数
                    private String driver;
                    private String url;
                    private String username;
                    private String password;-->
                    <property name="driver" value="${jdbc.driverClassName}"/>
                    <property name="url" value="${jdbc.url}"/>
                    <property name="username" value="${jdbc.username}"/>
                    <property name="password" value="${jdbc.password}"/>
                </dataSource>
            </environment>
    <!--        回家的配置,直接改environments default来切换-->
    <!--        <environment id="home">-->
    <!--            <transactionManager type=""></transactionManager>-->
    <!--            <dataSource type=""></dataSource>-->
    <!--        </environment>-->
        </environments>
    <!--    注册mapper.xml文件-->
        <mappers>
            <mapper resource="StudentMapper.xml"></mapper>
        </mappers>
    </configuration>
    
  2. 配置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:指定命名空间(相当于包名)用来区
    分不同mapper.xml文件中相同的id属性-->
    <mapper namespace="jv">
    <!-- 查询,
    resultType:指定查询返回的结果集的类型,如果是集合则必须是泛型的类型
    parameterType:如果有参数这通过它来指定参数的类型
    -->
    <!--    查询所有学生--> 
        <select id="getAll" resultType="com.jv.pojo.Student">
            select id,name,email,age from student;
        </select>
        <select id="getByid" parameterType="int" resultType="com.jv.pojo.Student">
            select id,name,email,age from student where id =#{id} ;
        </select>
    <!--    按名称模糊查询-->
        <select id="getByname" parameterType="string" resultType="com.jv.pojo.Student">
            select id,name,email,age from student
            where name like '%${name}%';
        </select>
    <!--    增加学生-->
        <insert id="addStudent" parameterType="com.jv.pojo.Student" >
            insert into student (name,email,age) values (#{name},#{email},#{age});
        </insert>
    <!--    删除学生-->
        <delete id="delStudent" parameterType="int">
            delete from student where id = #{id};
        </delete>
    <!--    更新学生-->
        <update id="update" parameterType="com.jv.pojo.Student">
            update student set name = #{name},email=#{email},age=#{age}
            where id=#{id};
        </update>
    </mapper>
    
  3. 使用代码测试 完成查询所有

            //使用文件流读取核心配置文件SqlMapConfig.xml
            InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
            //创建SqlSessionFactory工厂
            SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
            //取出SqlSession对象
            SqlSession sqlSession = factory.openSession();
            //完成查询
            List<Object> list = sqlSession.selectList("jv.getAll");
    //        list.forEach(student -> System.out.println(student));//lambda表达式
            for (Object o : list) {
                System.out.println(o);
            }
            //关闭SqlSession
        sqlSession.close();
    
  4. 切记:所有的增删改的操作后都必须手工提交事务!!sqlSession.commit();

8.MyBatis对象分析

  1. Resources类

    解析SqlMapConfig.xml文件,创建出相应的对象

    InputStream in = Resources.getResourceAsStream(“SqlMapConfig.xml”);

  2. SqlSessionFactory接口

    创建SqlSessionFactory工厂对象

    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);

  3. SqlSession接口

    完成sql功能的接口

9.测试注解

  1. @Test //测试方法
  2. @Before //在Test方法执行前先执行的代码
  3. @After // 在Test方法执行后先执行的代码

10.实体类(pojo)注册别名

  1. 单个注册

    <!--注册实体类的别名-->
        <typeAliases>
    <!--        单个实体类(pojo)注册-->
            <typeAlias type="com.jv.pojo.Student" alias="student"></typeAlias>
        </typeAliases>
    实体类别名为student
    
  2. 批量注册

       <typeAliases>
    <!--        实体类批量注册别名
                别名是类名的驼峰命名法   -->
            <package name="com.jv.pojo"/>
        </typeAliases>
    

    使用别名注册后再map中就只用写别名:

    <select id="getAll" resultType="student">
        select id,name,email,age from student;
    </select>
    

11.动态代理存在的意义

在三层架构中 业务逻辑层要通过接口访问数据访问层的功能,动态代理可以实现。

动态代理的实现规范:

  1. UserMapper.xml和UserMapper.java的接口必须在同一个目录下
  2. UserMapper.xml和UserMapper.java的文件名必须一致,后缀不管
  3. UserMapper.xml文件标签的id值和UserMapper.java的接口中方法的名称完全一致
  4. UserMapper.xml文件标签的parameterTyper属性值和UserMapper.java的接口中方法的参数类型完全一致
  5. UserMapper.xml文件标签的resultTyper属性值和UserMapper.java的接口中方法的返回值类型完全一致
  6. UserMapper.xml文件中namespace属性必须是接口的完全限定名称. com.jv.—
  7. 在sqlMapConfig.xml文件中注册mapper时,使用class=接口的完全限定名。

12.批量注册mapper

    <mappers>
<!--        <mapper class="com.jv.mapper.UsersMapper"></mapper>-->
<!--        批量注册-->
        <package name="com.jv.mapper"/>
    </mappers>

13.#{ }占位符

传参大部分使用#{ }占位符,它底层是prepareStatement对象,是安全的数据库访问防止sqsl注入。

#{ }里怎么写 要看prepareStatement参数的类型

  1. prepareStatement类型是简单类型(8种基本和封装+String),则#{ }里随便写
  2. prepareStatement类型是实体类的类型,则#{ } 里只能是类中成员变量的名称(属性名),而且区分大小写。

14.${ }字符串拼接或字符串替换

  1. 字符串拼接,一般用于模糊查询中,建议少用有sql注入风险

    同样看prepareStatement参数的类型

    • prepareStatement参数的类型是简单类型,则${}里随便写,但分版本,3.5.1以下的只能写value
    • prepareStatement参数的类型是实体类类型,则${}里只能是类中成员变量的名称(属性名),而且区分大小写。

    优化模糊查询

    传统:

    select id,username,birthday,sex,address from users where username like '%${name}%';
    

    用concat函数字符串拼接加#{}:

    select id,username,birthday,sex,address from users where username like concat('%',#{name},'%');
    

2.字符串替换

使用场景:当你需要根据不同的列名来进行对应的模糊查询时,用上${}字符串替换

  • mapper接口中可用iBatis注解 @Param来标记传参,在mapper中配置sql时调用

    //模糊地址和用户名查询
    List<Users> getByNameOrAddress(
            @Param("columnName")//模糊查询的列名
            String columnName,
            @Param("columnValue")//模糊查询的值
            String columnValue);
    
    • mapper.xml中调用,${columnName}实现接收各种的列名 (#{}是占位符相当于 ?不可用在where后表示列名,因此要字符串替换)

      <select id="getByNameOrAddress" resultType="users">
          select id,username,birthday,sex,address from users
          where ${columnName} like concat('%',#{columnValue},'%');
      </select>
      

15.返回自增的主键值

​ 在插入语句结束后,返回自增的主键值到入参的users对象的id属性中。select last_insert_id();

<insert id="addUser" parameterType="users">
        <selectKey keyProperty="id" resultType="int" order="AFTER">
            select last_insert_id();
        </selectKey>
        insert into users(username,birthday,sex,address) values (#{userName},#{birthday},#{sex},#{address})
    </insert>

标签参数:

  1. keyProperty:users对象的哪个属性来接返回的主键值

  2. resultType:返回的主键类型

  3. order:在插入语句执行前,还是插入执行后返回的主键值

16.UUID

是一个全球唯一字符串,由36个字母数字中划线组成。java和mysql都提供了UUID的生成。

17.什么是动态SQL

可以定义代码片段,可进行逻辑判断,可以进行循环处理(批量),是条件判断更简单。

  1. :用来定义代码片段,可将所有的列名,或复杂的条件定义为代码片段供使用时调用

    <!--    定义代码片段-->
        <sql id="allColumns">
            id,username,birthday,sex,address
        </sql>
    
  2. :用来引用定义的代码片段

    select <include refid="allColumns"></include>
        from users
    
  3. :进行条件判断

  4. :进行多个条件拼接,在查询、删除、更新中使用

    <select id="QueryByCondition" parameterType="users" resultType="users">
        select <include refid="allColumns"></include>
        from users
        <where>
            <if test="userName != null and userName != ''">
                and username like concat('%',#{userName},'%')
            </if>
            <if test="birthday != null">
                and birthday = #{birthday}
            </if>
            <if test="sex != null and sex != ''">
                and sex = #{sex}
            </if>
            <if test="address != null and address != ''">
                and address like concat('%',#{address},'%')
            </if>
        </where>
    </select>
    
  5. :有选择的进行更新处理,但至少更新一列

    <update id="update" parameterType="users">
        update users
        <set>
            <if test="userName != null and userName != ''">
                username = #{userName},
            </if>
            <if test="birthday != null">
                birthday = #{birthday},
            </if>
            <if test="sex != null and sex != ''">
                sex = #{sex},
            </if>
            <if test="address != null and address != '' ">
                address = #{address},
            </if>
        </set>
        where id = #{id}
    </update>
    
  6. :用来进行循环遍历,完成循环条件查询、批量删除、批量添加、批量更新

    //循环实现 :in(2,4,6)

    <select id="getByIds" resultType="users">
        select <include refid="allColumns"></include>
        from users
        where id in
            <foreach collection="array" item="id" separator="," open="(" close=")">
                #{id}
            </foreach>
    </select>
    

    其中参数:

    • collection:指定入参的类型,List集合用list、Map集合用map、数据用array.
    • item:每次循环出来的值或对象
    • separator:多个值或对象或语句之间的分隔符
    • open:整个循环外的前括号
    • close:整个循环外的后括号

    注意:多条语句一次性执行一定要开启数据库批处理(如批量更新),在properties数据库配置文件中url上添加&allowMultiQueries=true

18.指定参数位置

​ 如果入参是多个的,可以通过指定参数位置进行传参,是实体类包含不住的条件(实体类只能封装住成员变量的条件),如果某个成员变量要有区间范围类的判断,或者有两个值进行处理则实体类包不住,如:查询指定日期范围内的用户信息。

//查询指定日期范围的用户信息
List<Users> queryByBirthday(Date begin,Date end);

​ 用arg0|arg1来去,默认第一个入参是0一次往后

<select id="queryByBirthday" resultType="users">
    select <include refid="allColumns"></include>
    from users
    where birthday between #{arg0} and #{arg1};
</select>

19.入参是map

​ 如果是入参数超过一个,使用map封装查询条件,更有语义,查询条件更明确。

map.put("birBegin",sf.parse("1995-1-1"));
map.put("birEnd",sf.parse("1999-12-31"));
<!--    #{birBegin}:就是map中的key-->
    <select id="queryByMap" resultType="users">
        select <include refid="allColumns"></include>
        from users
        where birthday between #{birBegin} and #{birEnd};
    </select>

20.返回值是map

​ 如果返回的数据实体类无法包含,可使用map返回多张表中的若干个数据,返回后这些数据之间没有任何关系就是object类型;返回的map中key就是列名或别名。

Map getReturnMap(Integer id);//接口
//测试方法中
Map returnMap = mapper.getReturnMap(15);
System.out.println(returnMap.get("username"));//username就是列名
<select id="getReturnMap" resultType="map">
    select username,address from users where id = #{id};
</select>
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值