目录
4.为什么说mybatis是半自动化orm映射工具?它与全自动的区别在哪里?
6.JDBC编程有哪些不足之处?Mybatis是如何解决这些问题的?
11.XML映射文件中,不同的xml映射文件id是否可以重复?
12.通常一个xml映射文件,都会写一个Dao接口与之对应,那么这个Dao接口的工作原理是什么?Dao接口里的方法、参数不同时,方法可以重载吗?
13.mybatis实现一对一有几种方式?具体是怎么操作的?
14.mybatis实现一对多有几种方式?具体是怎么操作的?
16.Mybatis 是如何进行分页的?分页插件的原理是什么?
17.Mybatis 是否支持延迟加载?如果支持,它的实现原理是什么?
18.当实体类中的属性名和表中的字段名不一样,如果将查询的结果封装到指定 pojo?
19. Mybatis的动态sql是做什么的?都有哪些动态sql?
20.MyBatis 里面的动态 Sql 是怎么设定的?用什么语法?
21.使用Mybatis的Mapper接口调用时有哪些要求?
1.什么是Mybatis?
Mybatis是一个半自动化的ORM(对象关系映射)持久层框架,用来简化java应用程序和数据库之间的交互。让开发者可以通过编写简单的sql语句来操作数据库,并将查询结果自动映射为java对象。
2.Mybatis所提供的功能?
(1)简化数据库的操作:开发者只需要编写sql语句,mybatis会自动处理参数和结果的映射。
(2)动态sql:根据条件可以生成动态的sql语句。
(3)事务管理:支持事务,确保事务的一致性。
(4)缓存机制:提升查询性能,提供一级和二级缓存。一级缓存针对同一个SqlSession有效, 而二级缓存可以在多个SqlSession之间共享。
可能有些人对SqlSession概念有些模糊或遗忘,下面我给大家简单的提一下关于是SqlSession相关的内容?
(1)什么是SqlSession?
SqlSession是MyBatis中的核心接口之一,它负责和数据库的交互,执行sql语句,并管理事务。通过sqlsession,你可以执行数据库的查询、插入、更新、删除等操作。
(2)SqlSession的主要功能包括:
①执行Sql语句:它提供方法来执行SQL查询,例如selectOne()、selectList()、insert()、update()、delete()。
SqlSession session = sqlSessionFactory.openSesssion(); User user = sesssion.selectOne("namespace.getUserById",1);
②事务管理:SqlSession可以控制数据库事务,提供commit()和rollback()方法来提交或回滚事务。
try { session.insert("namespace.addUser", newUser); session.commit(); // 提交事务 } catch (Exception e) { session.rollback(); // 发生异常时回滚事务 }
③关闭资源:使用完SqlSession后,需要调用close()方法来释放数据库资源。
session.close();
总结:SqlSession 是开发者与数据库交互的桥梁,用于执行sql语句和管理事务。
3.MyBatis的优缺点是什么?
优点:
①基于 SQL 编程,灵活不影响应用程序和数据库设计,SQL 放在 XML 中便于管理和动态生成。
②比 JDBC 减少 50% 以上的代码,无需手动管理数据库连接。
③可以很好的与各种数据库兼容(Mybatis是用jdbc来连接数据库,所以jdbc支持的数据库Mybatis都支持)
④可以与spring很好的集成。
⑤支持对象与数据库字段的映射,提供对象关系映射标签。
缺点:
①sql语句编写工作量较大,尤其是字段多或者多表联查的时候,对开发人员编写sql语句的功底有一定要求。
②sql语句依赖于数据库,跨数据库迁移困难。
4.为什么说mybatis是半自动化orm映射工具?它与全自动的区别在哪里?
Mybatis是半自动化ORM工具,因为它需要手动编写sql语句,并将其映射到Java对象,提供灵活性和控制力。相比之下,全自动ORM(如Hibernate)自动生成sql语句和处理对象映射,简化了操作,但灵活性比较低。全自动ORM适合简单的增删查改,Mybatis则适合复杂查询和优化需求。
5.Hibernate和Mybatis的区别?
(1)相同点:
都是对jdbc的封装,都是持久层的框架,都用于dao层的开发。
(2)不同点:
①SQL生成方式:
Mybatis:半自动化,需要开发者手动编写sql语句,提供灵活的sql控制。
Hibernate:全自动化,基于对象可以自动生成sql。
②映射关系:
Mybatis:支持简单的对象关系映射,复杂关系映射需要手动配置,级联操作也需要手动配置。
Hibernate:支持复杂的对象关系映射,如一对多、多对多、级联操作等,自动管理对象之间关系。
③性能和灵活:
Mybatis:需要手动编写sql,sql语句优化容易,适合复杂查询和高性能需求场景。
Hibernate:自动生成的sql,性能不易优化,适合简单的增删查改。
④数据库依赖:
Mybatis:sql依赖于具体数据库,跨数据库迁移时需要调整SQL。
Hibernate:通过HQL(Hibernate query language)实现数据库无关的查询语句,跨数据迁移方便。
⑤学习和维护成本:
Mybatis:学习成本较低,但需要手动维护大量的SQL语句。
Hibernate:学习成本高,但是后期维护方便,sql生成自动化。
6.JDBC编程有哪些不足之处?Mybatis是如何解决这些问题的?
(1)数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库连接池就可以解决这个问题。
解决:在SqlMapConfig.xml中配置数据连接池,使用连接池管理数据库链接。
(2)Sql语句卸载代码中造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码。
解决:将Sql语句配置在XXXXmapper.xml文件中与java代码分离。
(3)向Sql语句传参数麻烦,因为sql语句中的where条件不一定,可能或多或少,占位符需要和参数一一对应。
解决:MyBatis自动将java对象映射至sql语句。
(4)对结果集解析麻烦,sql变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成pojo对象解析会比较方便。
解决:Mybatis自动将sql执行结果映射至java对象。
7.Mybatis编程步骤是什么样的?
【简化:见下】
(1)创建SqlSessionFactory
(2)通过创建的SqlSessionFactory对象来获取SqlSession对象
(3)通过SqlSession对象执行数据库操作
(4)调用SqlSession中的commit()提交事务
(5)调用SqlSession中的close()关闭会话
【详细:如下】
1. 创建数据库表和实体类
根据业务需求设计数据库表。
创建与数据库表对应的 Java 实体类。
2. 配置 MyBatis 环境
引入依赖: 在
pom.xml
中添加 MyBatis 和数据库驱动的依赖(如 MySQL 驱动)<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>最新版本</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>最新版本</version> </dependency>
MyBatis 配置文件(
mybatis-config.xml
): 配置数据库连接信息和 MyBatis 相关设置,如环境、映射文件路径等。<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/dbname"/> <property name="username" value="root"/> <property name="password" value="password"/> </dataSource> </environment> </environments> <mappers> <mapper resource="mapper/UserMapper.xml"/> </mappers> </configuration>
3. 创建 Mapper 接口
定义与数据库操作相关的接口,在接口中声明方法,不用写实现。
public interface UserMapper { User selectUserById(int id); void insertUser(User user); }
4. 编写 Mapper XML 文件
在
UserMapper.xml
文件中编写 SQL 语句并与接口方法进行映射。<mapper namespace="com.example.mapper.UserMapper"> <select id="selectUserById" parameterType="int" resultType="User"> SELECT * FROM users WHERE id = #{id} </select> <insert id="insertUser" parameterType="User"> INSERT INTO users (name, age) VALUES (#{name}, #{age}) </insert> </mapper>
5. 加载 MyBatis 配置文件
在 Java 代码中通过
SqlSessionFactory
读取 MyBatis 配置文件,创建SqlSession
,用以执行数据库操作。InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
6. 执行 SQL 操作
使用
SqlSession
调用 Mapper 接口执行数据库操作。try (SqlSession session = sqlSessionFactory.openSession()) { UserMapper mapper = session.getMapper(UserMapper.class); User user = mapper.selectUserById(1); System.out.println(user); // 插入用户 User newUser = new User("Alice", 25); mapper.insertUser(newUser); session.commit(); // 需要手动提交事务 }
7. 关闭资源
在操作完成后,确保
SqlSession
关闭,防止资源泄漏。
8.Mybatis的工作原理
①读取Mybatis配置文件:加载 MyBatis 全局配置文件(mybatis-config.xml
),其中包含数据库连接信息和 MyBatis 的运行环境设置。
②加载映射文件。映射文件即SQL映射文件,该文件中配置了操作数据库的SQL语句,需要在mybatis-config.xml中加载。mybatis-config.xml文件可以加载多个映射文件,每个文件对应数据库中的一张表。
③构建会话工厂:通过配置文件创建会话工厂SqlSessionFactory.,用于生成会话对象
④创建会话对象:由会话工厂创建 SqlSession 对象,执行 SQL 操作。
⑤Executor执行器:Executor
接口负责动态生成 SQL,并处理查询缓存和数据库操作。
⑥MappedStatement对象:封装 SQL 语句的映射信息,包含 SQL 语句的 ID、参数等,用于 SQL 的执行。
⑦输入参数映射:将输入参数映射到 SQL 中,支持基本类型、POJO 或集合类型。
⑧输出结果映射:将查询结果映射为 Java 对象或集合,类似 JDBC 解析结果集的过程。
9.#{}和${}的区别
#{}
和 ${}
是 MyBatis 中用于处理 SQL 语句参数的两种不同语法,它们的主要区别如下:
(1). 参数处理方式
#{}
(Prepared Statement):• 用于将参数值安全地绑定到 SQL 语句中,MyBatis 会将参数值作为 SQL 的占位符处理,防止 SQL 注入攻击。
• 在执行时,MyBatis 会将占位符替换为实际的参数值,并通过 PreparedStatement 进行处理。
【示例:】
SELECT * FROM users WHERE id = #{id}
${}
(字符串替换):• 用于直接将参数值替换到 SQL 语句中,MyBatis 会将
${}
中的内容直接替换为对应的值。• 不会进行参数安全处理,因此容易受到 SQL 注入的风险。
【示例:】
SELECT * FROM ${tableName} WHERE id = #{id}
2. 使用场景
#{}
:适用于大多数数据库操作,如查询和插入,推荐使用。
${}
:适用于动态表名和列名,需谨慎使用,确保安全。
10.在Mapper中如何传递多个参数?
(1)如果Dao层函数有多个参数,在对应的xml文件中,#{0}代表接收的是Dao层中的第一个参数,#{1}是第二个,以此类推。
(2)使用@Param注解:在Dao层中的参数前添加@param注解,注解内的参数名为传递到Mapper中的参数名。
(3)多个参数封装成Map,以HashMap的形式传递到Mapper中。
11.XML映射文件中,不同的xml映射文件id是否可以重复?
不同的xml映射文件,如果配置了namespace,那么id可以重复;如果没有配置,则不能重复。
【因为namespace+id是作为Map<String ,MapperStatement>中的key使用的,如果没有namespace,就剩下id,那么id重复会导致数据互相覆盖。有了namespace,自然id就可以重复,namespace不同,namespace+id自然也不同】
12.通常一个xml映射文件,都会写一个Dao接口与之对应,那么这个Dao接口的工作原理是什么?Dao接口里的方法、参数不同时,方法可以重载吗?
Dao接口即Mapper接口。接口的全限名就是映射文件中的namespace的值;接口的方法名就是映射文件中Mapper的Statement的id值;接口方法内的参数就是传递给sql的参数。Mapper接口是没有实现类的,当调用接口方法时接口全限名(命名空间)+方法名的拼接字符串作为key的值,可唯一定位一个MapperStatement。
Dao接口里的方法是不能重载的,因为是全限名+方法明德保存和寻找策略。
Dao接口的工作原理是JDK动态代理,Mybatis运行时会使用JDK动态代理为Dao接口生成代理proxy对象,代理对象proxy会拦截接口方法,转而执行MapperStatement所代表的sql,然后将sql执行结果返回。
那什么是动态代理呢?动态代理就是在程序运行期间由JVM通过反射等机制动态生成的,所以不会存在代理类的字节码文件,所以我们在Mybatis中使用mapper接口的时候没有它的实现类,代理对象和真实对象的关系是由运行时期才决定的。
13.mybatis实现一对一有几种方式?具体是怎么操作的?
有联合查询和嵌套查询两种方式。
联合查询是几个表联合查询,通过在resultMap里面配置association节点配置一对一的类就可以完成;
嵌套查询是先查一个表,根据这个表里面的结果的外键id,再去另外一个表里查询数据,也是通过association配置,但另外一个表的查询是通过select配置的。
【注意:嵌套查询容易导致1+n问题,即发了一条查询语句,有可能就是这个对象又包含多个角色,会将一条语句分到多个角色中查询】
14.mybatis实现一对多有几种方式?具体是怎么操作的?
有联合查询和嵌套查询两种方式。
联合查询是几个表联合查询,只查询一次,通过在resultMap里面的collection节点配置一对多的类就可以完成。
嵌套查询是先查一个表,根据这个表里面的结果的外键id,再去另外一个表里查询数据,也是通过collection,但另外一个表的查询也是通过select配置的。
【注意:优先考虑联合查询,可以提高性能,在分页等特殊条件下出现问题的时候才会优先考虑嵌套查询】
15.Mybatis的一级、二级缓存
(1)一级缓存:基于PerpetualCache的HashMap本地缓存,其存储作用域为Sesssion,当Session flush或close之后,该session中的Cache就将会清空,默认打开一级缓存。
(2)二级缓存与一级缓存机制相同,默认也是采用PerpetualCache,HashMap存储,不同在于其存储作用域为Mapper(namespace),并且可自定义存储源,如Ehcache。默认打不开二级缓存,要开启二级缓存,使用二级缓存属性类需要实现Serizalizable序列化接口(可用来保存对象的状态),可在它的映射文件中配置。
对于缓存数据更新机制,当某一作用域(一级缓存session/二级缓存namespace)进行了增、删、改操作后,默认该作用域下所有的select中的缓存将被clear。
16.Mybatis 是如何进行分页的?分页插件的原理是什么?
Mybatis 使用 RowBounds 对象进行分页,也可以直接编写 sql 实现分页,也可以使用Mybatis 的分页插件。
分页插件的原理:实现 Mybatis 提供的接口,实现自定义插件,在插件的拦截方法内拦截待执行的 sql,然后重写 sql。
举例:select * from student,拦截 sql 后重写为:select t.* from (select * from student)tlimit 0,10
17.Mybatis 是否支持延迟加载?如果支持,它的实现原理是什么?
Mybatis 仅支持 association 关联对象和 collection 关联集合对象的延迟加载,association指的就是一对一,collection 指的就是一对多查询。在 Mybatis 配置文件中,可以配置是否启用延迟加载 lazyLoadingEnabled = true | false。
它的原理是,使用 CGLIB 创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用 a.getB().getName(),拦截器 invoke()方法发现 a.getB()是 null 值,那么就会单独发送事先保存好的查询关联 B 对象的 sql,把 B 查询上来,然后调用 a.setB(b),于是 a 的对象 b 属性就有值了,接着完成 a.getB().getName()方法的调用。这就是延迟加载的基本原理。
18.当实体类中的属性名和表中的字段名不一样,如果将查询的结果封装到指定 pojo?
(1)通过在查询的 sql 语句中定义字段名的别名。
(2)通过来映射字段名和实体类属性名的一一对应的关系
19. Mybatis的动态sql是做什么的?都有哪些动态sql?
Mybatis中的动态参数可以让我们在XML映射文件内,以标签的形式编写动态sql,完成逻辑判断和动态拼接sql的功能,Mybatis提供了9种动态sql标签。
【trim / where / set / foreach / if / choose / when / otherwise / bind 】
其执行原理为,使用OGNL从sql参数对象中计算表达式的值,根据表达式的值动态拼接sql,以此完成动态sql的功能。
20.MyBatis 里面的动态 Sql 是怎么设定的?用什么语法?
MyBatis 里面的动态 Sql 一般是通过 if 节点来实现,通过 OGNL 语法来实现,但是如果要
写的完整,必须配合 where,trim 节点,where 节点是判断包含节点有内容就插入 where,否则不
插入,trim 节点是用来判断如果动态语句是以 and 或 or 开始,那么会自动把这个 and 或者 or
取掉。
21.使用Mybatis的Mapper接口调用时有哪些要求?
标签:总结,语句,映射,数据库,知识,接口,sql,Mybatis From: https://blog.csdn.net/weixin_69052332/article/details/142431671(1)Mapper接口名和mapper.xml中定义的每个sql的id相同。
(2)Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql的parameterType类型相同。
(3)Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同。
(4)Mapper.xml文件中的namespace即是mapper接口的类路径。