初识MyBatis
Posted shi_zi_183
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了初识MyBatis相关的知识,希望对你有一定的参考价值。
初识MyBatis
什么是MyBatis
MyBatis是一个支持普通SQL查询、储存过程以及高级映射的持久层框架,它消除了几乎所有的JDBC代码和参数的手动设置以及结果集的检索,并使用简单的XML或注解进行配置和原始映射,用以将接口和Java的POJO(Plain Old Java Object,普通Java对象)映射成数据库中的记录,使得Java开发人员可以使用面向对象的编程思想来操作数据库。
MyBatis框架也被称之为ORM(Object/Relational Mapping,即对象关系映射)框架。所谓的ORM就是一种为了解决面向对象与关系型数据库不匹配的技术,它通过描述Java对象与数据表之间的映射关系,自动将Java应用程序中的对象持久化到关系数据库的表中。
使用ORM框架后,应用程序不再直接访问底层数据库,而是以面向对象的方式来操作持久化对象,而ORM框架则会通过映射关系将这些面向对象的操作转换成底层的SQL操作。
ORM框架产品有很多,常见的ORM框架又Hibernate和MyBatis。
1、Hibernate:是一个全表映射的框架。通常开发者只需定义好持久化对象到数据库表的映射关系,就可以通过Hibernate提供的方法完成持久层操作。开发者并不需要熟练地掌握SQL语句地编写,Hibernate会根据指定的存储逻辑,自动地生成SQL,并调用JDBC接口来执行,所有开发效率会高于MyBatis。然而Hibernate自身也存在一些缺点,例如它在多表关联时,对SQL支持较差;更新数据时,需要发送所有字段;不支持存储过程;不能通过优化SQL来优化性能等。这些问题导致其只适合在场景不太复杂且对性能要求不高地项目中使用。
2、MyBatis:是一个半自动映射地框架,这里所谓地半自动是相对于Hibernate全映射而言的,MyBatis需要手动匹配提供POJO、SQL和映射关系,而Hibernate只需提供POJO和映射关系即可。与Hibernate相比,虽然使用MyBatis手动编写SQL要比使用Hibernate工作量大,但MyBatis可以配置动态SQL并优化SQL,可以通过配置决定SQL地映射规则,它还支持存储过程。对于一些复杂地和需要优化性能地项目来说,更加合适。
MyBatis的下载和使用
https://github.com/mybatis/mybatis-3/releases
我们将依赖包和核心包一并导入
MyBatis的工作原理
MyBatis框架在操作数据库时,大体经过了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执行器会通过MapperStatement对象来执行SQL前,将输入的Java对象映射到SQL语句中。这里对输入参数的映射过程就类似于JDBC编程中对PreparedStatement对象设置参数的过程。
8)输出结果映射。在数据库中执行完SQL语句后,MappedStatement对象会对SQL执行输出的结果进行定义(可以定义为Map和List类型、基本类型、POJO),Executor执行器会通过MapperStatement对象在执行SQL后,将输出结果映射至Java对象中。这种将输出结果映射到Java对象的过程就类似于JDBC编程中对结果的解析处理过程
MyBatis入门程序
查询客户
1、根据客户编号查询客户信息
1)在mysql数据库中,创建一个名为,mybatis的数据库,在此数据库中创建一个t_customer表,同时预先插入几条数据。
create database mybatis;
use mybatis;
create table t_customer(
id int(32) primary key auto_increment,
username varchar(50),
jobs varchar(50),
phone varchar(16)
);
insert into t_customer values ('1','joy','doctor','123456789');
insert into t_customer values ('2','jack','teacher','223456789');
insert into t_customer values ('3','tom','worker','323456789');
2)将mybatis核心包,mysql驱动包,依赖包一并导入
3)由于MyBatis默认使用log4j输出日志信息,所有如果要查看控制台的输出SQL语句,那么就需要在classpath路径下配置其日志。在项目的src目录下创建log4j.properties文件
# Global logging configuration
log4j.rootLogger=ERROR, stdout
# MyBatis logging configuration...
log4j.logger.MyBatis=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日志配置,和控制台输出,其中MyBatis日志配置用于将MyBatis包下的所有类的日志记录级别设置为DEBUG。
这个文件不需要手写,在mybatis帮助文档中可以找到
4)创建一个MyBatis包,在该包下创建持久化类Customer,并在类中声明id、username、jobs和phone属性,及其对应的getter/setter方法
package MyBatis;
public class Customer {
private Integer id;
private String username;
private String jobs;
private String phone;
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = 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;
}
@Override
public String toString(){
return "Customer [id="+id+",username="+username+",jobs="+jobs+",phone="+phone+"]";
}
}
5)在src目录下,创建一个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">
<mapper namespace="mapper.CustomerMapper">
<select id="findCustomerById" parameterType="Integer" resultType="MyBatis.Customer">
select * from t_customer where id = #{id}
</select>
</mapper>
<mapper>
元素是配置文件的根元素,它包含一个namespace属性,该属性用于指定了唯一的命名空间,通常会设置为"报名+SQL映射文件名"的形式。子元素<select>
中的信息是用于执行查询操作的配置,其id属性是<select>
元素在映射文件中的唯一标识;parameterType用于指定传入参数的类型,这里表示传递给执行SQL的是一个Integer类型的参数;resultType属性用于指定返回结果的类型,这里表示返回的数据是Customer类型。在定义的查询SQL语句中,"#{}“用于表示一个占位符,相当于”?",而"#{id}"表示该占位符待接收参数的名称为id。
6)创建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>
<environments default="mysql">
<environment id="mysql">
<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>
<mappers>
<mapper resource="mapper/CustomerMapper.xml"/>
</mappers>
</configuration>
7)创建一个test包,创建测试类MybatisTest
package test;
import java.io.InputStream;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.*;
import org.junit.Test;
import MyBatis.Customer;
public class MybatisTest {
@Test
public void findCustomerByIdTest()throws Exception{
String resource="mybatis-config.xml";
InputStream inputStream=Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession=sqlSessionFactory.openSession();
Customer customer=sqlSession.selectOne("mapper.CustomerMapper.findCustomerById", 1);
System.out.println(customer.toString());
sqlSession.close();
}
}
注:如果表中没有查询到记录,那么不会进行映射,而是直接返回null。
findCustomerByIdTest方法,首先通过输入流读取了配置文件,然后根据配置文件构建了SqlSessionFactory对象。接下来通过SqlSessionFactory对象又创建了Session对象,并通过selectOne方法执行查询操作。selectOne()方法的第一个参数表示映射SQL的标识字符串,它由CustomerMapper.xml中<mapper>
元素的namespace属性值+<select>
元素的id属性值组成,第二个参数表示查询所需要的参数,这里查询的是客户端中id为1的客户。为了查看查询结果,这里使用了输出语句输出查询结果信息,最后关闭SqlSession。
2、根据客户名模糊查询客户信息
1)在映射文件CustomerMapper.xml中,添加根据客户名模糊查询客户信息列表的SQL语句
<?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="mapper.CustomerMapper">
<select id="findCustomerById" parameterType="Integer" resultType="MyBatis.Customer">
select * from t_customer where id = #{id}
</select>
<select id="findCustomerByName" parameterType="String" resultType="MyBatis.Customer">
select * from t_customer where username like '%${value}%'
</select>
</mapper>
${}
用来表示拼接SQL的字符串,即不加解释的原样输出。${value}
表示要拼接的是简单类型参数
注:${}
无法防止SQL注入问题。所有想要即能实现模糊查询,又要防止SQL注入,可以使用SQL中的concat()函数进行字符串拼接
select * from t_customer where username like concat('%',#{value},'%')
2)测试类中,添加一个测试方法findCustomerByNameTest()
@Test
public void findCustomerByNameTest() throws Exception{
String resource="mybatis-config.xml";
InputStream inputStream=Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession=sqlSessionFactory.openSession();
List<Customer> customers=sqlSession.selectList("mapper.CustomerMapper.findCustomerByName", "j");
for(Customer customer:customers){
System.out.println(customer.toString());
}
sqlSession.close();
}
添加客户
在映射文件中,添加操作是通过<insert>
元素来实现的。
<insert id="addCustomer" parameterType="MyBatis.Customer">
insert into t_customer(username,jobs,phone)
values (#{username},#{jobs},#{phone})
</insert>
编写addCustomerTest()
public void addCustomerTest() throws Exception{
String resource="mybatis-config.xml";
InputStream inputStream=Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession=sqlSessionFactory.openSession();
Customer customer=new Customer();
customer.setUsername("rose");
customer.setJobs("student");
customer.setPhone("123456789");
int rows=sqlSession.insert("mapper.CustomerMapper.addCustomer",customer);
if(rows>0){
System.out.println("您成功插入了"+rows+"条数据!");
}else{
System.out.println("执行插入操作失败!!!");
}
sqlSession.commit();
sqlSession.close();
}
更新客户
更新是通过配置<update>
元素来实现的
<update id="updateCustomer" parameterType="MyBatis.Customer">
update t_customer set
username=#{username},jobs=#{jobs},phone=#{phone}
where id=#{id}
</update>
public void updateCustomerTest()throws Exception{
String resource="mybatis-config.xml";
InputStream inputStream=Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession=sqlSessionFactory.openSession();
Customer customer=new Customer();
customer.setId(4);
customer.setUsername("rose");
customer.setJobs("programmer");
customer.setPhone("123111111");
int rows=sqlSession.update("mapper.CustomerMapper.addCustomer",customer);
if(rows>0){
System.out.println("您成功修改了"+rows+"条数据!");
}else{
System.out.println("执行修改操作失败!!!");
}
sqlSession.commit();
sqlSession.close();
}
删除客户
删除操作是通过配置<delete>
元素来实现的
<delete id="deleteCustomer" parameterType="Integer">
delete from t_customer where id=#{id}
</delete>
public void deleteCustomerTest()throws Exception{
String resource="mybatis-config.xml";
InputStream inputStream=Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession=sqlSessionFactory.openSession();
Customer customer=new Customer();
int rows=sqlSession.delete("mapper.CustomerMapper.deleteCustomer",5);
if(rows>0){
System.out.println("您成功删除了"+rows+"条数据!");
}else{
System.out.println("执行删除操作失败!!!");
}
sqlSession.commit();
sqlSession.close();
}
以上是关于初识MyBatis的主要内容,如果未能解决你的问题,请参考以下文章
初识Spring源码 -- doResolveDependency | findAutowireCandidates | @Order@Priority调用排序 | @Autowired注入(代码片段
初识Spring源码 -- doResolveDependency | findAutowireCandidates | @Order@Priority调用排序 | @Autowired注入(代码片段