1.1什么是MyBatis
MyBatis(前身是iBatis)是一个支持普通SQL查询、存储过程以及高级映射的持久层框架,
它消除了几乎所有的JDBC代码和参数的手动设置以及对结果集的检索,并使用简单的XML或注解进行配置和原始映射,
用以将接口和Java的POJO(Plain Old Java Object,普通Java对象)映射成数据库中的记录,使得Java开发人员可以使用面向对象的编程思想来操作数据库。
MyBatis框架也被称之为ORM(Object/Relational Mapping,即对象关系映射)框架。所谓的ORM就是一种为了解决面向对象与关系型数据库中数据类型不匹配的技术,
它通过描述Java对象与数据库表之间的映射关系,自动将Java应用程序中的对象持久化到关系型数据库的表中。ORM框架的工作原理如图
从图可以看出,使用ORM框架后,应用程序不再直接访问底层数据库
而是以面向对象的方式来操作持久化对象(Persisent Object, PO),而ORM框架则会通过映射关系将这些面向对象的操作转换成底层的SQL操作。
当前的ORM框架产品有很多,常见的ORM框架有Hibernate和MyBatis。这两个框架的主要区别如下。· Hibernate:是一个全表映射的框架。
通常开发者只需定义好持久化对象到数据库表的映射关系,就可以通过Hibernate提供的方法完成持久层操作。开发者并不需要熟练地掌握SQL语句的编写,
Hibernate会根据制定的存储逻辑,自动的生成对应的SQL,并调用JDBC接口来执行,所以其开发效率会高于MyBatis。然而Hibernate自身也存在着一些缺点,
例如它在多表关联时,对SQL查询的支持较差;更新数据时,需要发送所有字段;不支持存储过程;不能通过优化SQL来优化性能等。
这些问题导致其只适合在场景不太复杂且对性能要求不高的项目中使用。· MyBatis:是一个半自动映射的框架。这里所谓的“半自动”是相对于Hibernate全表映射而言的,
MyBatis需要手动匹配提供POJO、SQL和映射关系,而Hibernate只需提供POJO和映射关系即可。与Hibernate相比,虽然使用MyBatis手动编写SQL要比使用Hibernate的工作量大,
但MyBatis可以配置动态SQL并优化SQL,可以通过配置决定SQL的映射规则,它还支持存储过程等。对于一些复杂的和需要优化性能的项目来说,显然使用MyBatis更加合适。
1.2MyBatis框架在操作数据库时,大体经过了8个步骤。具体如下。
(1)读取MyBatis配置文件mybatis-config.xml。mybatis-config.xml作为MyBatis的全局配置文件,配置了MyBatis的运行环境等信息,其中主要内容是获取数据库连接。
(2)加载映射文件Mapper.xml。Mapper.xml文件即SQL映射文件,该文件中配置了操作数据库的SQL语句,需要在mybatis-config.xml中加载才能执行。mybatis-config.xml可以加载多个配置文件,每个配置文件对应数据库中的一张表。
(3)构建会话工厂。通过MyBatis的环境等配置信息构建会话工厂SqlSessionFactory。
(4)创建SqlSession对象。由会话工厂创建SqlSession对象,该对象中包含了执行SQL的所有方法。
(5)MyBatis底层定义了一个Executor接口来操作数据库,它会根据SqlSession传递的参数动态地生成需要执行的SQL语句,同时负责查询缓存的维护。
(6)在Executor接口的执行方法中,包含一个MappedStatement类型的参数,该参数是对映射信息的封装,用于存储要映射的SQL语句的id、参数等。Mapper.xml文件中一个SQL对应一个MappedStatement对象,SQL的id即是MappedStatement的id。
(7)输入参数映射。在执行方法时,MappedStatement对象会对用户执行SQL语句的输入参数进行定义(可以定义为Map、List类型、基本类型和POJO类型), Executor执行器会通过MappedStatement对象在执行SQL前,将输入的Java对象映射到SQL语句中。这里对输入参数的映射过程就类似于JDBC编程中对preparedStatement对象设置参数的过程。
(8)输出结果映射。在数据库中执行完SQL语句后,MappedStatement对象会对SQL执行输出的结果进行定义(可以定义为Map和List类型、基本类型、POJO类型), Executor执行器会通过MappedStatement对象在执行SQL语句后,将输出结果映射至Java对象中。这种将输出结果映射到Java对象的过程就类似于JDBC编程中对结果的解析处理过程。通过上面对MyBatis框架执行流程的讲解,相信读者对MyBatis框架已经有了一个初步的了解。对于初学者来说,上面所讲解的内容可能不会完全理解,现阶段也不要求读者能完全理解,这里讲解MyBatis框架的执行过程是为了方便后面程序的学习。在学习完MyBatis框架后,读者自然就会明白上面所讲解的内容了。
1.3MyBatis入门程序
1.3.1查询客户
(1)在MySQL数据库中,创建一个名为mybatis的数据库,在此数据库中创建一个t_customer表,同时预先插入几条数据
(2)配置log4j.properties文件
log4j.rootLogger = debug,stdout,D,E log4j.appender.stdout = org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target = System.out log4j.appender.stdout.layout = org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
(3)根据(1)中创建的数据库创建持久化类创建持久化类Customer
package com.itheima.po; /* * 客户持久化类 */ public class Customer { private Integer id; //主键id private String username;//客户名称 private String job;//职业 private String phone;//电话 public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getJobs() { return job; } public void setJobs(String job) { this.job = job; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } @Override public String toString() { return "Customer [id=" + id + ", username=" + username + ", job=" + job + ", phone=" + phone + "]"; } }
从上述代码可以看出,持久化类Customer与普通的JavaBean并没有什么区别,只是其属性字段与数据库中的表字段相对应。
实际上,Customer就是一个POJO(普通Java对象), MyBatis就是采用POJO作为持久化类来完成对数据库操作的。
(4)在src目录下,创建一个com.itheima.mapper包,并在包中创建映射文件CustomerMapper. 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 namespace="com.itheima.mapper.CustomerMapper"> <!--根据客户编号获取客户信息 --> <select id="findCustomerById" parameterType="Integer" resultType="com.itheima.po.Customer"> select * from t_customer where id = #{id} </select> <!-- 根据客户名模糊查询客户信息列表 --> <select id="findCustomerByName" parameterType="String" resultType="com.itheima.po.Customer"> select *from t_customer where username like concat('%',#{value},'%') </select> <!-- 添加客户信息 --> <insert id="addCustomer" parameterType="com.itheima.po.Customer"> insert into t_customer(username,job,phone) values(#{username},#{job},#{phone}) </insert> <!-- 更新客户信息 --> <update id="updateCustomer" parameterType="com.itheima.po.Customer"> update t_customer set username=#{username},job=#{job},phone=#{phone} where id=#{id} </update> <!-- 删除客户信息 --> <delete id="deleteCustomer" parameterType="Integer"> delete from t_customer where id=#{id} </delete> </mapper>
(5)在src目录下,创建MyBatis的核心配置文件mybatis-config.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> <!-- 1.配置环境,默认的环境id为mysql --> <environments default="mysql"> <!-- 1.2配置id为mysql的数据库环境 --> <environment id="mysql"> <!-- 使用JDBC的事务管理 --> <transactionManager type="JDBC"/> <!-- 数据库连接池 --> <dataSource type="POOLED"> <!-- 数据库驱动 --> <property name="driver" value="com.mysql.jdbc.Driver"></property> <!-- 连接数据库 --> <property name="url" value="jdbc:mysql://localhost:3306/test"></property> <!-- 连接数据库的用户名 --> <property name="username" value="root"></property> <!-- 连接数据库的密码 --> <property name="password" value="root"></property> </dataSource> </environment> </environments> <!-- 2.配置Mapper的位置 --> <mappers> <mapper resource="com/itheima/mapper/CustomerMapper.xml"></mapper> <mapper resource="com/itheima/mapper/UserMapper.xml"></mapper> <mapper resource="com/itheima/mapper/CustomerMapper2.xml"></mapper> </mappers> </configuration>
(6)在src目录下,创建一个com.itheima.test包,在该包下创建测试类MybatisTest,并在类中编写测试方法findCustomerByIdTest(),如文件
import java.io.IOException; import java.io.InputStream; import java.util.List; 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 com.itheima.po.Customer; /* * 入门程序测试 */ public class MybatisTestDemo1 { /* * 根据客户编号查询客户信息 */ public void findCustomerByIdTest() throws Exception{ //1.读取配置文件 String resource="mybatis-config.xml"; InputStream inputStream= Resources.getResourceAsStream(resource); //2.根据配置文件构建sqlSessionFactory SqlSessionFactory sqlSessionFactory= new SqlSessionFactoryBuilder().build(inputStream); //3.通过SqlSessionFactory创建SqlSession SqlSession sqlSession=sqlSessionFactory.openSession(); //4.SqlSession执行映射文件中定义的SQL,并返回映射结果 Customer customer=sqlSession.selectOne("com.itheima.mapper" +".CustomerMapper.findCustomerById",1); //打印输出结果 System.out.println(customer.toString()); //5.关闭SqlSession sqlSession.close(); } //根据库的名字模糊查询 public void findCustomerByNameTest() throws Exception { //1.读取配置文件 String resource="mybatis-config.xml"; InputStream inputStream= Resources.getResourceAsStream(resource); //2.根据配置文件构建sqlSessionFactory SqlSessionFactory sqlSessionFactory= new SqlSessionFactoryBuilder().build(inputStream); //3.通过SqlSessionFactory创建SqlSession SqlSession sqlSession=sqlSessionFactory.openSession(); //4.SqlSession执行映射文件中定义的SQL,并返回映射结果 List<Customer> customers=sqlSession.selectList("com.itheima.mapper" +".CustomerMapper.findCustomerByName","j"); //打印输出结果 for(Customer customer:customers) { System.out.println(customer.toString()); } //5.关闭SqlSession sqlSession.close(); } //添加成员 public void addCustomerTest() throws Exception{ //1.读取配置文件 String resource="mybatis-config.xml"; InputStream inputStream= Resources.getResourceAsStream(resource); //2.根据配置文件构建sqlSessionFactory SqlSessionFactory sqlSessionFactory= new SqlSessionFactoryBuilder().build(inputStream); //3.通过SqlSessionFactory创建SqlSession SqlSession sqlSession=sqlSessionFactory.openSession(); //4.SqlSession执行添加操作 //4.1创建Customer对象,并向对象中添加数据 Customer customer=new Customer(); customer.setUsername("rose"); customer.setJobs("student"); customer.setPhone("1234567898"); //4.2执行SqlSession的插入方法,返回的是SQL语句影响的行数 int row=sqlSession.insert("com.itheima.mapper" +".CustomerMapper.addCustomer",customer); //4.3通过返回结果判断插入操作是否执行成功 if(row>0) { System.out.println("您成功插入了"+row+"条数据"); }else { System.out.println("执行插入操作失败"); } //4.4提交事务 sqlSession.commit(); //5关闭SqlSession sqlSession.close(); } //更新客户信息 public void updateCustomerTest() throws Exception { //1.读取配置文件 String resource="mybatis-config.xml"; InputStream inputStream= Resources.getResourceAsStream(resource); //2.根据配置文件构建sqlSessionFactory SqlSessionFactory sqlSessionFactory= new SqlSessionFactoryBuilder().build(inputStream); //3.通过SqlSessionFactory创建SqlSession SqlSession sqlSession=sqlSessionFactory.openSession(); //4.SqlSession执行更新操作 //4.1创建Customer对象,对对象的数据进行模拟更新 Customer customer=new Customer(); customer.setId(4); customer.setUsername("rose"); customer.setJobs("programmer"); customer.setPhone("987654321"); //4.2执行SqlSession的更新方法,返回的是SQL语句影响的行数 int row=sqlSession.update("com.itheima.mapper" +".CustomerMapper.updateCustomer",customer); //4.3通过返回值判断是否更新成功 if(row>0) { System.out.println("您成功修改了"+row+"条数据"); }else { System.out.println("执行修改操作失败!!!!"); } //4.4提交事务 sqlSession.commit(); //5关闭sqlSession sqlSession.close(); } //删除客户 public void deleteCustomerTest() throws Exception{ //1.读取配置文件 String resource="mybatis-config.xml"; InputStream inputStream= Resources.getResourceAsStream(resource); //2.根据配置文件构建sqlSessionFactory SqlSessionFactory sqlSessionFactory= new SqlSessionFactoryBuilder().build(inputStream); //3.通过SqlSessionFactory创建SqlSession SqlSession sqlSession=sqlSessionFactory.openSession(); //4.SqlSession执行删除操作 //4.1执行SqlSession的删除方法,返回的是SQL语句影响的行数 int row=sqlSession.delete("com.itheima.mapper" +".CustomerMapper.deleteCustomer",4); if(row>0) { System.out.println("您成功的删除了"+row+"条数据"); }else { System.out.println("执行删除操作失败"); } //4.3提交事务 sqlSession.commit(); //5关闭 sqlSession.close(); } public static void main(String[] args) throws Exception { MybatisTestDemo1 mybatisTestDemo1= new MybatisTestDemo1(); //mybatisTestDemo1.findCustomerByIdTest(); //mybatisTestDemo1.findCustomerByNameTest(); //mybatisTestDemo1.addCustomerTest(); //mybatisTestDemo1.updateCustomerTest(); //mybatisTestDemo1.deleteCustomerTest(); } }