Spring MyBatis

目录

什么是MyBatis

什么是ORM框架

ORM的工作原理

 ORM框架中Hibernate和Mybatis区别

 MyBatis工作原理

MyBatis入门程序

映射文件中${}和#{}


什么是MyBatis

MyBatis是当前主流的java持久层框架(对象持久化:是指将对象存储在可持久保存的存储介质上,例如主流的关系数据库中。)之一,与Hibernate一样,都是一种ORM框架(ORM:Object/Relational Mapping,即对象关系映射)。

MyBatis(前身是iBatis)是一个支持普通SQL查询,存储过程和高级映射的持久层框架。

MyBatis优点:性能优异,具有高度的灵活性,可优化性和易维护等特点。

什么是ORM框架

ORM是一种为了解决面向对象与关系型数据库中数据类型不匹配的技术。

ORM的工作原理

通过描述Java对象与数据库表之间的映射关系,自动将Java应用程序中的对象持久化到关系型数据库的表中。工作原理如图:

 ORM框架中Hibernate和Mybatis区别

 MyBatis工作原理

(可以结合入门程序理解)

(1)配置一个MyBatis全局配置文件,一般命名为sqlMapConfig.xml或者mybatis-config.xml,全局配置文件的作用是,配置MyBatis的运行环境,比如数据库连接,加载映射文件等。后边会介绍。

(2)加载映射文件,一个映射文件对应数据库中的一张表。一边命名为表名+Mapper.xml(如:userMapper.xml,该文件中编写对user表的增删改查语句)。映射文件需要在全局配置文件中加载。

(3)创建SqlSessionFactory会话工厂。

(4)创建SqlSession对象。由SqlSessionFactory会话工厂创建,该对象中包含了执行sql语句的所有方法。

后边的不太好理解,可以先看前四步然后看入门程序,结合入门程序理解。

(5)MyBatis底层定义了一个Executor接口来操作数据库,他会根据SqlSession传递的参数动态的生成需要执行的sql语句,同时负责查询缓存和维护。

(6)在Executor接口的执行方法中,包含一个MappedStatement类型的参数,该参数是对映射信息的封装,用于存储要映射的SQL语句的id,参数等。Mapper.xml文件中一个SQL对应一个MapperedStatement对象,SQL语句的id即是MappedStatement的id。

(7)输入参数映射。

(8)输出参数映射。

MyBatis入门程序

入门程序介绍:客户信息管理。通过该程序实现对数据库中客户的增加修改删除。

对数据库操作:创建一个mybatis数据库,新建一张名叫customer表,并添加数据。

(1)创建一个web项目,导入MyBatis所需要的jar包以及MySql数据库驱动jar包。

完成程序后web项目的目录结构如图所示:

 

 (2)创建全局配置文件myBatis-config.xml和log4j.properties(myBatis默认使用log4j输出日志信息)。

log4j.properties

# Global logging configuration
log4j.rootLogger=ERROR, stdout
# MyBatis logging configuration...
log4j.logger.haust=DEBUG
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

myBatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis//DTD Config 3.0//EN"".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 name="url" value="jdbc:mysql://localhost:3306/mybatis"/><property name="username" value="root"/><property name="password" value="123456"/></dataSource></environment></environments><!-- 2.配置映射文件Mapper的位置 --><mappers><mapper resource="com/haust/mapper/CustomerMapper.xml"/></mappers>
</configuration>

(3)创建Customer实体类

package com.haust.pojo;
/** 客户持久化类*/
public class Customer {private Integer id ; //主键idprivate String username;private String jobs ;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 jobs;}public void setJobs(String jobs) {this.jobs = jobs;}public String getPhone() {return phone;}public void setPhone(String phone) {this.phone = phone;}@Overridepublic String toString() {return "Customer [id=" + id + ", username=" + username + ", jobs="+ jobs + ", phone=" + phone + "]";}}

(4)创建CustomerMapper.xml映射文件,并在全局配置文件中添加该映射文件。

<?xml version="1.0" encoding="UTF-8" ?>
<!-- MyBatis的约束配置,约束配置信息位置在mybatis-3.4.2.pdf的Getting started 下的2.1.5小节中 -->
<!DOCTYPE mapperPUBLIC "-//mybatis//DTD Mapper 3.0//EN"".dtd">
<!-- namespace表示命名空间 -->
<mapper namespace="com.haust.mapper.CustomerMapper"><!-- 根据客户编号获取客户信息 --><!-- id属性是select元素在映射文件中的唯一标识 --><!-- parameterType属性用于指定传入参数的类型,这里表示传递给sql的是一个integer类型的参数 --><!-- resultType属性用于指定返回结果的类型,这里表示返回的数据是Customer类型 --><select id="findCustomerById" parameterType="Integer" resultType="com.haust.pojo.Customer">select * from t_customer where id = #{id}</select><!-- 根据客户名模糊查询客户信息列表 --><select id="findCustomerByName" parameterType="String" resultType="com.haust.pojo.Customer">select * from t_customer where username like concat('%',#{value},'%')</select><select id="addCustomer" parameterType="com.haust.pojo.Customer">insert into t_customer(username,jobs,phone)value(#{username},#{jobs},#{phone})</select><update id="updateCustomer" parameterType="com.haust.pojo.Customer">update t_customer setusername=#{username},jobs=#{jobs},phone=#{phone}where id=#{id}</update><delete id="deleteCustomer" parameterType="com.haust.pojo.Customer">delete from t_customer where id=#{id}</delete>
</mapper>

(5)创建工具类MyBatisUtil,在工具类中实现sqlSessionFactory会话工厂的创建和sqlSession对象。

package com.haust.util;import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;/** 使用工具类创建sqlSession*/
public class MyBatisUtil {private static SqlSessionFactory sqlSessionFactory = null ;//初始化sqlSessionFactory对象static{try {//使用mybatis提供的Resourcrs类加载MyBatis的配置文件Reader reader = Resources.getResourceAsReader("mybatis-config.xml");//构建SqlSessionFactory工厂sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);} catch (IOException e) {e.printStackTrace();}}//获取SqlSession对象的静态方法public static SqlSession getSession(){return sqlSessionFactory.openSession();}
}

(6)添加测试类(对客户的查询添加操作没有用工具类,而是在每个测试方法中创建了会话工厂和sqlSession对象,所以会有很多重复的代码和注释)。


package com.haust.test;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 org.junit.Test;import com.haust.pojo.Customer;
import com.haust.util.MyBatisUtil;public class findCustomerByIdTest {//通过id查询客户信息@Testpublic void findCustomerByIdTest() throws Exception{//1.通过输入流读取配置文件String resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);//2.根据配置文件构建SqlSessionFactorySqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//3.通过SqlSessionFactory创建SqlSessionSqlSession sqlSession = sqlSessionFactory.openSession();//4.SqlSession执行映射文件中定义的SQL,并返回映射结果//sqlSession.selectOne()的第一个参数表示映射SQL的标识字符串,他由映射文件中<mapper>元素的namespace属性值+<select>元素的id属性值组成//第二个参数表示查询所需要的参数,这里查询的是客户表中id为1的客户Customer customer = sqlSession.selectOne("com.haust.mapper"+".CustomerMapper.findCustomerById",1);//打印输出结果System.out.println(customer.toString());//5.关闭SqlSessionsqlSession.close();}//查询全部客户信息@Testpublic void findCustomerByName() throws Exception{//通过输入流读取配置文件String resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);//根据配置文件构建SqlSessionFactorySqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//通过SqlSessionFactory创建sqlSessionSqlSession sqlSession = sqlSessionFactory.openSession();//sqlSession执行映射文件中定义的SQL,并返回映射结果List<Customer> customers = sqlSession.selectList("com.haust.mapper"+".CustomerMapper.findCustomerByName","j");//打印输出结果集for (Customer customer : customers) {System.out.println(customer);}//关闭SqlSessionsqlSession.close();}//添加客户@Testpublic void addCustomerTest() throws Exception{//通过输入流读取配置文件String resource="mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);//创建SqlSessionFactorySqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//根据SqlSessionFactory创建SqlSessionSqlSession sqlSession = sqlSessionFactory.openSession();//sqlSession执行添加操作//4.1创建Customer对象,并向对象中添加数据Customer customer = new Customer();customer.setUsername("malong");customer.setJobs("player");customer.setPhone("13838312775");//4.2执行sqlSession的插入方法,返回的是SQL语句影响的行数int rows = sqlSession.insert("com.haust.mapper.CustomerMapper.addCustomer",customer);//4.3通过返回结果判断插入操作是否执行成功if(rows>0){System.out.println("成功插入了"+rows+"条数据");}else{System.out.println("执行插入操作失败!!");}//4.4提交事务sqlSessionmit();//关闭sqlSessionsqlSession.close();}//更新用户信息@Testpublic void updateCustomerTest() throws Exception{//获取配置文件String resource="mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);//创建SqlSessionFactorySqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//创建SqlSessionSqlSession sqlSession = sqlSessionFactory.openSession();//SqlSession执行更新操作//创建Customer对象Customer customer = new Customer();customer.setUsername("mayinlong");customer.setJobs("player");customer.setPhone("10086");customer.setId(3);//执行sqlSession的更新操作,返回的是受sql语句影响的行数int rows = sqlSession.update("com.haust.mapper.CustomerMapper.updateCustomer", customer);if(rows>0){System.out.println("成功修改了"+rows+"条语句");}else{System.out.println("修改失败!!!");}//提交更新操作sqlSessionmit();//关闭sqlSessionsqlSession.close();}//删除用户信息@Testpublic void deleteCustomer(){MyBatisUtil myBatisUtil = new MyBatisUtil();SqlSession sqlSession = myBatisUtil.getSession();//执行Sql语句int rows = sqlSession.delete("com.haust.mapper.CustomerMapper.deleteCustomer", 1);if(rows>0){System.out.println("删除成功");}else{System.out.println("删除失败");}sqlSessionmit();sqlSession.close();}
}

映射文件中${}和#{}

关于映射文件中sql语句中${}和#{}的区别在sql注入文章中有所说明

SQL注入_m0_51457307的博客-CSDN博客

思考题:请简述MyBatis的工作执行流程?