一、什么是MyBatis?
1.MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。
2.Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。
3.可以将向 preparedStatement中的输入参数自动进行输入映射,将查询结果集灵活映射成java对象。(输出映射)
二、Mybatis框架执行流程是什么?
- 读取MyBatis 配置文件mybatis-config.xml,加载数据源、事务等,管理映射文件
- 加载映射文件mapper.xml,用于映射表中列和实体属性的关系
- 定义SQL语句,在上一步的文件中加载。
- 创建会话工厂。(SqlSessionFactory),数据库连接池
- 创建会话(SqlSession),连接对象
- 通过Executor 操作数据库
- 输入参数和输出结果
三、实现Mybatis的具体步骤
1.先在pom.xml上添加Mybatis依赖
<dependencies>
<!-- MyBatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>版本号</version>
</dependency>
<!-- MySQL JDBC 驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>版本号</version>
</dependency>
</dependencies>
2. 配置 MyBatis
创建 mybatis-config.xml
文件,配置数据库连接和环境等:
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/数据库名"/>
<property name="username" value="用户名"/>
<property name="password" value="密码"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="org/mybatis/example/BlogMapper.xml"/>
</mappers>
</configuration>
3.配置 SqlSessionFactory
的操作:创建 SqlSession
实例,进而执行数据库操作
package util;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.Reader;
public class BuilderSessionFactory {
private static final String RESOURCE = "mybatis-config.xml";
private static SqlSessionFactory sqlSessionFactory = null;
static { //静态代码块
Reader reader = null;
try {
reader = Resources.getResourceAsReader(RESOURCE);
} catch (IOException e) {
throw new RuntimeException("Get resource error:"+RESOURCE, e);
}
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
}
/**
* 获得SqlSessionFactory
*/
public static SqlSessionFactory getSqlSessionFactory(){
return sqlSessionFactory;
}
}
4.根据数据库创建实体类对象,例如
private Integer cardid;
private String cardcode;
private Integer perid;
public Integer getCardid() {
return cardid;
}
public void setCardid(Integer cardid) {
this.cardid = cardid;
}
public String getCardcode() {
return cardcode;
}
public void setCardcode(String cardcode) {
this.cardcode = cardcode;
}
public Integer getPerid() {
return perid;
}
public void setPerid(Integer perid) {
this.perid = perid;
}
public Card(Integer cardid, String cardcode, Integer perid) {
this.cardid = cardid;
this.cardcode = cardcode;
this.perid = perid;
}
public Card() {
}
@Override
public String toString() {
return "Card{" +
"cardid=" + cardid +
", cardcode='" + cardcode + '\'' +
", perid=" + perid +
'}';
}
5.创建映射文件
(1)首先,什么是映射文件?
映射文件是 MyBatis 框架中用于定义 SQL 语句和 Java 对象之间映射的 XML 文件。它们允许开发者将数据库表的字段与 Java 类的属性关联起来,从而简化数据库操作。
(2)映射文件作用
- SQL 语句定义:在映射文件中,可以编写 SQL 查询、插入、更新和删除语句。
- 结果映射:定义 SQL 查询结果如何映射到 Java 对象的属性。
- 参数映射:定义如何将 Java 对象的属性作为参数传递给 SQL 语句。
- 动态 SQL:使用 MyBatis 的动态 SQL 功能,根据条件动态生成 SQL 语句。
- 缓存配置:可以为特定的 SQL 语句配置缓存策略。
- 事务管理:虽然通常在 MyBatis 配置文件中配置,但映射文件也可以包含事务管理的相关信息。
(3)映射文件通常遵循以下结构
- namespace:定义映射文件的命名空间,通常是 Mapper 接口的完全限定名。
- select|insert|update|delete:定义 SQL 语句,每个元素对应一种类型的数据库操作。
- resultMap:定义结果映射,将 SQL 查询结果映射到 Java 类的属性。
- sql:可以定义可重用的 SQL 片段。
- cache:定义缓存配置。
(4)映射文件示例
<?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="com.example.mapper.CardMapper">
<!-- ResultMap 定义 -->
<resultMap id="cardResultMap" type="com.example.model.Card">
<id property="cardid" column="cardid" />
<result property="cardcode" column="cardcode" />
<result property="perid" column="perid" />
</resultMap>
<!-- 查询单个 Card 记录 -->
<select id="selectCardById" resultMap="cardResultMap">
SELECT cardid, cardcode, perid FROM cards WHERE cardid = #{cardid}
</select>
<!-- 查询所有 Card 记录 -->
<select id="selectAllCards" resultMap="cardResultMap">
SELECT cardid, cardcode, perid FROM cards
</select>
<!-- 插入 Card 记录 -->
<insert id="insertCard" useGeneratedKeys="true" keyProperty="cardid">
INSERT INTO cards (cardcode, perid) VALUES (#{cardcode}, #{perid})
</insert>
<!-- 更新 Card 记录 -->
<update id="updateCard">
UPDATE cards SET cardcode=#{cardcode}, perid=#{perid} WHERE cardid=#{cardid}
</update>
<!-- 删除 Card 记录 -->
<delete id="deleteCard">
DELETE FROM cards WHERE cardid=#{cardid}
</delete>
</mapper>
(5)创建 Mapper 接口: 创建一个接口作为映射文件的访问点
package com.example.mapper;
import com.example.model.Card;
import java.util.List;
public interface CardMapper {
Card selectCardById(Integer cardid);
List<Card> selectAllCards();
void insertCard(Card card);
int updateCard(Card card);
int deleteCard(Integer cardid);
}
6.不使用映射文件也可根据注解形式写
package com.example.mapper;
import com.example.model.Card;
import org.apache.ibatis.annotations.*;
import java.util.List;
public interface CardMapperTwo {
// 根据 cardid 查询单个 Card 记录
@Select("SELECT cardid, cardcode, perid FROM cards WHERE cardid = #{cardid}")
Card selectCardById(Integer cardid);
// 查询所有 Card 记录
@Select("SELECT cardid, cardcode, perid FROM cards")
List<Card> selectAllCards();
// 插入 Card 记录
@Insert("INSERT INTO cards (cardcode, perid) VALUES (#{cardcode}, #{perid})")
@Options(useGeneratedKeys = true, keyProperty = "cardid")
void insertCard(Card card);
// 更新 Card 记录
@Update("UPDATE cards SET cardcode=#{cardcode}, perid=#{perid} WHERE cardid=#{cardid}")
int updateCard(Card card);
// 删除 Card 记录
@Delete("DELETE FROM cards WHERE cardid=#{cardid}")
int deleteCard(Integer cardid);
@Select("select * from person where perid=#{perid}")
@Results(value = {
@Result(id = true,column = "perid",property = "perid" ),
@Result(column = "pername",property = "pername" ),
@Result(column = "perid",property = "card",one=@One(select = "org.example.dao.AnyToAnyTwoDao.getCardByPerid"))
})
Person personAndCard(int perid);
@Select("select * from card where perid=#{perid}")
Card getCardByPerid(int perid);
}
7.先创建一个BuilderSessionFactory
来获取 SqlSessionFactory
并使用它来执行数据库操作的步骤
public class BuilderSessionFactory {
private static final String RESOURCE = "mybatis-config.xml";
private static SqlSessionFactory sqlSessionFactory = null;
static { //静态代码块
Reader reader = null;
try {
reader = Resources.getResourceAsReader(RESOURCE);
} catch (IOException e) {
throw new RuntimeException("Get resource error:"+RESOURCE, e);
}
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
}
/**
* 获得SqlSessionFactory
*/
public static SqlSessionFactory getSqlSessionFactory(){
return sqlSessionFactory;
}
}
8.调用Mysql方法
(1)通过映射文件接口调用Mysql方法
public class CardMapperDemo {
public static void main(String[] args) {
try (SqlSession sqlSession = BuilderSessionFactory.getSqlSessionFactory().openSession(true)) {
CardMapper mapper = sqlSession.getMapper(CardMapper.class);
// 示例:根据 ID 查询单个 Card 记录
Integer cardIdToFind = 1; // 假设我们要查找 cardid 为 1 的记录
Card card = mapper.selectCardById(cardIdToFind);
System.out.println("Selected Card: " + card);
// 示例:查询所有 Card 记录
List<Card> cards = mapper.selectAllCards();
System.out.println("All Cards: " + cards);
// 示例:插入一个新的 Card 记录
Card newCard = new Card(/* 构造 Card 对象 */);
mapper.insertCard(newCard);
// 注意:这里不需要提交事务,因为 openSession(true) 已经自动提交
// 示例:更新 Card 记录
Card cardToUpdate = /* 获取或构造 Card 对象 */;
mapper.updateCard(cardToUpdate);
// 同上,不需要手动提交事务
// 示例:删除 Card 记录
Integer cardIdToDelete = 2; // 假设我们要删除 cardid 为 2 的记录
mapper.deleteCard(cardIdToDelete);
// 同上,不需要手动提交事务
} catch (Exception e) {
// 处理异常,如果需要可以回滚事务
e.printStackTrace();
}
}
}
(2)通过注解形式调用mysql方法
public class CardMapperDemo {
public static void main(String[] args) {
try (SqlSession sqlSession = BuilderSessionFactory.getSqlSessionFactory().openSession(true)) {
CardMapperTwo mapper = sqlSession.getMapper(CardMapperTwo.class);
// 示例:根据 ID 查询单个 Card 记录
Integer cardIdToFind = 1; // 假设我们要查找 cardid 为 1 的记录
Card card = mapper.selectCardById(cardIdToFind);
System.out.println("Selected Card: " + card);
// 示例:查询所有 Card 记录
List<Card> cards = mapper.selectAllCards();
System.out.println("All Cards: " + cards);
// 示例:插入一个新的 Card 记录
Card newCard = new Card(/* 构造 Card 对象 */);
mapper.insertCard(newCard);
// 注意:这里不需要提交事务,因为 openSession(true) 已经自动提交
// 示例:更新 Card 记录
Card cardToUpdate = /* 获取或构造 Card 对象 */;
mapper.updateCard(cardToUpdate);
// 同上,不需要手动提交事务
// 示例:删除 Card 记录
Integer cardIdToDelete = 2; // 假设我们要删除 cardid 为 2 的记录
mapper.deleteCard(cardIdToDelete);
// 同上,不需要手动提交事务
} catch (Exception e) {
// 处理异常,如果需要可以回滚事务
e.printStackTrace();
}
}
}