Mybatis的简单介绍和基本使用
1、数据库操作框架的历程
1、JDBC
JDBC(java数据库连接),是一种用于执行数据库SQL语句的Java API,可以为多种关系型数据库提供统一访问,它由一组用Java语言编写的类和接口组成,JDBC提供了一种基准,据此可以构建更高级的工具和接口,使数据库人员开发人员能够编写数据库应用程序。
优点:运行期:快捷、高效。
缺点:编码期:代码量大,繁琐的异常处理,不支持数据库跨平台。
JDBC核心API:
1、DriverManager:负责连接数据库。
2、Connection:连接数据库的抽象标志。
3、Statment:负责执行真正的Sql语句。
4、ResultSet:获取到真正的数据结果集。
2、DBUtils
DbUtils是Apache组织提供的一个对JDBC进行简单封装的开源工具类库,使用它能够简化JDBC应用程序的开发,同时也不会影响程序的性能。
DBUtils的三个核心功能:
1、QueryRunner是提供对sql语句操作的api。
2、ResultSetHandler接口,用于定义select语句操作后,怎样封装结果集。
3、DBUtils类,就是一个工具类,定义了关闭资源与事务处理的方法。
3、Hibernate
Hibernate:Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架,hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以随心所欲的使用面向对象编程思维来操纵数据库。 Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序使用,也可以在Servlet/JSP的Web应用中使用,最具革命意义的是,Hibernate可以在应用EJB的JavaEE架构中取代CMP,完成数据持久化的重任。
ORM:(object relational mapping),对象关系映射。
Hibernate优点
1、可自己创建表并维护表结构,通过pojo,就跟python的odoo框架一样。
2、操作数据库的完全面向对象化。
3、完美的跨数据库平台,因为访问数据库也是跨数据库是面向对象的,所以在迁移项目时基本只需要更换数据库驱动即可。
Hibernate缺点
1、优化sql困难,因为sql被封装了。
2、代码耦合度太高。
3、找bug困难。
4、批量数据操作需要大量的内存空间而且执行过程中需要的对象太多。
4、JDBCTemplate
JdbcTemplate是Spring对JDBC的封装,目的是使JDBC更加易于使用。JdbcTemplate是Spring的一部分。JdbcTemplate处理了资源的建立和释放。他帮助我们避免一些常见的错误,比如忘了总要关闭连接。它运行核心的JDBC工作流,如Statement的建立和执行,而我们只需要提供SQL语句和提取结果。
JDBCTemplate优点
运行期:高效、内嵌Spring框架,支持基于AOP的声明式事务。
JDBCTemplate缺点
必须与Spring框架结合在一起、不支持数据库跨平台、默认没有缓存。
5、Mybatis
Mybatis是一款优秀的持久层/半自动框架,它支持自定义sql、存储过程以及高级映射。Mybatis免除了几乎所有的JDBC代码以及设置参数和获取结果集的工作。Mybatis可以通过简单的xml或者注解来配置和映射原始类型、接口和Java POJO(Plain Old Java Object,普通老式Java对象)为数据库中的记录。
Mybatis优点
1、与JDBC相比,减少了50%的代码量。
2、最简单的持久层框架,简单易学。
3、Sql代码从程序代码中分离出来,可以重用。
4、提供xml标签,支持编写动态SQL。
5、提供映射标签,支持对象与数据库的ORM字段关系映射。
6、支持缓存、连接池、数据库移植等。
Mybatis缺点
1、Sql语句编写工作量大,熟练度要高。
2、数据库移植性比较差,如果需要切换数据库的话,Sql会有很大的差异。
2、快速搭建Mybatis项目
2.1、新建一个maven项目,并导入pom依赖
<!-- mybatis核心驱动 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<!-- 导入mysql对应版本的驱动(根据自己安装的版本) -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.24</version>
</dependency>
如何找到适合与自己安装的mysql的连接依赖:依照下面的图去寻找即可。
进入mysql官网mysql官网地址
2.2、配置一个SqlSessionFactory的文件
创建一个配置mybatis核心的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="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="org/mybatis/example/BlogMapper.xml"/>
</mappers>
</configuration>
快速查看drive参数
快速查看url参数
3、mybatis的简单使用
创建一个实体类Emp:
package cool.ale.pojo;
/**
* @author dujlc
*/
public class Emp {
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Emp{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
创建一个EmpMapper.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">
<!-- namespace如果是基于statementId的方式去执行SQL就可以随便写
如果是基于接口绑定的方式就需要输入相应接口的完整限定名-->
<mapper namespace="cool.ale.mapper.EmpMapper">
<select id="selectEmp" resultType="cool.ale.pojo.Emp">
select * from emp where id = #{id}
</select>
</mapper>
3.1、基于statementId的方式去调用SQL
在mybatis配置文件中引入EmpMapper.xml,以供后续去创建SqlSessionFactory
<mappers>
<mapper resource="EmpMapper.xml"/>
</mappers>
测试类
package cool.ale.tests;
import cool.ale.pojo.Emp;
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 java.io.IOException;
import java.io.InputStream;
public class Test {
/**
* 基于statementId的方式去执行SQL
* @throws IOException
*/
@org.junit.Test
public void Test01() throws IOException {
// 从 xml中构建 SqlSessionFactory
String resource = "mybatis.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 获取数据的第一种方式
try (SqlSession session = sqlSessionFactory.openSession()) {
// 这里的第一个参数是EmpMapper中的namespace + 具体sql语句的id
// 第二个是传入sql的参数
Emp emp = (Emp) session.selectOne("cool.ale.pojo.EmpMapper.selectEmp", 101);
System.out.println(emp);
}
}
}
3.2、基于接口绑定的方式调用SQL
1、创建一个调用sql的接口EmpMapper
package cool.ale.mapper;
import cool.ale.pojo.Emp;
public interface EmpMapper {
/**
* 根据id查询sql
* @param id id参数
* @return
*/
Emp selectEmp(Integer id);
}
2、修改EmpMapper.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="cool.ale.mapper.EmpMapper">
<select id="selectEmp" resultType="cool.ale.pojo.Emp">
select * from emp where id = #{id}
</select>
</mapper>
3、修改EmpMapper.xml文件的引入方式,在mybatis文件中需要用mapper属性引入上面创建EmpMapper接口
<mappers>
<mapper class="cool.ale.mapper.EmpMapper"></mapper>
</mappers>
4、特别注意,我们的EmpMapper接口文件必须和EmpMapper.xml文件在同一目录下,否则找不到文件,如果我们是maven项目的话,我们可以在这里一级一级的创建相同的文件目录,如下所示:
5、创建测试类
package cool.ale.tests;
import cool.ale.mapper.EmpMapper;
import cool.ale.pojo.Emp;
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 java.io.IOException;
import java.io.InputStream;
public class Test {
/**
*
* 基于接口绑定的方式
* @throws IOException
*/
@org.junit.Test
public void Test02() throws IOException {
// 从 xml中构建 SqlSessionFactory
String resource = "mybatis.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 获取数据的第二种方式
try (SqlSession session = sqlSessionFactory.openSession()) {
EmpMapper mapper = session.getMapper(EmpMapper.class);
Emp emp = mapper.selectEmp(101);
System.out.println(emp);
}
}
}
3.3、基于注解的方式调用Sql
1、在接口的方法上写上相应的SQL
package cool.ale.mapper;
import cool.ale.pojo.Emp;
import org.apache.ibatis.annotations.Select;
public interface EmpMapper {
/**
* 根据id查询sql
* @param id id参数
* @return
*/
@Select("select * from emp where id = #{id}")
Emp selectEmp(Integer id);
}
2、不要在mapper.xml文件中写上相对应的SQL,在这里我将第二种方式的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">
<!-- namespace如果是基于statementId的方式去执行SQL就可以随便写
如果是基于接口绑定的方式就需要输入相应接口的完整限定名-->
<mapper namespace="cool.ale.mapper.EmpMapper">
<!--<select id="selectEmp" resultType="cool.ale.pojo.Emp">
select * from emp where id = #{id}
</select>-->
</mapper>
3、其它配置不变,写上相应的测试类
/**
*
* 基于注解的方式
* @throws IOException
*/
@org.junit.Test
public void Test03() throws IOException {
// 从 xml中构建 SqlSessionFactory
String resource = "mybatis.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 获取数据的第二种方式
try (SqlSession session = sqlSessionFactory.openSession()) {
EmpMapper mapper = session.getMapper(EmpMapper.class);
Emp emp = mapper.selectEmp(101);
System.out.println(emp);
}
}
4、mybatis的增删改查操作
4.1、准备工作
1、构建一个maven项目,导入下面的jar包,mysql驱动jar包的版本有必要看一下本博客的2.1章节
<!-- mybatis核心驱动 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<!-- 导入mysql对应版本的驱动(根据自己安装的版本) -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.24</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
2、构建Mybatis的配置文件,命名mybatis.xml,mapper那块引入的第3步相应接口的完整限定名
<?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="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--<mapper resource="EmpMapper.xml"/>-->
<mapper class="cool.ale.mapper.EmpMapper"></mapper>
</mappers>
</configuration>
3、定义相应的调用sql语句的接口,命名EmpMapper
package cool.ale.mapper;
import cool.ale.pojo.Emp;
public interface EmpMapper {
/**
* 根据id查询sql
* @param id id参数
* @return
*/
Emp selectEmp(Integer id);
}
4、根据是数据库表定义相应的实体类
package cool.ale.pojo;
/**
* @author dujlc
*/
public class Emp {
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Emp{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
5、配置相应的写sql的文件,命名EmpMapper.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如果是基于statementId的方式去执行SQL就可以随便写
如果是基于接口绑定的方式就需要输入相应接口的完整限定名-->
<mapper namespace="cool.ale.mapper.EmpMapper">
<select id="selectEmp" resultType="cool.ale.pojo.Emp">
select * from emp where id = #{id}
</select>
</mapper>
接下来的工作有三步
1、EmpMapper.xml文件中写上相应的Sql。
2、接口文件中写上相应的接口。
3、写出测试类调用。
4.2、具体操作
<?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如果是基于statementId的方式去执行SQL就可以随便写
如果是基于接口绑定的方式就需要输入相应接口的完整限定名-->
<mapper namespace="cool.ale.mapper.EmpMapper">
<select id="selectEmp" resultType="cool.ale.pojo.Emp">
select * from emp where id = #{id}
</select>
<insert id="insertEmp">
INSERT INTO `mybatis`.`emp`(`id`, `name`) VALUES (#{id}, #{name});
</insert>
<update id="updateEmp">
UPDATE emp SET name = #{name} WHERE id = #{id};
</update>
<delete id="deleteEmp">
DELETE FROM emp WHERE id = #{id};
</delete>
</mapper>
package cool.ale.mapper;
import cool.ale.pojo.Emp;
public interface EmpMapper {
/**
* 根据id查询sql
* @param id id参数
* @return
*/
Emp selectEmp(Integer id);
/**
* 插入Emp信息
* @param emp 传入需要插入的emp对象
* @return
*/
Integer insertEmp(Emp emp);
/**
* 需要更新的对象
* @param emp 传入需要更新的emp对象
* @return
*/
Integer updateEmp(Emp emp);
/**
* 需要删除的对象
* @param id 需要删除的emp对象的id
* @return
*/
Integer deleteEmp(Integer id);
}
package cool.ale.tests;
import cool.ale.mapper.EmpMapper;
import cool.ale.pojo.Emp;
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.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
public class MybatisCRUDTest {
private SqlSession session = null;
@Before
public void before() throws IOException {
// 从 xml中构建 SqlSessionFactory
String resource = "mybatis.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// true是设置自动提交
session = sqlSessionFactory.openSession(true);
}
@Test
public void select() {
EmpMapper mapper = session.getMapper(EmpMapper.class);
Emp emp = mapper.selectEmp(101);
System.out.println(emp);
}
@Test
public void Insert() {
EmpMapper mapper = session.getMapper(EmpMapper.class);
Emp emp = new Emp();
emp.setId(102);
emp.setName("张三");
Integer result = mapper.insertEmp(emp);
System.out.println(result.toString());
}
@Test
public void Update() {
EmpMapper mapper = session.getMapper(EmpMapper.class);
Emp emp = new Emp();
emp.setId(102);
emp.setName("李四");
Integer result = mapper.updateEmp(emp);
System.out.println(result.toString());
}
@Test
public void Delete() {
EmpMapper mapper = session.getMapper(EmpMapper.class);
Integer id = 102;
Integer result = mapper.deleteEmp(id);
System.out.println(result.toString());
}
}