CRUD是什么意思?
CRUD说的就是增查改删
C:就是创建(Create)
R:就是查找(Retrieve)
U:就是更改(Update)
D:就是删除(Delete)
什么是面向接口方式进行CRUD?
在传统的JavaWeb开发中,DAO(Data Access Object)层通常需要你手写接口和实现类,接口定义了数据库操作方法,而实现类则具体实现这些方法,使用JDBC或其他持久化技术进行数据库操作。
但是在MyBatis框架中,你只需要定义DAO接口,MyBatis会根据XML配置文件或注解自动生成接口的实现类。这样就不需要手动编写实现类了,减少了大量的代码工作。其背后的原理是MyBatis使用动态代理来为这些接口生成实现类,执行SQL操作。
具体来说:
-
手写DAO层:通常需要手动编写两个部分:
- DAO接口:定义基本的CRUD方法。
- DAO实现类:通过JDBC等方式编写具体的数据库操作逻辑。
public interface UserDao { User findUserById(int id); } public class UserDaoImpl implements UserDao { @Override public User findUserById(int id) { // JDBC logic to find user by id } }
2. MyBatis中的DAO层:只需编写DAO接口,并通过MyBatis的XML映射文件或注解绑定SQL语句,MyBatis会自动生成实现类。
示例:
- DAO接口:
public interface UserDao { User findUserById(int id); }
XML映射文件(
UserMapper.xml
):<select id="findUserById" parameterType="int" resultType="User"> SELECT * FROM users WHERE id = #{id} </select>
MyBatis通过动态代理机制自动实现了
UserDao
接口的实现类并执行对应的SQL查询,使得开发者可以更加专注于业务逻辑,而无需处理底层的数据访问实现。
知识点介绍:
getMapper
是 MyBatis 框架中的一个常用方法,用于获取映射器(Mapper)。映射器是 MyBatis 中的接口,它负责与数据库进行交互。通过 getMapper
方法,你可以动态获取这些映射器的实例,并调用其中定义的数据库操作方法。接下来是关于 getMapper
的一些知识点。
1. 基本概念
在 MyBatis 中,映射器(Mapper)是一个接口,定义了数据访问的方法。MyBatis 框架通过 getMapper
方法为这个接口生成具体的实现类,并且这个实现类会自动执行与数据库的交互逻辑。
2. getMapper
的用法
getMapper
通常用于从 MyBatis 的 SqlSession
中获取映射器的实例。你可以通过映射器直接调用数据库的操作方法,而无需手动编写数据库访问代码。代码示例:
// 1. 获取 SqlSession
SqlSession sqlSession = MyBatisUtils.getSqlSession();
// 2. 获取映射器
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 3. 使用映射器进行数据库操作
User user = userMapper.findUserById(1);
// 4. 关闭 SqlSession
sqlSession.close();
在上面的例子中:
UserMapper
是一个定义了数据库操作方法的接口。sqlSession.getMapper(UserMapper.class)
返回了UserMapper
接口的实现类实例,并通过这个实例可以直接调用数据库查询方法。
使用的前提条件:
-
AccountMapper.xml 文件中的
namespace
:- XML 文件的
<mapper>
标签需要设置namespace
,其值必须是 DAO 接口的全限定名(即包路径+类名)。<mapper namespace="com.example.dao.AccountDao">
- XML 文件的
-
id
必须和接口方法名一致:-
XML 中每个 SQL 映射的
<select>
,<insert>
等标签的id
必须与AccountDao
接口中的方法名一致。<select id="findById" resultType="com.example.domain.Account"> SELECT * FROM account WHERE id = #{id} </select>
-
对应的 DAO 接口方法:
Account findById(int id);
这样,当调用
accountDao.findById()
时,MyBatis 会根据接口的代理类自动映射到AccountMapper.xml
中的id="findById"
这段 SQL。 -
实例:
dao层
CarMapper接口
package dao;
import pojo.Car;
import java.util.List;
public interface CarMapper {
/**
* 新增汽车信息
* @param car
* @return 返回新增条数
*/
int insert(Car car);
/**
* 根据id值删除汽车信息
* @param id
* @return 返回删除条数
*/
int deleteById(Long id);
/**
* 根据id值更新
* @param car
* @return 返回更新条数
*/
int update(Car car);
/**
* 获取所有汽车信息
* @return 返回Car的集合
*/
List<Car> selectAll();
}
pojo层(Model层内部):
Car类:
package pojo;
public class Car {
private int id;
private String carNum;
private String brand;
private double guidePrice;
private String produceTime;
private String carType;
public Car() {
}
public Car(int id,String carNum, String brand, double guidePrice,String produceTime,String carType) {
this.brand = brand;
this.carNum = carNum;
this.carType = carType;
this.guidePrice = guidePrice;
this.id = id;
this.produceTime = produceTime;
}
// Getters and setters
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCarNum() {
return carNum;
}
public void setCarNum(String carNum) {
this.carNum = carNum;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public double getGuidePrice() {
return guidePrice;
}
public void setGuidePrice(double guidePrice) {
this.guidePrice = guidePrice;
}
public String getProduceTime() {
return produceTime;
}
public void setProduceTime(String produceTime) {
this.produceTime = produceTime;
}
public String getCarType() {
return carType;
}
public void setCarType(String carType) {
this.carType = carType;
}
@Override
public String toString() {
return "Car{" +
"id=" + id +
", carNum='" + carNum + '\'' +
", brand='" + brand + '\'' +
", guidePrice=" + guidePrice +
", produceTime='" + produceTime + '\'' +
", carType='" + carType + '\'' +
'}';
}
}
Util包:
运用该类则需要进行手动提交
package util;
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 SqlSessionUtil {
// 静态SqlSessionFactory对象,用于保证整个应用程序中只有一个SqlSessionFactory实例
private static SqlSessionFactory sqlSessionFactory;
// 静态代码块,用于类加载时初始化SqlSessionFactory对象
static {
try {
// 读取MyBatis配置文件,构建SqlSessionFactory对象
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.XML");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
throw new RuntimeException(e); // 捕获IO异常并抛出运行时异常
}
}
// 全局的,服务器级别的,一个服务器当中定义一个即可
private static ThreadLocal<SqlSession> local = new ThreadLocal<>();
/**
* 获取SqlSession对象
* @return SqlSession对象
*/
public static SqlSession openSession() {
SqlSession sqlSession = local.get();
if (sqlSession==null){
sqlSession = sqlSessionFactory.openSession();
// 将sqlSession对象绑定子啊当前线程上 保证一个线程是一个sqlSession对象
local.set(sqlSession);
}
return sqlSession;
}
/**
* 关闭SqlSession对象从当前线程移除sqlSession对象
* @param sqlSession 要关闭的SqlSession对象
*/
public static void closeSession(SqlSession sqlSession) {
if (sqlSession != null) {
sqlSession.close(); // 关闭会话
// 移除SqlSession对象和线程的绑定关系
// 因为Tomcat服务器支持线程池。也就是说:用过的线程对象t1,可能下一次还会使用这个t1线程。
local.remove();
}
}
}
配置文件
carMapper.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="dao.CarMapper">
<!--这里的namespace一定要是接口的全限定名称-->
<!-- insert语句 id 是sql语句的唯一标识,这个id就代表了这条sql语句 -->
<insert id="insert">
insert into t_car(id, car_num, brand, guide_price, produce_time, car_type)
values(null, #{carNum}, #{brand}, #{guidePrice}, #{produceTime}, #{carType})
</insert>
<delete id="deleteById">
delete from t_car where id = #{id}
</delete>
<update id="update">
update t_car set
car_num = #{carNum},
brand = #{brand},
guide_price = #{guidePrice},
produce_time = #{produceTime},
car_type = #{carType}
where id = #{id}
</update>
<!--注意,select语句都需要取别名,不然sql上的数据对应不上类中数据-->
<select id="selectAll" resultType="pojo.Car">
select
car_num as carNum,
brand,
guide_price as guidePrice,
produce_time as produceTime,
car_type as carType
from t_car
</select>
</mapper>
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="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED"> <!-- 如果你需要使用非连接池类型,可以替换为 UNPOOLED -->
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/testmybatis"/>
<property name="username" value="root"/>
<property name="password" value="root"/> <!--自己的用户密码-->
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="carMapper.XML"/> <!--一定要在这里配置不然找不到接口-->
</mappers>
</configuration>