是一个支持普通SQL查询、存储过程以及高级映射的持久层框架,使得Java开发人员可以使用面向对象的编程思想来操作数据库。
MyBatis框架
也被称之为ORM( Object/Relational Mapping,即对象关系映射)框架
是一个全表映射的框架
。通常开发者只需定义好持久化对象到数据库表的映射关系,就可以通过 Hibernate提供的方法完成持久层操作。开发者并不需要熟练地掌握SQL语句的编写, Hibernate会根据制定的存储逻辑,自动的生成对应的SQL,并调用JDBC接口来执行,所以其开发效率会高于 MyBatis。然而 Hibernate自身也存在着一些缺点,例如它在多表关联时,对SQL查询的支持较差;更新数据时,需要发送所有字段;不支持存储过程;不能通过优化SOL来优化性能等。这些问题导致其只适合在场景不太复杂且对性能要求不高的项目中使用。
是一个半自动映射的框架
。这里所谓的“半自动”是相对于 Hibernate全表映射而言的, MyBatis需要手动匹配提供POJO、SQL和映射关系,而 Hibernate只需提供POJO和映射关系即可。与 Hibernate相比,虽然使用 MyBatis手动编写SQL要比使用Hibernate的工作量大,但 MyBatis可以配置动态SQL并优化SQL,可以通过配置决定SQL的映射规则,它还支持存储过程等。对于一些复杂的和需要优化性能的项目来说,显然使用MyBatis更加合适。
mybatis- config. xml作为 Mybatis的全局配置文件,配置了 Mybatis的运行环境等信息,其中主要内容是获取数据库连接。
Mapper.xml文件即SQL映射文件,该文件中配置了操作数据库的SQL语句,需要在 mybatis- config. xml中加载オ能执行。 mybatis- config. xml可以加载多个配置文件,每个配置文件对应数据库中的一张表。
通过 MyBatis的环境等配置信息构建会话工厂 Sqlsessionfactory。
由会话工厂创建 Sqlsession对象,该对象中包含了执行SQL的所有方法。
MyBatis底层定义了一个 Executor接口来操作数据库,它会根据 Sqlsession传递的参数动态地生成需要执行的SQL语句,同时负责查询缓存的维护。
在 Executor接口的执行方法中,包含一个 MappedStatement 类型的参数,该参数是对映射信息的封装,用于存储要映射的SQL语句的id、参数等。 Mapper.xml文件中一个SQL对应一个 MappedStatement对象,SQL的d即是 MappedStatement的id。
在执行方法时, MappedStatement对象会对用户执行SOL语句的输入参数进行定义(可以定义为Map、List类型、基本类型和POJO类型), Executor执行器会通过MappedStatement对象在执行SQL前,将输入的Java对象映射到SOL语句中。这里对输入参数的映射过程就类似于JDBC编程中对 preparedstatement对象设置参数的过程。
输出结果映射。在数据库中执行完SQL语句后, MappedStatement对象会对SOL执行输出的结果进行定义(可以定义为Map和List类型、基本类型、POJO类型), Executor执行器会通过 MappedStatement对象在执行SQL语句后,将输出结果映射至Java对象中。这种将输出结果映射到Java对象的过程就类似于JDBC编程中对结果的解析处理过程。
在 MYSQL数据库中,创建一个名为spring的数据库,在此数据库中创建一个person表,同时预先插入几条数据。
在IDEA中,创建一个名为Spring MyBatis的Web项目,将 Mybatis的核心JAR包、lib目录中的依赖JAR包,以及MySQL数据库的驱动JAR包一同添加到项目的lib目录下,并发布到类路径中。
所需jar包地址.
在Src目录下,创建一个com.soft.model包,在该包下创建持久化类 Person,并在类中声明id、 username、 jobs和 phone属性,及其对应的 getter/setter方法。
package com.soft.model;
public class Person {
private int id;
private String username;
private String password;
private String job;
private String phone;
@Override
public String toString() {
return "Person{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", job='" + job + '\'' +
", phone='" + phone + '\'' +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}
# Global logging configuration
log4j.rootLogger=ERROR, stdout
# MyBatis logging configuration...
log4j.logger.com.soft=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
在com目录下,创建一个映射文件PersonMapper. xml
核心配置文件,事务 ,数据源,加载mapper文件,mapper 用一个唯一标识(命名空间+id),找到一条sql语句
<mapper namespace="com.soft.model.PersonMapper">
<select id="findPersonById" parameterType="integer" resultType="com.soft.model.Person">
select * from person where id=#{id}
select>
<select id="findPersonByName" parameterType="String" resultType="com.soft.model.Person">
select * from person where username like concat('%',#{username},'%')
select>
<insert id="addPerson" parameterType="com.soft.model.Person">
insert into person(id,username,password,job,phone) values (#{id},#{username},#{password},#{job},#{phone})
insert>
<update id="updatePerson" parameterType="com.soft.model.Person">
update person set username=#{username},password=#{password},job=#{job},phone=#{phone} where id=#{id}
update>
<delete id="deletePerson" parameterType="integer">
delete from person where id=#{id}
delete>
mapper>
在定义的查询SQL语句中,“#{}”用于表示ー个占位符,相当于"?",而“#{id}”表示该占位符待接收参数的名称为id。
<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/spring" />
<property name="username" value="root" />
<property name="password" value="123456" />
dataSource>
environment>
environments>
<mappers>
<mapper resource="PersonMapper.xml"/>
mappers>
configuration>
在com.soft目录下,创建测试类myBibatisTest,并在类中编写测试方法findPersonByIdTest()、findPersonByNameTest()、addPersonTest()、updatePersonTest()、deletePersonTest(),分别对应通过用户ID查询、通过名字中所含字段查询、增加用户信息、插入/更改用户信息、删除用户信息。
package com.soft;
import com.soft.model.Person;
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.InputStream;
import java.util.List;
public class myBibatisTest {
@Test
public void findPersonByIdTest() throws Exception {
//读取配置文件
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
//根据配置文件构建 会话工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//会话工厂 创建 会话对象
SqlSession sqlSession = sqlSessionFactory.openSession();
Person p1 = sqlSession.selectOne("com.soft.model.PersonMapper.findPersonById", 1);
System.out.println(p1);
sqlSession.close();
}
@Test
public void findPersonByNameTest() throws Exception{
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = build.openSession();
List<Person> o = sqlSession.selectList("com.soft.model.PersonMapper.findPersonByName", "o");
for(Person person:o){
System.out.println(person);
}
sqlSession.close();
}
@Test
public void addPersonTest() throws Exception{
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = build.openSession();
Person person = new Person();
person.setId(20);
person.setUsername("程序员2020");
person.setPassword("456789");
person.setJob("程序员");
person.setPhone("78945612365454");
int i = sqlSession.insert("com.soft.model.PersonMapper.addPerson", person);
if(i>0){
System.out.println("插入了"+i+"条数据");
}else {
System.out.println("插入失败");
}
sqlSession.commit();
sqlSession.close();
}
@Test
public void updatePersonTest() throws Exception {
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = sqlSessionFactory.openSession();
Person person = new Person();
person.setUsername("202003150734");
person.setPassword("456321");
person.setJob("程序员4");
person.setPhone("457912345689");
person.setId(20);
int i = sqlSession.insert("com.soft.model.PersonMapper.updatePerson", person);
if(i>0){
System.out.println("修改成功,修改了: "+i+" 条数据");
}
sqlSession.commit();
sqlSession.close();
}
@Test
public void deletePersonTest() throws Exception {
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = sqlSessionFactory.openSession();
int d = sqlSession.delete("com.soft.model.PersonMapper.deletePerson", 15);
if(d>0){
System.out.println("成功删除了: "+d+" 条对象");
}
sqlSession.commit();
sqlSession.close();
}
}
findPersonByIdTest():
findPersonByNameTest():
addPersonTest():
updatePersonTest():
deletePersonTest():
在使用“${}”进行SQL字符串拼接时,无法防止SQL注入问题。所以想要既能实现模糊查询,又要防止SQL注入,可以对上述映射文件PersonMapper. xml中模糊查询的 select语句进行修改,使用 MySQL中的 concat函数进行字符串拼接。
select * from person where username like concat('%',#{username},'%')