MyBatis

MyBatis框架概述

三层架构

视图展现层(Servlet/web/Controller)—SpringMVC
业务逻辑层(service)—Spring
数据持久层(dao)—MyBatis

框架(Framework)

是一个模板,是个半成品软件,框架是安全的,可复用的,不断升级的软件。

MyBatis框架

基于Java的持久层框架(DAO),早期叫ibatis,代码在GitHub上。JDBC增强版
sql mapper:sql映射—把数据表中的一行数据映射为一个Java对象
Data Access Objects(DAOs)—数据访问,对数据库执行增删改查
MyBatis功能:
1.提供了创建Connection、Statement、ResultSet的能力,不用开发人员创建这些对象。
2.提供了执行sql语句的能力,不用开发人员执行sql。
3.提供了循环sql,把sql的结果转为java对象、list集合的能力。
4.提供了关闭资源,不用开发人员关闭Connection、Statement、ResultSet。

只需开发人员提供sql语句即可。
总结:什么是MyBatis
MyBatis是一个sql映射框架,提供数据库的操作能力,是一个增强的JDBC,使用MyBatis让开发人员集中精神写sql语句就可以了,不必关心Connection、Statement、ResultSet的创建和销毁

MyBatis框架入门

MyBatis下载地址

第一个MyBatis入门例子

步骤
sql映射文件(一张表对应一个sql映射文件),idea可使用模板

<?xml version="1.0" encoding="UTF-8" ?>
<!--sql映射文件:写sql语句的,MyBatis会执行这些SQL语句-->
<!--
    指定约束文件
    mybatis-3-mapper.dtd是约束文件的名称
    约束文件作用:限制,检查在当前文件中出现的标签,属性必须包含MyBatis的要求。
-->
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--
    mapper是当前文件的根标签,必须的
    namespace:命名空间,是唯一的,可以是自定义的字符串,一般写的是dao接口全类名
-->
<mapper namespace="com.whh.dao.StudentDao">
<!--
    在当前文件中,可以使用特定的标签,表示数据库的特定操作
    <select>表示执行查询操作,放的是select语句
    <update>表示更新数据库操作,放的是update语句
    <insert>表示插入操作,放的是insert语句
    <delete>表示删除草,放的是delete语句
    id:你要执行的sql语法的唯一标识,MyBatis会使用这个id值来找到要执行的sql语句
       可以自定义,一般使用的是接口中的方法名
    resultType:表示结果类型,是sql语句执行后的得到的ResultSet,遍历这个ResultSet得到的java对象类型
                写的是类型的bean文件全类名
-->
    <select id="selectStudents" resultType="com.whh.bean.Student">
        select id,name,email,age from student order by id
    </select>

    <!--插入数据-->
    <insert id="insertStudents">
        insert into student values(#{id},#{name},#{email},#{age})
    </insert>

</mapper>

MyBatis主配置文件(一个项目对应一个主配置文件),idea可使用模板

<?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>

    <!--settings:控制mybatis全局行为-->
    <settings>
        <!--设置mybatis输出日志-->
        <setting name="logImpl" value="STDOUT_LOGGING" />
    </settings>

    <!--环境配置: 数据库的连接信息
        default:必须和某个environment的id值一样。
        告诉mybatis使用哪个数据库的连接信息。也就是访问哪个数据库
    -->
    <environments default="development">
        <!-- environment : 一个数据库信息的配置, 环境
             id:一个唯一值,自定义,表示环境的名称。
        -->
        <environment id="development">
            <!--
               transactionManager :mybatis的事务类型
                   type: JDBC(表示使用jdbc中的Connection对象的commit,rollback做事务处理)
            -->
            <transactionManager type="JDBC"/>
            <!--
               dataSource:表示数据源,连接数据库的
                  type:表示数据源的类型, POOLED表示使用连接池
            -->
            <dataSource type="POOLED">
                <!--
                   driver, user, username, password 是固定的,不能自定义。
                -->
                <!--数据库的驱动类名-->
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <!--连接数据库的url字符串-->
                <property name="url" value="jdbc:mysql://localhost:3306/ssm?serverTimezone=GMT&amp;allowPublicKeyRetrieval=true&amp;useSSL=false&amp;characterEncoding=utf8"/>
                <!--访问数据库的用户名-->
                <property name="username" value="root"/>
                <!--密码-->
                <property name="password" value="123456"/>
            </dataSource>
        </environment>


    </environments>

    <!-- sql mapper(sql映射文件)的位置-->
    <mappers>
        <!--一个mapper标签指定一个文件的位置。
           从类路径开始的路径信息。  target/classes(类路径)
        -->
        <mapper resource="com/whh/dao/StudentDao.xml"/>
    </mappers>
</configuration>
        <!--
           mybatis的主配置文件: 主要定义了数据库的配置信息, sql映射文件的位置

           1. 约束文件
           <!DOCTYPE configuration
                PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
                "http://mybatis.org/dtd/mybatis-3-config.dtd">

            mybatis-3-config.dtd:约束文件的名称

          2. configuration 根标签。
        -->

执行代码(可以写一个得到sqlSession的工具类MyBatisUtils.getSqlSession())

@Test
public void test() throws IOException {
    //访问mybatis读取student数据
    //1.定义mybatis主配置文件的名称, 从类路径的根开始(target/classes)
    String config="mybatis.xml";
    //2.读取这个config表示的文件
    InputStream in = Resources.getResourceAsStream(config);
    //3.创建了SqlSessionFactoryBuilder对象
    SqlSessionFactoryBuilder builder  = new SqlSessionFactoryBuilder();
    //4.创建SqlSessionFactory对象
    SqlSessionFactory factory = builder.build(in);
    //5.获取SqlSession对象,从SqlSessionFactory中获取SqlSession
    SqlSession sqlSession = factory.openSession();
    //6.【重要】指定要执行的sql语句的标识。  sql映射文件中的namespace + "." + 标签的id值
    //String sqlId = "com.whh.dao.StudentDao" + "." + "selectStudents";
    String sqlId = "com.whh.dao.StudentDao.selectStudents";
    //7.【重要】执行sql语句,通过sqlId找到语句
    List<Student> studentList = sqlSession.selectList(sqlId);
    //8.输出结果
    //studentList.forEach( stu -> System.out.println(stu));
    for(Student stu : studentList){
        System.out.println("查询的学生="+stu);
    }
    //9.关闭SqlSession对象
    sqlSession.close();
}

MyBatis对象分析

1.Resources类:mybatis中的一个类, 负责读取主配置文件

InputStream in = Resources.getResourceAsStream("mybatis.xml");

2.SqlSessionFactoryBuilder类: 创建SqlSessionFactory对象

//创建了SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder builder  = new SqlSessionFactoryBuilder();
//创建SqlSessionFactory对象
SqlSessionFactory factory = builder.build(in);

3.SqlSessionFactory接口 : 重量级对象, 程序创建一个对象耗时比较长,使用资源比较多。在整个项目中,有一个就够用了。
SqlSessionFactory:接口,接口实现类: DefaultSqlSessionFactory
SqlSessionFactory作用: 获取SqlSession对象。SqlSession sqlSession = factory.openSession();

openSession()方法说明:
1. openSession() :无参数的, 获取是非自动提交事务的SqlSession对象
2. openSession(boolean): openSession(true) 获取自动提交事务的SqlSession.
openSession(false) 非自动提交事务的SqlSession对象
4. SqlSession接口 :定义了操作数据的方法 例如 selectOne() ,selectList() ,insert(),update(), delete(), commit(), rollback()
SqlSession接口的实现类DefaultSqlSession。
使用要求: SqlSession对象不是线程安全的,需要在方法内部使用, 在执行sql语句之前,使用openSession()获取SqlSession对象。在执行完sql语句后,需要关闭它,执行SqlSession.close(). 这样能保证他的使用是线程安全的。
核心是获得SqlSession对象

//执行sql语句,通过sqlId找到语句
List<Student> studentList = sqlSession.selectList(sqlId);

☆MyBatis框架Dao动态代理

MyBatis动态代理

MyBatis使用动态代理完成了传统的接口实现(DaoImpl)类,不需要我们自己写

public class StudentDaoImpl implements StudentDao {
    @Override
    public List<Student> selectStudents() {
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        String sqlId = "com.whh.dao.StudentDao.selectStudents";
        List<Student> students = sqlSession.selectList(sqlId);
        sqlSession.close();
        return students;
    }
}

有了MyBatis动态代理就不用写这个啦!!!

MyBatis的动态代理可以创建出接口实现类来完成SqlSession调用方法执行sql映射文件的sql语句
最终使用这种MyBatis动态代理sqlSession.getMapper的方式完成项目

@Test
public void testSelectStudents(){
    /*
     * 使用MyBatis的动态代理机制,使用sqlSession.getMapper(dao接口)
     * getMapper能获取dao接口对应的实现类对象
     */
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    //getMapper能获取StudentDao接口对应的实现类对象
    StudentDao dao = sqlSession.getMapper(StudentDao.class);
    //调用dao方法,执行数据库操作
    List<Student> students = dao.selectStudents();
    for(Student stu : students){
        System.out.println(stu);
    }
}

参数(sql语句占位符)传递

1.parameterType:参数类型,表示dao接口中该方法的参数的数据类型,可以不写。

<select id="selectStudentById" parameterType="java.lang.Integer" resultType="com.whh.bean.Student"><!--id接口中的方法名;该表对应bean文件全类名-->
    select id,name,email,age from student where id=#{id}
</select>

2.传递一个简单参数
#{ 任意字符 },可避免sql注入的风险
3.传递多个参数
①使用注释@Param(" ")

List<Student> selectStudentByIdAndName(@Param("myid") Integer id, @Param("myname") String name);
<select id="selectStudentByIdAndName" resultType="com.whh.bean.Student"><!--id接口中的方法名;该表对应bean文件全类名-->
    select id,name,email,age from student where id=#{myid} and name=#{myname}
</select>

②使用Java对象 #{属性名}—用的较多

Student student = new Student(1008,"hello","sakh@qq.com",20);
Integer nums = dao.insertStudents(student);
<select id="insertStudents" resultType="com.whh.bean.Student"><!--id接口中的方法名;该表对应bean文件全类名-->
    insert into student values(#{id},#{name},#{email},#{age})
</select>

③按位置—了解
④使用Map—了解(任何时候都不建议形参列表用map,可读性差)

$和#

通常用#
#:占位符,告诉 mybatis 使用实际的参数值代替。并使用 PrepareStatement 对象执行 sql 语句, #{…}代替 sql 语句的“?”。这样做更安全,更迅速,通常也是首选做法。

$ 字符串替换,告诉 mybatis 使用 包 含 的 “ 字 符 串 ” 替 换 所 在 位 置 。 使 用 S t a t e m e n t 把 s q l 语 句 和 包含的“字符串”替换所在位置。使用 Statement 把 sql 语句和 使Statementsql{}的 内容连接起来。主要用在替换表名,列名,不同列排序等操作。会出现sql注入问题
$ 和 # 区别(面试题)
1. #使用 ?在sql语句中做站位的, 使用PreparedStatement执行sql,效率高
2. #能够避免sql注入,更安全。
3. $不使用占位符,是字符串连接方式,使用Statement对象执行sql,效率低
4. $有sql注入的风险,缺乏安全性。
5. $:可以替换表名或者列名

封装MyBatis输出结果

**resultType:**执行 sql 得到 ResultSet 转换的类型,使用类型的完全限定名或别名。 注意如果返回的是集 合,那应该设置为集合包含的类型,而不是集合本身。resultType 和 resultMap,不能同时使用
①返回简单类型

/**
 * 根据id查询age值
 * @param id
 * @return
 */
Integer selectAgeById(@Param("id")Integer id);

resultType用全限定名称就好,别用别名。

<select id="selectAgeById" resultType="integer">
     select age from student where id = #{id}
</select>
@Test
public void testSelectAgeById(){
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    StudentDao dao = sqlSession.getMapper(StudentDao.class);
    Integer age = dao.selectAgeById(1002);
    sqlSession.commit();
    sqlSession.close();
    System.out.println(age);
}

②返回对象类型

Student selectStudentById(Integer id);
<select id="selectStudentById" resultType="com.whh.bean.Student">
    select id,name,email,age from student where id=#{id}
</select>

③返回map
sql 的查询结果作为 Map 的 key 和 value,推荐使用 Map。总之,不建议使用。
resultMap:可以自定义 sql 的结果和 java 对象属性的映射关系。更灵活的把列值赋值给指定属性,常用在列名和 java 对象属性名不一样的情况。
使用方式:
1.先定义 resultMap,指定列名和属性的对应关系。
2.在中把 resultType 替换为 resultMap
列名和 java 对象属性名不一样的情况解决方式:
sql语句起别名+
使用给java对象属性赋于同列名一致
与不可一起用,只能选其一

模糊查询like

模糊查询的实现的两种方式:
一是 java 代码中给查询数据加上“%” —建议这种方式

select id,name,email,age from student where name like #{name}

List<Student> students = dao.selectFuzzyByName("李%");

二是在 mapper 文件 sql 语句条件位置加上“%”

select id,name,email,age from student where name like "%"#{name}"%"

List<Student> students = dao.selectFuzzyByName("李");

MyBatis框架动态SQL

动态SQL

动态sql: 通过 MyBatis 提供的各种标签对条件作出判断以实现动态拼接 SQL 语句sql的内容是变化的,可以根据条件获取到不同的sql语句,主要是where部分发生变化。
常见的动态SQL标签有、、、

①动态SQL之

<!--if test=" "内是 属性=值 -->
<select id="selectIf" resultType="com.whh.bean.Student"><!--id接口中的方法名;返回值类型的全限定名称-->
    select id,name,email,age from student
    where id > 0
    <if test="name != null and name != '' ">
        and name = #{name}
    </if>
    <if test="age > 0">
        or age = #{age}
    </if>
</select>

若都满足sql语句为 select id,name,email,age from student where id > 0 and name = ? or age = ?

②动态SQL之

<select id="selectWhere" resultType="com.whh.bean.Student">
    select id,name,email,age from student
    <where>
        <if test="name != null and name != '' ">
            name = #{name}
        </if>
        <if test="age > 0">
            or age = #{age}
        </if>
    </where>
</select>

若两个test都满足则SQL语句为 select id,name,email,age from student WHERE name = ? or age = ? 
若前test满足后test不满足SQL语句为 select id,name,email,age from student WHERE name = ? 
若前test不满足后test满足SQL语句为 select id,name,email,age from student WHERE age = ? 
若两个test都不满足则SQL语句为 select id,name,email,age from student 
与<if>标签一起用非常方便!

③动态SQL之

<select id="selectForeach" resultType="com.whh.bean.Student">
    select id,name,email,age from student where id in
    <foreach collection="list" open="(" close=")" item="stu" separator=",">
        #{stu}
    </foreach>
</select>

List<Integer> list = new ArrayList<>();
list.add(1001);
list.add(1002);
list.add(1003);

得到的SQL语句为 select id,name,email,age from student where id in ( ? , ? , ? ) 

④动态SQL之代码片段
sql代码片段, 就是复用一些语法
步骤:
1.先定义 sql语句, 表名,字段等
2.再使用,

<sql id="studentSql">
    select id,name,email,age from student
</sql>

<select id="selectWhere" resultType="com.whh.bean.Student">
    <!--select id,name,email,age from student-->
    <!--引用代码片段-->
    <include refid="studentSql"/>
    <where>
        <if test="name != null and name != '' ">
            and name = #{name}
        </if>
        <if test="age > 0">
            or age = #{age}
        </if>
    </where>
</select>

MyBatis主配置文件mybati.xml&PageHelper

主配置文件mybatis.xml

1.数据库的属性配置文件:把数据库连接信息放到一个单独的文件中,在mybatis.xml同级目录下创建一个jdbc.properties文件存放连接数据库的信息和mybatis主配置文件分开。格式是 key=value
2.在mybatis的主配置文件,使用 指定文件的位置,在需要使用值的地方用${key}
目的是便于修改,保存,处理多个数据库的信息。解耦
mybatis.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>
    <!--指定jdbc.properties文件的位置,从类路径根开始找文件-->
    <properties resource="jdbc.properties"/>
    <settings>
        <!--设置mybatis输出日志-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <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>

    <mappers>
        <!-- sql mapper(sql映射文件)的位置-->
        <mapper resource="com/whh/dao/StudentDao.xml"/>
    </mappers>
</configuration>

jdbc.properties

jdbc.url=jdbc:mysql://localhost:3306/ssm?serverTimezone=GMT&allowPublicKeyRetrieval=true&useSSL=false&characterEncoding=utf8
jdbc.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.username=root
jdbc.password=123456

sql映射文件

mybatis.xml指定sql映射文件,如有多个sql映射文件写多个即可或者使用包名
①写多条指定多个sql映射文件

<mappers>
    <!-- sql mapper(sql映射文件)的位置-->
    <mapper resource="com/whh/dao/StudentDao.xml"/>
    <mapper resource="com/whh/dao/UserDao.xml"/>
    <mapper resource="com/whh/dao/BookDao.xml"/>
</mappers>

②使用包名,它会指定该包名下的所有.xml文件

<mappers>
    <!-- sql mapper(sql映射文件)的位置-->
    <mapper resource="com/whh/dao"/>
</mappers>

使用package包名的要求:
1. mapper文件名称需要和接口名称一样, 区分大小写的一样
2. mapper文件和dao接口需要在同一目录

PageHelper

PageHelper做数据分页的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值