小白入门之Mybatis 一时失言乱红尘 2021-09-11 02:14 516阅读 0赞 ### 文章目录 ### * * MyBatis持久层框架 * * 概念 * 内部组件结构图 * 准备数据表 * MyBatis:XML映射方式 * * Maven工程结构 * pom.xml * mybatis-config.xml * User.java * UserMapper.xml * 引入 UserMapper.xml * TestMybatis.java * 参数解析 * * 别名:alias * 参数值:paramterType * 返回值:resultType * 返回值:resultMap * \#和$的区别 * SQL中有特殊字符 * 动态SQL * * sql和include * if * where * set * foreach * MyBatis:接口映射方式 * * 概述 * Maven工程结构 * 创建Emp.java * 创建EmpMapper.xml * 创建EmpMapper接口 * 创建测试类 * ResultMap简单使用 * * 概述 * 案例 * 自动匹配规范驼峰规则 * 扩展 * * JDBC和MyBatis的区别? * XML和接口方式的区别? * 接口方式怎么找到xml执行的? ## MyBatis持久层框架 ## ### 概念 ### MyBatis的前身就是iBatis,iBatis本是apache的一个开源项目,2010年5月这个项目由apahce sofeware foundation 迁移到了google code,并且改名为MyBatis。 MyBatis 是支持普通 SQL 查询,存储过程和高级映射的优秀持久层框架。MyBatis 消除了几乎所有的 JDBC 代码和参数的手工设置以及结果集的检索。 1. 简化JDBC的开发 2. 能够更好的完成ORM(对象关系映射) ### 内部组件结构图 ### ![\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TmpD1kne-1623150729867)(RackMultipart20210608-4-12c6kke\_html\_28841cf87cefc5b9.png)\]][img-TmpD1kne-1623150729867_RackMultipart20210608-4-12c6kke_html_28841cf87cefc5b9.png] ### 准备数据表 ### create database mybatisdb default character set utf8; use mybatisdb; create table user(id int primary key auto_increment,name varchar(100),addr varchar(100),age int); Insert into user values(null,'hanmeimei','北京',28); Insert into user values(null,'xiongda','上海',20); Insert into user values(null,'xiaonger','上海',19); DROP TABLE IF EXISTS `dept`; CREATE TABLE `dept` ( `id` int(11) NOT NULL AUTO_INCREMENT, `dname` varchar(14) DEFAULT NULL, `loc` varchar(13) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of dept -- ---------------------------- INSERT INTO `dept` VALUES ('1', '呵呵呵', '一区'); INSERT INTO `dept` VALUES ('2', '哈哈哈哈', '二区'); INSERT INTO `dept` VALUES ('3', 'operations', '二区'); INSERT INTO `dept` VALUES ('5', 'java教研部', '大钟寺'); INSERT INTO `dept` VALUES ('10', '开发', '西二旗'); DROP TABLE IF EXISTS `emp`; CREATE TABLE `emp` ( `id` int(11) NOT NULL AUTO_INCREMENT, `ename` varchar(10) DEFAULT NULL, `job` varchar(9) DEFAULT NULL, `mgr` decimal(4,0) DEFAULT NULL, `hiredate` date DEFAULT NULL, `sal` decimal(7,2) DEFAULT NULL, `comm` decimal(7,2) DEFAULT NULL, `deptno` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=510 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of emp -- ---------------------------- INSERT INTO `emp` VALUES ('100', 'jack', '副总', null, '2002-05-03', '90000.00', null, '1'); INSERT INTO `emp` VALUES ('200', 'tony', '总监', '100', '2015-02-02', '10000.00', '2000.00', '2'); INSERT INTO `emp` VALUES ('300', 'hana', '经理', '200', '2017-02-02', '8000.00', '1000.00', '2'); INSERT INTO `emp` VALUES ('400', 'leo', '员工', '300', '2019-02-22', '3000.00', '200.12', '2'); INSERT INTO `emp` VALUES ('500', 'liu', '员工', '300', '2019-03-19', '3500.00', '200.58', '2'); INSERT INTO `emp` VALUES ('502', '王一博', 'topidol.', '1000', '2021-03-31', '20000.00', '99.00', '88'); INSERT INTO `emp` VALUES ('504', '蔡徐坤', 'rapper', '10', '2021-03-29', '100.00', '1000.00', '100'); ## MyBatis:XML映射方式 ## ### Maven工程结构 ### ![\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I1Vq37eQ-1623150729879)(RackMultipart20210608-4-12c6kke\_html\_77eb7aca2d14719f.png)\]][img-I1Vq37eQ-1623150729879_RackMultipart20210608-4-12c6kke_html_77eb7aca2d14719f.png] 注:导入jUnit5,使用@BeforeEach注解替代jUnit4的@Before。 ### pom.xml ### <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>cn.tedu</groupId> <artifactId>mybatis</artifactId> <version>0.0.1-SNAPSHOT</version> <name>mybatis</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.4.2</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <java.version>1.8</java.version> </properties> <dependencies> <!--mybatis依赖包--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.4</version> </dependency> <!--jdbc依赖包--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.48</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> ### 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"> <!-- mybatis的核心配置文件 --> <configuration> <environments default="test"> <environment id="test"> <transactionManager type="JDBC"></transactionManager> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatisdb?characterEncoding=utf8&serverTimezone=Asia/Shanghai" /> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> </configuration> ### User.java ### package cn.tedu.pojo; public class User { private int id; private String name; private String addr; private int age; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddr() { return addr; } public void setAddr(String addr) { this.addr = addr; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "User [id=" + id + ", name=" + name + ", addr=" + addr + ", age=" + age + "]"; } } ### UserMapper.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="hello"> <select id="get" resultType="cn.tedu.pojo.User"> select * from user </select> </mapper> ### 引入 UserMapper.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"> <!-- mybatis的核心配置文件 --> <configuration> <environments default="test"> <environment id="test"> <transactionManager type="JDBC"></transactionManager> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatisdb?characterEncoding=utf8&serverTimezone=Asia/Shanghai" /> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> **<mappers> <mapper resource="mappers/UserMapper.xml"/> </mappers>** </configuration> ### TestMybatis.java ### package cn.tedu.test; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.List; 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.jupiter.api.Test; import cn.tedu.pojo.User; public class TestMybatis { @Test public void get() throws IOException { //1,创建SqlSessionFactory对象,线程非安全,用来产生SqlSession //2,创建SqlSession,用来执行sql //3, 定位SQL: namespace的值+id的值 //4,解析结果并打印 InputStream in = Resources.getResourceAsStream("mybatis-config.xml"); SqlSessionFactory session = new SqlSessionFactoryBuilder().build(in); SqlSession sqlSession = session.openSession(); List<User> list = sqlSession.selectList("hello.get"); for (User u : list) { System.out.println(u); } } } ## 参数解析 ## ### 别名:alias ### 在sqlMapConfig.xml配置,在映射文件中直接写对象名称即可 <typeAliases> <typeAlias type="cn.mybatis.pojo.User" alias="User"/> </typeAliases> ### 参数值:paramterType ### 指定参数类型,通常制定一个对象类型。 ### 返回值:resultType ### 非常重要的东西,即完成ORM的映射关系所在。这里指定的cd.tedu.mybatis.domain.User代表把结果集转换成一个User对象实例。 ### 返回值:resultMap ### resultMap 用于对复杂对象结构时,对应的ResultMap结构名称 ### \#和$的区别 ### 两种方式都可以获取参数的值。区别如下: (推荐!)\#: 使用\#\{parameterName\}引用参数的时候,Mybatis会把这个参数认为是一个字符串,例如传入参数是"Smith",那么在SQL(Select \* from emp where name = \#\{employeeName\})使用的时候就会转换为Select \* from emp where name = 'Smith'。 ![\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wa3qlyQ5-1623150729885)(RackMultipart20210608-4-12c6kke\_html\_58b998a1e9e6558d.png)\]][img-wa3qlyQ5-1623150729885_RackMultipart20210608-4-12c6kke_html_58b998a1e9e6558d.png] $: 不做字符串拼接,SQL(Select \* from emp where name = $\{employeeName\})使用的时候就会转换为Select \* from emp where name = Smith。此时,如果字段是varchar类型直接抛出SQL异常。 ![\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nEmacuyX-1623150729893)(RackMultipart20210608-4-12c6kke\_html\_4eb79d545cd23655.png)\]][img-nEmacuyX-1623150729893_RackMultipart20210608-4-12c6kke_html_4eb79d545cd23655.png] 从安全性上考虑,能使用\#尽量使用\#来传参,因为这样可以有效防止SQL注入的问题。 ### SQL中有特殊字符 ### 当SQL中有特殊字符,mybatis不能正常解析时, 用<!\[CDATA\[ ?? \]\]>括起来就解决了 <!\[CDATA\[ and age<=\#\{age\} \]\]> <![CDATA[ and age<=#{ age} ]]> ![在这里插入图片描述][487b730f6f29409ebfc494961aa3c7d4.png] ## 动态SQL ## Mybatis提供使用ognl表达式动态生成sql的功能。 ### sql和include ### Sql标签用来提取SQL片段,来提高SQL的复用. 使用位置需要通过include引用指定的SQL片段. <sql id="cols"> id,title,sell_point,price,num,barcode,image,cid,status,created,updated </sql> <select id="find" resultType="Item" parameterType="Item"> SELECT <include refid="cols"/> FROM tb_item </select> ### if ### 执行SQL时,可以添加一些判断条件. <select id="find" resultType="Item" parameterType="Item"> SELECT <include refid="cols"/> FROM tb_item where <if test="title != null"> title like #{ title} </if> <if test="sellPoint != null">and sell_point like #{ sellPoint}</if> </select> ### where ### 去掉条件中可能多余的and或者or: <select id="find" resultType="Item" parameterType="Item"> SELECT <include refid="cols"/> FROM tb_item <where> <if test="title != null"> title like #{ title} </if> <if test="sellPoint != null">and sell_point like #{ sellPoint}</if> </where> </select> ### set ### 去掉最后可能多余的逗号: <update id="update"> UPDATE teachers <set> <if test="tname != null">tname=#{ tname},</if> <if test="tsex != null">tsex=#{ tsex},</if> <if test="tbirthday != null">tbirthday=#{ tbirthday},</if> <if test="prof != null">prof=#{ prof},</if> <if test="depart != null">depart=#{ depart}</if> </set> WHERE tno=#{ tno} </update> ### foreach ### 用于in子查询中的多个值的遍历: <delete id="delete"> DELETE FROM teachers WHERE tno IN <!--ids是给SQL传递的参数Map里的key,item的值就像是for循环里的i变量名--> <foreach collection="ids" item="id" open="(" close=")" separator=","> #{ id} </foreach> </delete> 调用代码: Map<String,Object> map = new HashMap<String,Object>(); String[] ps = { "1","22"}; map.put("ids", ps ); mapper.delete(map); ## MyBatis:接口映射方式 ## ### 概述 ### 在上面的测试用例中,在调用session的方法的时候,都会传入要调用的SQL的namespace+id名称,这不是必须的。可以只传入id即可。但是,如果在mybatis的环境中有多个相同id的映射名称,就会报错。所以,一般情况下,调用方法最好还是使用namespace+id。但是,namespace+id的使用方式很容易报错,因为是string类型的,没有检查。所以,mybatis提供了一种非常好的设计方式来避免这种问题,即Mapper接口。 ### Maven工程结构 ### ![\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TjFV2nVf-1623150729901)(RackMultipart20210608-4-12c6kke\_html\_259effa30254dad7.png)\]][img-TjFV2nVf-1623150729901_RackMultipart20210608-4-12c6kke_html_259effa30254dad7.png] 注:导入jUnit5,使用@BeforeEach注解替代jUnit4的@Before。 ### 创建Emp.java ### package cn.tedu.pojo; import java.util.Date; public class Emp { private int id; private String ename; private String job; private double mgr; private Date hiredate; private double sal; private double comm; private int deptno; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getEname() { return ename; } public void setEname(String ename) { this.ename = ename; } public String getJob() { return job; } public void setJob(String job) { this.job = job; } public double getMgr() { return mgr; } public void setMgr(double mgr) { this.mgr = mgr; } public Date getHiredate() { return hiredate; } public void setHiredate(Date hiredate) { this.hiredate = hiredate; } public double getSal() { return sal; } public void setSal(double sal) { this.sal = sal; } public double getComm() { return comm; } public void setComm(double comm) { this.comm = comm; } public int getDeptno() { return deptno; } public void setDeptno(int deptno) { this.deptno = deptno; } @Override public String toString() { return "Emp [id=" + id + ", ename=" + ename + ", job=" + job + ", mgr=" + mgr + ", hiredate=" + hiredate + ", sal=" + sal + ", comm=" + comm + ", deptno=" + deptno + "]"; } } ### 创建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="cn.tedu.mapper.EmpMapper"> <!-- SQL片段,提高SQL的复用 --> <sql id="columns"> id,ename,job,mgr,hiredate,sal,comm,deptno </sql> <select id="getAll" resultType="cn.tedu.pojo.Emp"> <!-- select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp --> <!-- 引用指定的SQL片段 --> select <include refid="columns"></include> from emp </select> <!-- resultType必须配置 ,parameterType可以省略--> <select id="getOne" resultType="cn.tedu.pojo.Emp" parameterType="int"> select <include refid="columns"></include> from emp where <!-- 判断条件,满足就执行SQL,不满足就不执行了 --> <if test="x != 0" >id = #{ x}</if> </select> <select id="getCount" resultType="int"> select count(*) from emp </select> <!-- Emp在核心配置文件里加了别名配置了 --> <insert id="add" parameterType="Emp"> insert into emp( <include refid="columns"></include>) values(null, <if test="ename!=null">#{ ename},</if> <if test="job!=null">#{ job},</if> <if test="mgr!=0">#{ mgr},</if> NOW(), <if test="sal!=0">#{ sal},</if> <if test="comm!=0">#{ comm},</if> <if test="deptno!=0">#{ deptno}</if> ); </insert> <update id="update" parameterType="Emp"> update Emp <set><!-- set能去多余逗号 --> <if test="ename !=null">ename=#{ ename},</if> <if test="job !=null">job=#{ job},</if> <if test="mgr !=0">mgr=#{ mgr},</if> hiredate=NOW(), <if test="sal !=0">sal=#{ sal},</if> <if test="comm !=0">comm=#{ comm},</if> <if test="deptno !=0"> deptno=#{ deptno},</if> </set> <where> <if test="id !=0">id=#{ id}</if> </where> </update> <delete id="del" parameterType="int"> delete from emp <where>id=#{ x}</where> </delete> <delete id="delmore"> delete from emp <!-- where id in(1,2,3,4,5); --> where id in <!--获取map里的数据, ids是map里的key <foreach collection="ids" open="(" close=")" separator="," item="i"> --> <!--获取数组里的数据, array是固定写法 <foreach collection="array" open="(" close=")" separator="," item="i"> --> <!--获取list里的数据, list是固定写法 --> <foreach collection="list" open="(" close=")" separator="," item="i"> #{ i} </foreach> </delete> </mapper> ### 创建EmpMapper接口 ### **注意:** 1. **包名** **+** **类名** **= UserMapper.xml**\*\* 中 **namespace** 的值\*\* 2. **接口中方法名** **= mapper.xml**\*\* 中定义的 **id** 值\*\* 3. **方法的返回值类型和参数类型要和映射文件中一致** package cn.tedu.mapper; import java.util.List; import java.util.Map; import cn.tedu.pojo.Emp; public interface EmpMapper { List<Emp> getAll(); Emp getOne(int id); int getCount(); void add(Emp emp); void update(Emp emp); void del(int id); void delmore(Map map); void delmore(List list); <T> void delmore(T[] t); } ### 创建测试类 ### package cn.tedu.test; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; import java.util.List; import java.util.Map; 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.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import cn.tedu.mapper.EmpMapper; import cn.tedu.pojo.Emp; //接口开发模式 public class TestEmpInter { private SqlSession session ; @BeforeEach public void init() throws IOException { InputStream in = Resources.getResourceAsStream("sqlMapConfig.xml"); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); session = factory.openSession(); // session = factory.openSession(true);//开启自动提交 } @Test public void getAll() { EmpMapper mapper = session.getMapper(EmpMapper.class); List<Emp> list = mapper.getAll(); for (Emp e : list) { System.out.println(e); } } @Test public void getOne() { EmpMapper mapper=session.getMapper(EmpMapper.class); Emp emp = mapper.getOne(100); System.out.println(emp); } @Test public void getCount() { EmpMapper mapper = session.getMapper(EmpMapper.class); int count = mapper.getCount(); System.out.println("总记录数:"+count); } @Test public void add() { EmpMapper mapper = session.getMapper(EmpMapper.class); Emp emp = new Emp(); emp.setEname("蔡徐坤2"); emp.setJob("rapper"); emp.setMgr(10); emp.setSal(100); emp.setComm(1000); emp.setDeptno(100); mapper.add(emp); session.commit();//提交事务,commit()或者openSession(true) } @Test public void update() { EmpMapper mapper = session.getMapper(EmpMapper.class); Emp emp = new Emp(); emp.setId(502); emp.setEname("王一博"); emp.setJob("topidol."); emp.setMgr(1000); emp.setSal(20000); emp.setComm(99); emp.setDeptno(88); mapper.update(emp); session.commit(); } @Test public void del() { EmpMapper mapper = session.getMapper(EmpMapper.class); mapper.del(503); session.commit(); } @Test public void delmore() { EmpMapper mapper = session.getMapper(EmpMapper.class); // Map<String,Object> map = new HashMap<>(); // map.put("ids", new int[] {506,508,509}); // mapper.delmore(map);//用map封装数据 List list = new ArrayList(); Collections.addAll(list,500,400); mapper.delmore(list);//用list封装数据 // mapper.delmore(new Integer[] {510,511});//用数组封装数据 session.commit(); } } ## ResultMap简单使用 ## ### 概述 ### 当数据库的字段名 和 对象的属性名 一致时,可以用简单属性resultType。 但是当 数据库中的字段名称 和 对象中的属性名称 不 一致时,就需要resultMap属性。 ### 案例 ### <?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="cn.tedu.mybatis.pojo.PersonMapper"> <!-- 最强大对象resultMap,结果封装到哪个pojo对象,type就是谁 --> <resultMap type="Person" id="personRM"> <!—单独处理 属性名 和 字段名不一致的 --> <result property="userName" column="user_name"/> </resultMap> <!-- 查询所有 --> <select id="find" resultMap="personRM"> SELECT id,user_name FROM person WHERE id=#{ id} </select> </mapper> ### 自动匹配规范驼峰规则 ### 数据库中我们习惯使用全大写,多个单词用下划线隔开,而po对象中,习惯使用java驼峰规则。那一个一个手工写resultMap字段,浪费开发时间,直接配置一下就可以了。 如: 数据库字段: is\_man Javabean属性: private Integer isMan mapper配置不需要写字段与属性的配置,会自动映射 注意:主键需要单独写,其它字段就可以直接利用驼峰规则自动映射。 第一步:在sqlMapConfig.xml中配置settings: <?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> <settings> <!--开启驼峰规则--> <setting name="mapUnderscoreToCamelCase" value="true" /> </settings> </configuration> 第二步:resultMap配置autoMapping=“true” <resultMap type="cn.tedu.jk.domain.Contract" id="contractRM" autoMapping="true"> <!-- <id property="id" column="CONTRACT_ID"/> -- > </resultMap> ## 扩展 ## ### JDBC和MyBatis的区别? ### JDBC是java提供了一套专门用于和数据库对接的api,java.sql.\*,其规范了如何和数据库进行对接,实现由各数据库厂商进行各自的实现和扩展。学习JDBC重点在学习如何使用其api。 MyBatis框架是轻量级封装了JDBC,我们已经看不到这些api,连接connection、语句preparedstatement、结果集ResultSet,而关注的是mybatis框架体系如何去使用,一旦写好,我们关注的是java对象。 ### XML和接口方式的区别? ### MyBatis提供了两种操作数据库的方式,一种是通过xml映射文件,一种是通过java的接口类。按面向对象方式更加推荐接口方式,但如果复杂的多表映射,仍然需要使用xml映射文件的ResultMap方式实现。 接口只是假象,其底层仍然是通过xml实现,好不容易实现了一套方式,怎忍丢掉呢?可以做个测试就知道它底层怎么实现的?把xml中的sql删除,它就玩不转了。 ### 接口方式怎么找到xml执行的? ### SqlSession的getMapper方法找到类,通过反射可以获取到类的全路径(包名.类名),相加后就定位到某个xml的命名空间namespace,在根据调用的方法去找到xml中某个标签的id属性。从而实现价值接口,调用接口的方法而间接找到xml中的标签,通过解析xml获取这个标签的内容,从而获取到sql语句。 ![\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-coHyzmah-1623150729909)(RackMultipart20210608-4-12c6kke\_html\_953ff03b9141b1d8.png)\]][img-coHyzmah-1623150729909_RackMultipart20210608-4-12c6kke_html_953ff03b9141b1d8.png] [img-TmpD1kne-1623150729867_RackMultipart20210608-4-12c6kke_html_28841cf87cefc5b9.png]: /images/20210911/cb54fae83c454ca5821e2cf874d8dbd2.png [img-I1Vq37eQ-1623150729879_RackMultipart20210608-4-12c6kke_html_77eb7aca2d14719f.png]: /images/20210911/a4d59e2b29bd4e40b11d8a4fd8601bff.png [img-wa3qlyQ5-1623150729885_RackMultipart20210608-4-12c6kke_html_58b998a1e9e6558d.png]: /images/20210911/88dbb4a1e5b741ceb6b46ac07fea3601.png [img-nEmacuyX-1623150729893_RackMultipart20210608-4-12c6kke_html_4eb79d545cd23655.png]: /images/20210911/993752ec69c54b5e85d46e21f8426352.png [487b730f6f29409ebfc494961aa3c7d4.png]: /images/20210911/1dd6b7bdc1a4483ea1aa27693697fbd0.png [img-TjFV2nVf-1623150729901_RackMultipart20210608-4-12c6kke_html_259effa30254dad7.png]: /images/20210911/978223010e244b75ad9b97307ca22a49.png [img-coHyzmah-1623150729909_RackMultipart20210608-4-12c6kke_html_953ff03b9141b1d8.png]: /images/20210911/cad1a3147857467ea0da25c0d920c6e4.png
相关 小白入门之 Springboot整合SSM 文章目录 1.1 创建SSM模块 1.1.1 系统架构图 1.1.2 项目结构 1.1.3 需 深藏阁楼爱情的钟/ 2021年09月11日 02:20/ 0 赞/ 464 阅读
相关 小白入门之Hello Spring Boot 文章目录 SpringBoot介绍 定义 特点 SpringBoot全新的pom.xml 深藏阁楼爱情的钟/ 2021年09月11日 02:14/ 0 赞/ 385 阅读
还没有评论,来说两句吧...