1.之前我们是如何执行一个sql语句自动包装成一个java对象呢?
1.创建一个mapper.xml,定义 执行的语句名字 和 包装成什么类
2.在总的配置文件里申明这个mapper
3.在java里通过sqlSession执行mapper里定义好的内容
我们还可以使用另一种方法实现第三步。现在我们我们实际上是通过读取xml配置文件中的映射关系来确定selectUser执行的是哪条sql语句,返回什么值。
我们还可以再创建一个接口,在接口中写抽象方法,将接口中的抽象方法和xml文件里的映射关系一一对应。这样我们通过调用接口里的抽象方法,就可以找到xml中的映射关系,进而确定 selectUser执行的是哪条sql语句。
2.现在我们如何执行一个sql语句自动包装成一个java对象
1.基本逻辑
mapper.xml中存放了很多映射关系:
sql语句名称-》真正的sql语句,ie:selectUser-》select * from accounting_ledger.user
现在我们编写一个接口,对这些映射关系命名:
a(映射关系名)= 【sql语句名称-》真正的sql语句】
有了接口之后,我们再调用某个sql语句,就只需要知道映射关系名即可。
2.编写接口和xml
接口:
package Mybatis.Mapper;
import Mybatis.User;
import java.util.List;
public interface UserMapper {
List<User> selectStudent();
}
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">
<!--
MyBatis 映射器(Mapper)XML 文件,用于定义 SQL 映射配置。
映射器文件通常用于将数据库操作与 Java 方法关联起来。
-->
<!-- 定义映射器命名空间,通常与对应的 Java 接口或类的全限定名一致 -->
<mapper namespace="Mybatis.Mapper.UserMapper">
<!--
namespace是这个mapper配置文件的名字,这里我们通过namespace属性把这个mapper和UserMapper接口对应
这样当我们调用接口中的抽象方法时,myBatis就知道通过这个mapper里的配置文件,来实现那个抽象方法
id指的是“select * from user”这条语句的名字,起了这个名字后,我们就可以在后面的java代码里用这个名字指代这条sql语句
这里我们已经将这个mapper和接口对应,接口里会有一个名叫selectUser的抽象方法
当调用selectUser方法时,myBatis会通过namespace找到这个mapper
再通过id来找到调用的这个selectUser方法具体对应这个mapper里的哪一部分语句
resultType是需要映射成的类型的位置(不是电脑里的路径,是在java里的位置,哪个包(也可能不在包里,看你自己),哪个类)
在这个例子里User是类名,Mybatis是User类所在的包名,这个地方每个人不一样,根据你的类的位置来决定。
-->
<select id="selectUser" resultType="Mybatis.User">
select * from accounting_ledger.user
</select>
<!--
在实际项目中,查询语句通常更为复杂,可以包含条件、关联查询等。
这里的示例是一个简单的查询所有user的语句。
-->
</mapper>
3.接口和mapper.xml是如何对应的
(1)一个项目里可能有多个mapper,而每一个mapper对应一个接口,所以我们需要将mapper和接口对应。
mapper的namespace属性应该等于接口的全限定名
(<mapper namespace="Mybatis.Mapper.UserMapper">)
全限定名:
package com.example.myproject.interfaces;
public interface TestMapper {
// 接口方法定义
}
那么,TestMapper
接口的全限定名就是 com.example.myproject.interfaces.TestMapper
。这个全限定名唯一标识了这个接口在Java代码中(不是计算机的路径)的位置。
(2)一个mapper里有多个sql语句,所以接口里也要有多个抽象方法,我们需要将接口里的抽象方法和mapper中的sql语句对应
xml中,每条sql的id应该和接口中的抽象方法名相同
(select id="selectUser"-》List<User> selectUser();)
(3)抽象方法的返回值应该和sql语句的返回值相同
这里抽象方法返回List<User>,而这个sql语句返回的就是一些列user对象的属性。
4.工程文件的格式
我们建议将mapper.xml和接口写在同一目录下:
5.更改最初的mybatis全局配置文件
因为此时我们的mapper被移动到了src文件夹内(接口肯定写在src里,mapper和接口在一起-》mapper在src里),所以此时我们要将全局配置文件中的mapper部分由:
<mapper url="file:UserMapper.xml"/>
改为
<mapper resource="Mybatis/Mapper/UserMapperWithInterface.xml"/>
当配置文件在src文件夹下的时候,用resource,用/表示层级关系。在src文件夹外的时候,用url,用.表示层级关系。resource指类目录,url指电脑的文件目录
6.调用
package Mybatis.Mapper;
import Mybatis.MyBatisUtil;
import Mybatis.User;
import org.apache.ibatis.session.SqlSession;
import java.util.List;
public class Main3 {
public static void main(String args[]){
//用MyBatisUtil来包装之前Main1的工厂类,更简单地得到连接
try(SqlSession sqlSession = MyBatisUtil.getSession(true)){
//获取接口的实现类
UserMapper testMapper = sqlSession.getMapper(UserMapper.class);
//通过接口来实现sql语句
List<User> user = testMapper.selectUser();
//这行代码使用了 Java 8 引入的新特性之一,称为方法引用(Method Reference)。
// 具体来说,System.out::println 是一个静态方法引用,用于将 println 方法关联到 System.out 对象上。
//在这里,System.out::println 等效于 lambda 表达式 (s) -> System.out.println(s)。
// 它表示将遍历 student 集合的每个元素,并将每个元素传递给 System.out.println 方法,实现在控制台上打印每个元素的效果。
user.forEach(System.out::println);
}
}
}
1.当上述代码调用testMapper.selectUser();时,java发现这是一个接口的抽象方法,没有发现真正的实现方法,先暂停
2.与此同时,java读取到了mybatis的大配置文件,发现了
<mapper resource="Mybatis/Mapper/UserMapperWithInterface.xml"/>
3.mybatis开始工作,找到了这个mapper,和刚刚的那个接口,发现了mapper.xml和接口的各种对应关系
4.mybatis通过这个mapper里的sql语句开始为接口里的抽象方法同态生成实现的方法。