Java经典面试题汇总:Mybatis
MyBatis是Java中一款非常流行的持久层框架,是Apache下的一个开源项目,它提供了使用Java对象来映射数据库操作的ORM框架,封装了原始的JDBC访问,让使用者能够更加方便的使用数据库。本篇文章将介绍MyBatis常见的面试题及其详细解析。
1. MyBatis的使用及原理
1.1 MyBatis的使用
- 首先在项目中引入MyBatis相关的依赖:
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
- 在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/test"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapper/StudentMapper.xml"/>
</mappers>
</configuration>
- 创建Mapper映射文件,例如StudentMapper.xml:
<mapper namespace="com.example.mapper.StudentMapper">
<select id="findById" parameterType="int" resultType="com.example.pojo.Student">
select * from student where id = #{id}
</select>
</mapper>
- 创建Mapper接口,例如StudentMapper.java:
public interface StudentMapper {
Student findById(int id);
}
- 在SpringBoot主类中添加Mapper扫描注解:
@SpringBootApplication
@MapperScan("com.example.mapper")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
- 在Service层中注入Mapper并调用方法:
@Service
public class StudentService {
@Autowired
private StudentMapper studentMapper;
public Student findById(int id) {
return studentMapper.findById(id);
}
}
1.2 MyBatis的原理
MyBatis框架主要由以下几部分组成:SqlSessionFactory、SqlSession、Executor、StatementHandler、ParameterHandler、ResultSetHandler、MappedStatement和Configuration。
- SqlSessionFactory:SqlSessionFactory是MyBatis的核心接口,用于创建SqlSession对象;
- SqlSession:SqlSession是执行持久化操作的核心接口,它提供了很多方法,例如查询、新增、修改和删除操作;
- Executor:Executor是MyBatis引擎中最核心的对象,提供了事务管理和执行SQL语句的功能;
- StatementHandler:StatementHandler是执行SQL语句的核心对象,提供了操作SQL语句的各种方法;
- ParameterHandler:ParameterHandler是处理SQL参数的核心对象,提供了操作SQL参数的各种方法;
- ResultSetHandler:ResultSetHandler是处理结果集的核心对象,提供了操作结果集的各种方法;
- MappedStatement:MappedStatement是执行SQL语句的映射对象,提供了SQL语句、输入参数和输出结果的各种信息;
- Configuration:Configuration是MyBatis配置信息对象,提供了MyBatis配置信息的各种设置。
2. MyBatis的优化
2.1 使用缓存
MyBatis中的缓存分为一级缓存和二级缓存。一级缓存是SqlSession级别的缓存,查询结果会自动缓存到SqlSession中;二级缓存是Mapper级别的缓存,查询结果会缓存到二级缓存中,多个SqlSession共享这个缓存。使用缓存能够提高查询效率。
一级缓存示例:
public class StudentMapperTest {
private SqlSession sqlSession;
@Before
public void before() throws Exception {
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder()
.build(Resources.getResourceAsStream("mybatis-config.xml"));
sqlSession = sessionFactory.openSession();
}
@Test
public void testFindById() throws Exception {
StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
Student student1 = studentMapper.findById(1);
Student student2 = studentMapper.findById(1);
System.out.println(student1 == student2); // true
}
}
二级缓存示例:
<cache eviction="LRU" flushInterval="60000" size="512" readOnly="true"/>
2.2 关闭日志
MyBatis框架默认会输出sql语句和参数,可以通过配置关闭日志来提高查询效率:
<configuration>
<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>
</configuration>
2.3 使用连接池
MyBatis框架默认使用的是简单的JDBC连接池,可以通过使用第三方的连接池来提高效率,例如:Druid连接池、HikariCP连接池。
3. MyBatis的动态SQL
MyBatis的动态SQL是指在执行SQL语句时,可以根据条件进行判断,生成不同的SQL语句,从而实现动态的SQL查询。
3.1 if标签
if标签可以根据条件来判断是否生成SQL语句:
<select id="findByName" resultType="com.example.pojo.Student">
select * from student where 1=1
<if test="name != null">
and name = #{name, jdbcType=VARCHAR}
</if>
<if test="sex != null">
and sex = #{sex, jdbcType=VARCHAR}
</if>
</select>
3.2 choose标签
choose标签可以根据条件判断生成不同的SQL语句:
<select id="findByCondition" parameterType="com.example.pojo.Student"
resultType="com.example.pojo.Student">
select * from student
<where>
<choose>
<when test="name != null">
and name = #{name, jdbcType=VARCHAR}
</when>
<when test="sex != null">
and sex = #{sex, jdbcType=VARCHAR}
</when>
<otherwise>
and 1=1
</otherwise>
</choose>
</where>
</select>
3.3 foreach标签
foreach标签可以遍历集合生成多个SQL语句:
<delete id="deleteByIds" parameterType="java.util.List">
delete from student
where id in
<foreach collection="list" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
4. MyBatis的乐观锁
MyBatis的乐观锁指通过版本号的方式来实现数据库的同步更新,具有防止高并发多次操作的特点。
4.1 乐观锁的使用
在实体类中添加版本号字段:
public class Student {
private int id;
private String name;
private String sex;
private int version;
//getter和setter方法
}
在Mapper映射文件中添加更新方法:
<update id="updateNameByVersion" parameterType="com.example.pojo.Student">
update student set name = #{name, jdbcType=VARCHAR},
version = #{version} + 1
where id = #{id} and version = #{version}
</update>
在Service层中调用更新方法:
@Service
public class StudentService {
@Autowired
private StudentMapper studentMapper;
public boolean updateName(int id, String name) {
Student student = studentMapper.findById(id);
student.setName(name);
return studentMapper.updateNameByVersion(student) > 0;
}
}
4.2 乐观锁的实现原理
MyBatis的乐观锁通过在执行更新操作时,自动判定版本号是否匹配,如果不匹配则自动回滚整个事务,从而达到同步更新数据的目的。MyBatis乐观锁的实现,是通过在更新数据库表时,在where子句中添加版本号验证的SQL语句来实现的。当多个线程同时更新一行数据时,只有其中一个线程能够成功更新,其他线程则会出现版本号不匹配的情况,导致更新失败,从而实现同步更新数据的目的。
总结
本文从MyBatis的使用、原理、优化、动态SQL和乐观锁几个方面,讲解了MyBatis常见的面试题。MyBatis是Java中非常流行的持久层框架,通过本文中的学习,相信大家对MyBatis的使用和原理都有了更深入的了解。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java经典面试题汇总:Mybatis - Python技术站