MyBatis入门

Mybatis

一、概述
1.首先什么是jdbc技术:

由于不同的数据库实现对数据相同的操作的命令可能不同,所以servlet在和数据库交互时,所有的数据库公司都必须按照Sun公司提供的一套标准来封装自己家数据库操作数据的方法,以此提供服务。(比如Mysql的jar包,相当于servlet连接Mysql数据库的驱动包。)程序员只需要在servlet调用驱动包就可以连接到数据库。其中程序员调用数据库的规范就是jdbc技术

2.jdbc操作数据库的流程为:
1.加载调用数据库的驱动包(比如Mysql的jar包)
2.创建并获取数据库连接对象connection
3.通过连接对象获取会话对象statement
4.执行SQL语句。如果是查询语句的话需要通过ResultSet对象进行接收,然后关闭ResultSet对象,关闭statement对象。如果是增删改语句的话,执行完SQL语句之后直接关闭statement对象
5.关闭Connection对象

jdbc操作数据库的过程还是有点多的,而且还有以下问题:

  • 尽管每一次执行完SQL语句后都关闭对象资源,但数据库连接时频繁创建、释放资源会影响系统性能。

  • SQL语句在servlet(Java文件)中,开发中如果修改的话,还需要重新进行编译。

  • 对结果集的解析也是硬编码,SQL变化会导致解析结果的代码也跟着变化,系统不易维护。

3.MyBatis框架

MyBatis是一个优秀的基于Java的持久层框架,内部对jdbc做了封装,使开发者只需要关注SQL语句,而不用关注jdbc中连接和关闭对象的代码,是开发更加简单。

MyBatis采用了半个ORM的思想,而SSH中的Hibernate框架是完全的ORM思想。

ORM:Object Relationship Model 对象关系模型,包含两个映射。

  • 第一个映射是对象和数据库做一 一映射,也就是查询出的数据会封装到对象中。

  • 第二个映射是不使用SQL语句。就是把SQL语句封装到了自己定义的语法中。但这样不灵活:因为无法进行延迟加载和复杂的查询操作如联表查询。

由于Mybatis只把查询的数据封装到了对象中,而且使用SQL语句。所以说是半个ORM思想。

二、MyBatis的入门程序
1.准备步骤
  • 创建数据库和表
  • 创建Maven项目,引入坐标依赖
<dependencies>
<!--mybatis核心包--> 
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!--mysql驱动包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!-- 单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
<!-- 日志 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
  • 编写User实体类(用于把查询到的数据封装进实体中)
  • 实体(entity)就是数据库中的一个个表,可参考E-R图也就是实体联系图。

  • 实体类中的属性尽量使用包装类:

    第一是因为 包装类的默认值为null,而基本类型如int的默认值为0,float的默认值为0.0,char默认值为"",boolean默认值为false。null对于程序来说比较好控制,可以做空值判断。

    第二是因为 数据库中的字段可能为空,如果返回字段是null的话,int类型会报错。

  • 编写UserDao的接口和方法

MyBatis通过反射按照接口定义的规则生成代理实现类,代理实现类生成对象按照接口定义的标准去实现方法。

为什么这里要实现接口而不是实现一个类:因为类实现方式太具体了,已经固定了。而接口只需要定义方法而不需要实现,方法的具体内容让实现接口的类自己实现,很灵活。

2.XML配置方式

MyBatis通过在测试类中 加载 主配置文件sqlMapConfig.xml,主配置文件中有关于各个Dao接口的配置文件(比如UserDao.xml)的映射,然后通过反射获取到接口配置文件中的mapper根标签下的namespace(命名空间)和select、insert等标签下的id、resultType等属性。根据namespace的值MyBatis知道映射到哪个接口,根据select标签中的id,MyBatis知道每个SQL语句应该映射到接口中的哪个抽象方法,并最终生成一个代理实现类。

namespace和resultType等属性中的值不能直接写接口名或者实体类名,而应该写成 包名.接口 / 包名.实体类 这些 具体的路径,这是为了让MyBatis可以通过 反射 来获得类并生成对象。

有类的话 可以通过 类.class 获得类,有对象的话 可以通过 对象.getClass() 获得类。但是这里既没有类又没有对象,只能通过 Class.forName(“类的路径”)这个静态方法来反射获得类。所以这里得写全路径而不是只写接口名和类名。但是基本类型和常用的String不需要写全路径,因为做了优化。

  • 在resource目录下,创建mapper(映射)文件夹。编写UserDao.xml的配置文件,用来 当MyBatis通过反射按照接口生成代理实现类然后生成对象后,将SQL语句映射到Java对象中。
<?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="com.qcby.dao.UserDao">
    <select id="findAll" resultType="com.qcby.entity.User">
        select * from user
    </select>
</mapper>
  • 编写主配置文件,在resource目录下创建sqlMapConfig.xml配置文件

对不同操作的事务管理:默认采用JDBC原则—操作数据时增删改操作默认不执行,因为会改动数据。就算增删改完数据也会把数据回滚回来。所以想要增删改数据的话就需要手动提交数据。查询的话是会自动提交的,因为查询没有改动数据。

连接池:原来用jdbc直接操作数据库的时候,都是创建一个connection对象,不用数据库的时候再close掉。这样的话每次使用数据库就会频繁创建、释放资源,影响性能。

连接池的作用就是为了提高性能。

连接池的基本原理是先初始化一定的数据库连接对象,并且把这些连接保存在池中。当需要建立数据库连接时,只需要从池中取出一个对象访问,使用完毕之后再放回去。这样省略了创建连接和销毁连接的过程,性能上得到提高。本质上放在内存当中,如果初始连接的数量太大的话会消耗内存资源。

<?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>
    <environments default="mysql">
        <environment id="mysql">
            <!--配置事务的类型,使用本地事务策略-->
            <transactionManager type="JDBC"></transactionManager>
            <!--是否使用连接池 POOLED表示使用连接池,UNPOOLED表示不使用连接池-->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3308/mybatis_day01"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    
    <!-- 加载映射配置文件 -->
    <mappers>
        <mapper resource="mapper/UserDao.xml"></mapper>
    </mappers>
</configuration>
  • 编写测试类(两种方法)

一种是SQL Session对象 直接操作数据库,另一种是SQL Session对象 生成接口的代理对象,由代理对象操作数据库

package com.qcby.test;

import com.qcby.dao.UserDao;
import com.qcby.entity.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.IOException;
import java.io.InputStream;
import java.util.List;

public class TestUser {

    @Test
    public void run() throws IOException {

        //加载主配置文件,目的是为了构建SqlSessionFactory对象
        InputStream in = Resources.getResourceAsStream("mybatis.xml");
        //创建SqlSessionFactory对象
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
        //创建SqlSession对象
        SqlSession session = factory.openSession();
        //调用查询所有的方法
        //SQL Session对象 直接操作数据库
        List<User> users = session.selectList("com.qcby.dao.UserDao.findAll");
        //输出结果
        for (User user : users) {
            System.out.println(user);
        }
    }

    @Test
    public void run1() throws IOException {

        //加载主配置文件,目的是为了构建SqlSessionFactory对象
        InputStream in = Resources.getResourceAsStream("mybatis.xml");
        //创建SqlSessionFactory对象
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
        //创建SqlSession对象
        SqlSession session = factory.openSession();
        
        //SQL Session对象 生成接口的代理对象,由代理对象操作数据库
        //通过SqlSession对象创建UserDao接口的代理对象
        UserDao mapper = session.getMapper(UserDao.class);
        //代理对象调用方法
        List<User> users = mapper.findAll();
        //输出结果
        for (User user : users) {
            System.out.println(user);
        }
    }


}
3.注解开发

利用注解开发不再需要编写 接口对应的XML配置文件,之前在XML中写的SQL代码直接写在 接口 中。

MyBatis通过在测试类中加载主配置文件sqlMapConfig.xml,主配置文件中有 关于 接口 的映射,然后通过反射获取到接口中注解着SQL语句的抽象方法,生成代理实现对象。

  • 修改 主配置文件sqlMapConfig.xml 中的映射源
<!-- 加载映射配置文件 -->
    <mappers>
       <!-- 之前是映射xml配置文件 -->
       <!--<mapper resource="mapper/UserDao.xml"></mapper> -->
        <!--<mapper resource="mapper/StudentDao.xml"></mapper>
        <mapper resource="mapper/TeacherDao.xml"></mapper>-->
		
       <!-- 现在是映射接口 -->
       <mapper class="com.qcby.dao.UserDao"></mapper>
        <mapper class="com.qcby.dao.StudentDao"></mapper>
        <mapper class="com.qcby.dao.TeacherDao"></mapper>
    </mappers>
  • 在接口中的方法上方加入注解
//注解开发
//插入数据,并返回新插入数据的id     新语句 select last_insert_id()
    @Insert("insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})")
    @SelectKey(statement = "select last_insert_id()",keyColumn = "id",keyProperty = "id",before = false,resultType = Integer.class)
    int insert(User user);

//模糊查询的两种方法
    /*@Select("select * from user where username like #{name}")*/
    @Select("select * from user where username like '%${value}%'")
    List<User> likeSelect(String name);

//注解开发中的分步查询 来实现延迟加载
/*  
  当 实体类的属性名 和 数据库表中的字段名 不一致时:
  当两者只是大小写差别的时候,两者字段是一致的。
  只有插入其他字符如'_'时,两者字段名会不一致导致无法映射,用@Results()注解。 
*/

public class Teacher {
    private Integer id;
    private String Tname;

    private List<Student> students;

    @Override
    public String toString() {
        return ...
    }
}

public class Student {
    private Integer id;
    private String sname;
    private String sex;
    private Integer age;
    private Integer tid;

    //private Teacher teacher;

    @Override
    public String toString() {
        return ...
    }
}

public interface TeacherDao {
    //分步查询 第一步:查询所有老师的信息
    
    @Select("select * from teacher")
    @Results(value = {
            @Result(property = "id",column = "id"),
            @Result(property = "Tname",column = "Tname"),
            @Result(property = "students",column = "id", many = @Many(select = "com.qcby.dao.StudentDao.student",fetchType = FetchType.LAZY))
    })
    List<Teacher> teacher2();
}

public interface StudentDao {
    //分步查询  第二步:查询老师的学生
    
    @Select("select * from student where t_id = #{id}")
    Student student();
}
  • 测试类同上
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值