做暖暖视频网站大全/朋友圈广告投放
MyBatis 是一个流行的Java持久层框架,它提供了简单和直观的方法来处理数据库操作。相比于传统的JDBC操作,MyBatis通过XML或注解方式映射Java对象与数据库之间的关系,极大地简化了数据库编程工作。除了基本的数据映射和SQL语句执行功能,MyBatis还提供了一些高级特性来支持复杂的数据库操作和优化性能。下面是一些MyBatis的高级特性:
动态SQL
MyBatis 允许构建动态SQL语句,根据不同条件动态改变SQL执行逻辑,这对于复杂查询条件的情况下非常有用。可以使用<if>
、<choose>
、<when>
、<otherwise>
等元素在XML映射文件中定义动态SQL。
MyBatis 的动态SQL是一种强大的功能,它允许开发者在XML映射文件中根据不同的条件构建灵活的SQL语句。这种能力使得管理复杂查询逻辑变得简单,特别是当查询条件的存在依赖于用户输入或业务逻辑时。通过使用特定的XML标签,你可以在SQL语句中插入条件判断、循环等逻辑结构,从而动态地生成最终的SQL语句。下面是一些常用的动态SQL元素及其用法:
1. <if>
标签
<if>
标签允许你根据条件判断是否包含某段SQL代码。这在你需要基于不同条件构建查询语句时非常有用。
<select id="findActiveUsers" resultType="User">SELECT * FROM usersWHERE 1=1<if test="name != null">AND name = #{name}</if><if test="email != null">AND email = #{email}</if>
</select>
在这个例子中,只有当name
和email
非null
时,相应的条件才会被包括在内。
2. <choose>
, <when>
, <otherwise>
标签
这组标签类似于Java中的switch-case
语句,允许你在多个条件中选择一个执行。
<select id="findUserStatus" resultType="String">SELECT status FROM usersWHERE id = #{id}<choose><when test="name != null">AND name = #{name}</when><when test="email != null">AND email = #{email}</when><otherwise>AND name = 'unknown'</otherwise></choose>
</select>
这个例子中,根据条件选择不同的SQL片段。如果name
非null
,使用name
作为条件;如果name
为null
且email
非null
,使用email
作为条件;否则,使用默认值。
3. <where>
标签
<where>
标签用于动态插入WHERE
语句,如果其中包含的条件都未满足(即没有条件被包括),则整个<where>
标签不会产生任何输出。如果有条件满足,<where>
会自动处理前导的AND
或OR
。
<select id="findUsersByConditions" resultType="User">SELECT * FROM users<where><if test="name != null">AND name = #{name}</if><if test="email != null">AND email = #{email}</if></where>
</select>
4. <set>
标签
<set>
标签用于动态更新语句中的字段,自动处理列表中的前导逗号问题。
<update id="updateUser">UPDATE users<set><if test="name != null">name = #{name},</if><if test="email != null">email = #{email},</if></set>WHERE id = #{id}
</update>
在这个例子中,只有当name
或email
非null
时,相应的字段才会被更新。
通过这些动态SQL特性,MyBatis 让复杂的SQL语句构建变得灵活和简洁,有助于提高SQL的维护性和可读性。
映射结果集到Java对象
MyBatis 支持高级的结果映射特性,可以将数据库的结果集映射到Java对象中,包括简单Java对象(POJOs)、集合、嵌套对象等。
MyBatis 的结果映射特性允许开发者以灵活的方式将数据库查询的结果集直接映射到Java对象中。这大大简化了数据处理逻辑,避免了传统JDBC编程中繁琐的手动结果集处理。MyBatis 支持多种映射策略,包括简单的直接映射到Java对象、映射到Java集合、以及更复杂的嵌套映射等。下面详细解释这些特性:
简单映射到POJOs
最基本的映射是将查询结果的每一行映射到一个Java对象(通常是POJO - Plain Old Java Object)中。每列的值将填充到对象的属性中,通常通过名字匹配或显式指定映射关系来实现。
<select id="selectUsers" resultType="com.example.User">SELECT id, name, email FROM users
</select>
在这个例子中,selectUsers
查询的结果会被自动映射到com.example.User
类的实例中,假设User
类有id
、name
、和email
属性。
集合映射
MyBatis 也支持直接将结果映射到Java集合类型,例如List
、Set
等。这对于返回多行数据的查询尤其有用。
<select id="selectAllUsers" resultType="com.example.User">SELECT id, name, email FROM users
</select>
这个查询将返回一个User
对象的List
,每个对象对应结果集中的一行。
嵌套映射
MyBatis 允许进行复杂的嵌套映射,这对于处理具有一对多或多对多关系的数据特别有用。你可以在一个对象中嵌套另一个对象或对象的集合。
<select id="selectUsersWithPosts" resultMap="userResultMap">SELECT u.id, u.name, u.email, p.id as post_id, p.title, p.contentFROM users uLEFT JOIN posts p ON u.id = p.user_id
</select><resultMap id="userResultMap" type="com.example.User"><id property="id" column="id" /><result property="name" column="name" /><result property="email" column="email" /><collection property="posts" ofType="com.example.Post"><id property="id" column="post_id" /><result property="title" column="title" /><result property="content" column="content" /></collection>
</resultMap>
在这个例子中,selectUsersWithPosts
查询不仅加载用户信息,而且还加载每个用户的帖子列表。resultMap
定义了如何将查询结果映射到User
对象及其内部的Post
对象集合中。
高级结果映射特性
MyBatis 的结果映射还支持其他高级特性,包括但不限于:
- 自动映射: 自动根据数据库列名和Java对象属性名的匹配程度来填充对象。
- 构造方法映射: 允许使用查询结果中的列作为参数来调用目标对象的构造函数。
- 枚举类型处理: 可以将数据库中的值映射到Java枚举类型。
- 自定义类型处理器: 对于非标准的映射关系,可以通过实现
TypeHandler
接口自定义映射逻辑。
通过这些高级映射特性,MyBatis 不仅可以处理简单的数据映射场景,还能轻松应对复杂的数据结构和关系映射,极大地提高了数据处理的效率和灵活性。
延迟加载:
MyBatis 支持延迟加载技术(懒加载),可以在关联对象被访问时才加载数据,这有助于提高应用性能,特别是对于数据量大的情况。
延迟加载(懒加载)是一种在软件开发中常用的优化技术,特别是在处理数据库操作和对象关系映射(ORM)时。在MyBatis中,延迟加载指的是只有在真正需要使用到关联对象的数据时,才执行相应的SQL查询来加载这些数据,而不是在加载主对象时就立即加载所有关联的对象。这种方式可以显著提高应用的性能,尤其是在处理复杂的对象关系和大量数据时。
如何工作
MyBatis的延迟加载依赖于代理对象。当加载一个对象时,MyBatis会为那些配置了延迟加载的关联对象创建代理(Proxy)对象。这些代理对象在外观上与实际对象相同,但在内部包含了加载实际对象所需的所有信息。当程序第一次访问代理对象的任何属性或方法时,代理对象会触发一个真实的数据库查询来加载实际的对象,然后将请求转发给这个新加载的对象。
配置延迟加载
在MyBatis中配置延迟加载需要在全局配置文件(mybatis-config.xml)中进行设置,并且还可以精细控制哪些关联应该延迟加载。
<settings><!-- 开启全局的延迟加载 --><setting name="lazyLoadingEnabled" value="true" /><!-- 将所有关联对象设置为懒加载 --><setting name="aggressiveLazyLoading" value="false" />
</settings>
lazyLoadingEnabled
:启用或禁用延迟加载。aggressiveLazyLoading
:当这个配置项为true
时,任何关联对象的访问都会加载该对象的所有懒加载属性。为false
时,每个属性会按需加载。
使用场景举例
考虑一个博客应用中的User
和Post
对象。一个用户可能有成百上千篇博客帖子,如果在加载User
对象时立即加载所有Post
对象,将会非常低效,尤其是在只需要用户信息而不需要帖子信息的场景下。通过配置延迟加载,MyBatis可以在首次访问用户的posts
属性时才加载这些帖子。
<resultMap id="userResultMap" type="User"><id property="id" column="id" /><result property="username" column="username" /><collection property="posts" ofType="Post" select="selectPostsByUserId" column="id" lazy="true"/>
</resultMap><select id="selectPostsByUserId" resultType="Post">SELECT * FROM posts WHERE userId = #{id}
</select>
在这个配置中,posts
集合被标记为懒加载,这意味着在User
对象被加载后,与之关联的Post
对象将只有在实际访问posts
属性时才会被加载。
优点与局限
延迟加载最大的优点是提高了应用性能,特别是在数据模型复杂或数据量大时。但也有一些局限,比如延迟加载可能会导致N+1查询问题,即每访问一个对象的延迟加载属性就会执行一个新的SQL查询。此外,对于代理对象的管理和理解也需要开发者有一定的了解,以避免潜在的问题。正确使用延迟加载特性需要权衡利弊,并在特定的应用场景下做出合理的决策。
缓存
MyBatis 内置了一级缓存(SqlSession级别)和二级缓存(mapper级别)功能,可以显著提高应用性能通过减少数据库查询次数。
MyBatis提供的缓存功能是其强大特性之一,旨在通过减少对数据库的查询次数来提高应用性能。MyBatis有两级缓存:一级缓存和二级缓存,它们在不同的层面上工作,提供了不同级别的数据缓存。
一级缓存(SqlSession级别)
一级缓存是MyBatis的默认缓存,它的作用范围限定在SqlSession内。当在同一个SqlSession中执行相同的SQL查询时,第一次查询后的结果会被缓存起来,后续相同的查询就可以直接从缓存中获取结果,而不需要再次访问数据库。一级缓存默认是开启的,无需特别配置。
工作原理:
- 当执行一个SQL查询时,MyBatis会先查看一级缓存中是否有该查询的结果。
- 如果有,则直接从缓存中返回结果;如果没有,则执行数据库查询,并将查询结果存入缓存。
- 当在同一个SqlSession中执行任何写操作(插入、更新、删除)或调用
SqlSession.clearCache()
时,一级缓存会被清空,以保证缓存数据的一致性。
限制:
- 一级缓存的作用域仅限于当前SqlSession,不同的SqlSession之间无法共享缓存。
- 在分布式系统中,一级缓存可能会导致数据不一致的问题。
二级缓存(Mapper级别)
二级缓存的作用范围更广,它是基于namespace的,可以被同一个Mapper接口的不同实例共享。也就是说,二级缓存可以跨SqlSession共享数据,适用于多个SqlSession对同一数据的读操作较多的情况。
开启二级缓存:
- 在mybatis-config.xml中全局开启二级缓存:
<settings><setting name="cacheEnabled" value="true"/> </settings>
- 在Mapper.xml文件中配置使用二级缓存:
<mapper namespace="com.example.mapper.UserMapper"><cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>... </mapper>
配置选项:
eviction
:缓存回收策略,如FIFO(先进先出)、LRU(最近最少使用)等。flushInterval
:缓存刷新间隔,单位是毫秒。size
:引用数目,即缓存中可以存储多少个对象。readOnly
:是否只读。只读缓存会给所有调用者返回相同的实例,因此它们不应该被修改。
注意:
- 使用二级缓存时,需要考虑数据的一致性问题。在更新数据时,相关的缓存需要被清除,以避免脏读。
- 对于频繁变动的数据,使用二级缓存可能会带来更多的维护成本。
小结
通过合理使用一级和二级缓存,可以显著提高应用的读取性能,减少对数据库的访问次数。但是,同时也需要注意缓存数据的一致性和时效性,避免出现脏读或数据过时的问题。在设计应用时,应该根据实际需求和数据访问模式来决定是否以及如何使用MyBatis的缓存功能。
批量操作
MyBatis 支持批量操作,允许在一个会话中执行多个更新操作,这可以大幅提高数据批处理的效率。
MyBatis支持批量操作,这是一个优化数据库交互性能的重要特性,尤其是当你需要在单个会话中执行多个插入、更新或删除操作时。通过批量操作,可以将多个操作合并成一次数据库交云,减少网络往返次数,从而显著提高数据处理的效率。
批量操作的实现方法
在MyBatis中实现批量操作通常有两种方法:
-
使用
foreach
标签: 在Mapper的XML文件中,使用foreach
标签来遍历一个集合,并为集合中的每个元素生成相应的SQL语句。 -
使用批处理执行器(
ExecutorType.BATCH
): 配置MyBatis使用批处理执行器来执行会话。这种方式可以直接利用JDBC的批处理能力,适用于大量的插入或更新操作。
使用foreach
标签
这种方法适用于执行相同的SQL语句多次,但每次执行时使用的参数不同。在Mapper XML中定义时,可以这样使用:
<insert id="insertUsers" parameterType="list">INSERT INTO users (name, email) VALUES<foreach collection="list" item="user" separator=",">(#{user.name}, #{user.email})</foreach>
</insert>
这里,foreach
会遍历传入的列表(假设是用户对象的列表),为列表中的每个用户生成一个插入操作。这样做虽然可以一次性插入多条记录,但实际上是生成了一条包含多个VALUES
子句的SQL语句,并非数据库层面的批处理。
使用批处理执行器
要使用JDBC批处理,你需要调整SqlSessionFactory的配置,使其使用ExecutorType.BATCH
。在Spring配置中,可以通过以下方式设置:
@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();sessionFactory.setDataSource(dataSource());sessionFactory.setTypeAliasesPackage("com.example.domain");// 其他配置 ...// 设置为BATCH模式sessionFactory.setExecutorType(ExecutorType.BATCH);return sessionFactory.getObject();
}
使用批处理执行器时,可以在Mapper接口中定义插入或更新方法,然后在Service层循环调用这些方法。最后,需要手动提交SqlSession以执行批处理:
List<User> users = // ... 获取用户列表
try (SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH)) {UserMapper mapper = session.getMapper(UserMapper.class);for (User user : users) {mapper.insertUser(user);}session.commit();
}
在这种模式下,每个insertUser
调用并不会立即执行,而是将所有操作积累起来,在session.commit()
时以批处理方式一次性执行,这大大减少了数据库的访问次数和网络延迟,提高了效率。
注意事项
- 在使用批处理时,应注意批量操作可能对数据库性能的影响。大量的数据操作可能会导致数据库暂时锁定或事务日志迅速增长,应根据实际情况调整批量操作的大小。
- 批处理执行器在执行批处理操作时不会立即返回每条语句的执行结果,因此,如果批处理中某个操作失败,可能需要特别的错误处理逻辑来处理或回滚事务。
- 使用批处理执行器时,MyBatis会为每次操作缓存预处理语句(PreparedStatement),直到调用
commit
或flushStatements
。因此,进行大批量操作时应注意内存使用情况。
插件
MyBatis 允许使用插件来拦截映射语句的执行,这使得开发者可以在SQL执行过程中插入自定义逻辑,增加了框架的灵活性。
MyBatis的插件系统是一个强大的特性,它允许开发者在MyBatis的核心处理流程中的某些点插入自定义逻辑。通过实现Interceptor
接口,并使用@Intercepts
注解标记,可以创建插件来拦截执行过程中的方法调用,比如SQL语句的执行、参数的设置、结果的映射等。这种能力使得开发者可以不修改MyBatis内部实现的情况下,扩展其功能,例如添加日志、修改SQL语句、测量查询执行时间等。
如何创建MyBatis插件
-
实现Interceptor接口: MyBatis提供了
org.apache.ibatis.plugin.Interceptor
接口,你需要实现这个接口的intercept
方法来定义你的拦截逻辑。 -
使用@Intercepts注解: 使用这个注解来标明你想要拦截的目标方法。这包括目标方法所在的接口和方法名,以及方法参数类型。
-
配置插件: 在MyBatis配置文件中注册你的插件,这样MyBatis启动时就会加载并应用它。
示例
以下是一个简单的MyBatis插件示例,该插件用于拦截所有的Executor
接口的update
方法调用(这包括了INSERT、UPDATE和DELETE操作),并在操作执行前后打印日志。
@Intercepts({@Signature(type= Executor.class,method = "update",args = {MappedStatement.class, Object.class})
})
public class ExamplePlugin implements Interceptor {@Overridepublic Object intercept(Invocation invocation) throws Throwable {// 在SQL执行前打印日志System.out.println("Before executing update: " + Arrays.toString(invocation.getArgs()));// 执行原方法(即继续执行SQL操作)Object result = invocation.proceed();// 在SQL执行后打印日志System.out.println("After executing update, result: " + result);// 返回原方法执行的结果return result;}@Overridepublic Object plugin(Object target) {// 用Plugin.wrap方法来创建目标对象的代理,用于拦截目标方法的执行return Plugin.wrap(target, this);}@Overridepublic void setProperties(Properties properties) {// 可以接收配置文件中的属性}
}
插件注册
在MyBatis的配置文件mybatis-config.xml
中注册上述插件:
<plugins><plugin interceptor="com.example.ExamplePlugin"/>
</plugins>
注意事项
- 插件可以拦截的方法包括:
Executor
的方法、ParameterHandler
的方法、ResultSetHandler
的方法和StatementHandler
的方法。 - 通过拦截器,可以修改方法的参数、中断方法的执行或在方法执行前后添加自定义逻辑。
- 插件应该尽量做到轻量和无侵入性,避免影响MyBatis的正常功能和性能。
- 多个插件会形成一个拦截链,按照它们在配置文件中的声明顺序执行。开发者需要注意插件之间的相互作用和潜在的冲突。
通过利用MyBatis的插件机制,开发者可以非常灵活地扩展MyBatis的功能,使其更好地满足特定项目的需求。
注解支持
除了XML映射文件,MyBatis也支持使用Java注解来映射SQL语句,这使得代码更简洁,减少了配置的复杂度。
MyBatis的注解支持为开发者提供了一种更加简洁直观的方式来定义SQL映射,避免了编写大量的XML配置文件。通过在Mapper接口中直接使用注解来指定SQL语句,可以使代码更加紧凑和易于理解,特别是在SQL语句不是特别复杂时。下面介绍MyBatis中常用的几种注解及其用法。
@Select、@Insert、@Update、@Delete
这四个注解分别对应数据库的查询、插入、更新和删除操作。通过这些注解,可以直接在Mapper接口的方法上定义对应的SQL语句。
@Mapper
public interface UserMapper {@Select("SELECT * FROM users WHERE id = #{id}")User selectUser(int id);@Insert("INSERT INTO users(name, email) VALUES(#{name}, #{email})")@Options(useGeneratedKeys = true, keyProperty = "id")int insertUser(User user);@Update("UPDATE users SET name = #{name}, email = #{email} WHERE id = #{id}")int updateUser(User user);@Delete("DELETE FROM users WHERE id = #{id}")int deleteUser(int id);
}
@Param
当方法有多个参数时,可以使用@Param
注解给每个参数命名,以便在SQL语句中引用。
@Select("SELECT * FROM users WHERE name = #{name} AND email = #{email}")
User findUserByNameAndEmail(@Param("name") String name, @Param("email") String email);
@Results 和 @Result
这两个注解用于结果映射,将SQL查询的结果集映射到Java对象或对象集合中。@Results
用于定义结果集的映射关系,@Result
用于指定单个字段的映射。
@Results({@Result(property = "id", column = "id"),@Result(property = "name", column = "name"),@Result(property = "email", column = "email")
})
@Select("SELECT id, name, email FROM users")
List<User> findAllUsers();
@Mapper
这是一个标记性注解,用于标识一个接口是MyBatis的Mapper接口。Spring Boot应用中,通常在启动类或配置类上使用@MapperScan
注解来自动扫描并注册Mapper接口,而不需要为每个Mapper接口添加@Mapper
注解。
使用注解的优势和限制
优势:
- 代码简洁:直接在接口方法上定义SQL,减少了XML配置的数量,使得代码更加简洁。
- 开发效率:对于简单SQL操作,使用注解可以更快速地进行开发。
限制:
- 功能限制:注解方式不支持一些XML映射中的高级特性,如动态SQL。
- 维护性:复杂的SQL语句或大量的SQL映射使用注解方式可能会降低代码的可读性和维护性。
总结
MyBatis的注解支持为开发者提供了一种便捷的SQL映射方式,特别适合于SQL逻辑简单的应用。然而,在面对复杂SQL逻辑或需要高度可配置性的场景时,XML配置方式可能更为合适。开发者可以根据实际需求和个人偏好选择使用注解还是XML进行SQL映射定义。
多数据库支持
MyBatis 通过外部配置文件支持多种数据库,便于应用在不同数据库间迁移。
MyBatis的多数据库支持特性意味着你可以轻松地将应用从一个数据库迁移到另一个数据库,或者在同一个应用中支持多种数据库。这一特性在现代多变的技术环境中尤为重要,因为它为应用提供了极大的灵活性和扩展性。以下是如何利用MyBatis实现多数据库支持的一些关键点。
1. 数据库方言的抽象
数据库之间存在差异,如SQL语法、数据类型等,这些差异被称为数据库方言。MyBatis通过外部配置文件(如XML映射文件)抽象了这些差异,使得开发者可以针对不同的数据库编写特定的SQL语句,而不需要改动Java代码。例如,针对分页功能,不同数据库的实现语句可能不同,你可以为每种数据库准备不同的SQL映射文件。
2. 配置文件的动态切换
在多数据库环境下,可以通过在应用配置(如Spring的application.properties或application.yml文件)中动态指定MyBatis的配置文件或直接指定数据库连接信息,来切换不同的数据库。例如,你可以根据不同的环境(开发、测试、生产)来加载不同的数据库配置。
3. 使用Profile定义不同数据库配置
在MyBatis的配置文件中,可以使用<environment>
标签定义不同的数据库环境(如开发、测试、生产环境),每个环境可以指定不同的数据库连接和事务管理器。然后,你可以在应用启动时,通过指定环境ID来选择使用哪个环境的配置。
<environments default="development"><environment id="development"><!-- 配置开发环境数据库连接 --></environment><environment id="test"><!-- 配置测试环境数据库连接 --></environment>
</environments>
4. 抽象数据库访问代码
为了进一步增强多数据库支持的灵活性,可以将数据库访问逻辑抽象化,例如,通过定义通用的接口和使用MyBatis的Mapper接口来实现这些通用接口。这样,即使迁移到新的数据库,也只需调整SQL映射文件或者配置文件,而不需要修改业务逻辑代码。
5. 使用数据库中间件
在一些复杂的场景下,可以考虑使用数据库中间件(如ShardingSphere)来实现数据库的抽象和透明访问,它能够在更高的层面上管理多数据库的路由、分片、读写分离等,与MyBatis配合使用,进一步提高应用的可扩展性和灵活性。
总结
MyBatis通过提供灵活的配置和映射机制,支持了多数据库环境的快速切换和迁移,这不仅减少了开发和维护成本,也为应用的扩展和迁移提供了便利。正确利用MyBatis的这一特性,可以使你的应用更加健壮,更容易适应不断变化的技术需求和业务环境。
类型处理器
MyBatis 提供了类型处理器(Type Handlers),允许你在Java类型和数据库类型之间进行自定义映射,这在处理某些特殊数据类型时非常有用。
MyBatis的类型处理器(Type Handler)是一个非常强大的特性,它允许开发者控制Java类型和数据库类型之间的映射关系。这在处理Java世界和数据库世界中不匹配的数据类型时特别有用,例如:将数据库中的日期时间类型与Java 8中的LocalDateTime
、将数据库中的枚举类型字符串与Java的枚举类型等进行转换。
工作原理
类型处理器的主要职责是:
- 从数据库结果集中获取数据时,将数据库类型转换为Java类型。
- 向数据库提交参数时,将Java类型转换为数据库类型。
MyBatis在执行SQL操作时,会自动选择合适的类型处理器来完成这种转换。
内置类型处理器
MyBatis已经为常见的Java类型提供了内置的类型处理器,例如:
- 基本数据类型及其包装类
- 字符串类型
- 日期时间类型(包括
java.util.Date
和java.sql.Timestamp
) - 枚举类型
自定义类型处理器
当内置的类型处理器无法满足需求时,你可以创建自己的类型处理器。自定义类型处理器需要实现TypeHandler
接口或继承BaseTypeHandler
类,并重写相应的方法来实现类型转换逻辑。
示例:自定义类型处理器
假设我们有一个Java枚举Gender
,表示性别,但在数据库中性别是以M
和F
的字符串形式存储的。我们可以创建一个类型处理器来处理这种映射关系:
public enum Gender {MALE, FEMALE
}@MappedTypes(Gender.class)
public class GenderTypeHandler extends BaseTypeHandler<Gender> {@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, Gender parameter, JdbcType jdbcType) throws SQLException {ps.setString(i, parameter == Gender.MALE ? "M" : "F");}@Overridepublic Gender getNullableResult(ResultSet rs, String columnName) throws SQLException {String gender = rs.getString(columnName);return "M".equals(gender) ? Gender.MALE : Gender.FEMALE;}@Overridepublic Gender getNullableResult(ResultSet rs, int columnIndex) throws SQLException {String gender = rs.getString(columnIndex);return "M".equals(gender) ? Gender.MALE : Gender.FEMALE;}@Overridepublic Gender getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {String gender = cs.getString(columnIndex);return "M".equals(gender) ? Gender.MALE : Gender.FEMALE;}
}
配置自定义类型处理器
在MyBatis配置文件中注册自定义类型处理器:
<typeHandlers><typeHandler handler="com.example.GenderTypeHandler"/>
</typeHandlers>
或者,如果你使用的是注解配置方式,并且你的类型处理器与Mapper位于同一个包或自动扫描的包下,MyBatis将自动注册这些类型处理器,无需手动配置。
使用场景
自定义类型处理器特别适用于以下场景:
- 数据库存储的枚举类型需要映射到Java枚举。
- 需要对数据库中存储的加密数据进行解密。
- 将数据库中特定格式的字符串映射到复杂的Java对象。
- 处理数据库中不存在的特殊数据类型,如JSON或XML格式的数据。
通过类型处理器,MyBatis提供了一种灵活的方式来处理数据库和Java应用之间的数据转换,使得数据库操作更加直观和类型安全。
SQL构建器
MyBatis提供了一个SQL构建器API,允许程序化地构建SQL语句,这对于动态生成复杂查询语句非常有用。
MyBatis的SQL构建器API提供了一个编程式的方式来构建SQL语句,这对于需要动态生成SQL语句的场景特别有用。这种方法提供了比XML配置或注解方式更大的灵活性,特别是对于复杂的查询条件组合或需要根据不同的业务逻辑动态改变SQL结构的情况。
使用SQL构建器的好处
- 灵活性:允许在运行时根据不同的条件动态构建SQL语句。
- 可读性:编程式的构建方式比拼接字符串更加易于理解和维护。
- 安全性:通过减少字符串拼接来构建SQL,可以降低SQL注入的风险。
SQL构建器API的关键类
SqlBuilder
:包含用于构建SQL语句各个部分的静态方法,如SELECT
、FROM
、WHERE
等。SQL
:一个实用类,提供了一种链式调用的方法来构建SQL语句。它实际上在内部使用了SqlBuilder
的方法。
示例:使用SQL构建器构建查询
下面是一个使用MyBatis SQL构建器构建动态查询的示例:
import org.apache.ibatis.jdbc.SQL;public class UserSqlBuilder {public String buildGetUsersByName(final String name) {return new SQL() {{SELECT("*");FROM("users");WHERE("name = #{name}");}}.toString();}public String buildGetUsersByConditions(final String name, final Integer age) {SQL sql = new SQL();sql.SELECT("*");sql.FROM("users");if (name != null) {sql.WHERE("name = #{name}");}if (age != null) {sql.WHERE("age = #{age}");}return sql.toString();}
}
在这个例子中,buildGetUsersByName
方法构建了一个简单的查询,而buildGetUsersByConditions
方法则展示了如何根据条件的存在动态地构建查询语句。
使用构建的SQL
构建的SQL语句可以在MyBatis的Mapper接口中使用。你需要在Mapper接口的方法上使用@SelectProvider
、@InsertProvider
、@UpdateProvider
或@DeleteProvider
注解,指定使用哪个类和方法来提供SQL语句。
@Mapper
public interface UserMapper {@SelectProvider(type = UserSqlBuilder.class, method = "buildGetUsersByName")User getUserByName(String name);@SelectProvider(type = UserSqlBuilder.class, method = "buildGetUsersByConditions")List<User> getUsersByConditions(String name, Integer age);
}
总结
MyBatis的SQL构建器API通过提供一种更加灵活和安全的方式来构建SQL语句,使得处理动态SQL变得更加简单和直接。这对于需要根据不同条件组合构建复杂查询语句的应用来说,是一个非常有用的工具。使用SQL构建器,开发者可以以编程式的方式构建SQL语句,同时避免了直接拼接SQL带来的安全风险。
这些高级特性使得MyBatis在处理复杂数据库操作时更加强大和灵活。正确利用这些特性可以极大提高开发效率和应用性能。
相关文章:

MyBatis的高级特性探索
MyBatis 是一个流行的Java持久层框架,它提供了简单和直观的方法来处理数据库操作。相比于传统的JDBC操作,MyBatis通过XML或注解方式映射Java对象与数据库之间的关系,极大地简化了数据库编程工作。除了基本的数据映射和SQL语句执行功能&#x…...

未来制造:机器人行业新质生产力提升策略
机器人行业新质生产力提升咨询方案 一、机器人行业目前发展现状及特点: 创新活跃、应用广泛、成长性强。 二、机器人企业发展新质生产力面临的痛点: 1、高端人才匮乏 2、核心技术受限 3、竞争日益国际化 4、成本控制挑战 5、用户体验提升需求 三…...

开发过程中PostgreSQL常用的SQL语句,持续更新ing
修改字段类型 -- ALTER TABLE 模式名.表明 ALTER COLUMN 字段名 TYPE 类型; alter table alarm.alarm_produce_config alter column alarm_level type int4;重置序列值 -- ALTER SEQUENCE 序列名 RESTART WITH 序列值; alter sequence enterprise_type_id_seq restart with 1…...

Linux screen命令教程:如何在一个终端窗口中管理多个会话(附实例详解和注意事项)
Linux screen命令介绍 screen是一个全屏窗口管理器,它将物理终端抽象为多个虚拟终端,每个虚拟终端都可以运行一个shell或程序。screen命令可以让你在一个终端窗口中打开多个会话,每个会话都有自己的环境,可以独立运行命令。这对于…...

Android中的本地广播与全局广播
文章目录 1. 概念介绍2. 本地广播3. 全局广播 1. 概念介绍 前文我们介绍了Android中的广播,按注册方式分为静态广播和动态广播;按接收顺序分为有序广播与无序广播 本文我们按照广播的传播范围,将广播分为本地广播和全局广播 本地广播&#x…...

Debezium日常分享系列之:Debezium2.5稳定版本之MySQL连接器配置示例和Connector参数详解
Debezium日常分享系列之:Debezium2.5稳定版本之MySQL连接器配置示例和Connector参数详解 一、MySQL 连接器配置示例二、添加连接器配置三、连接器属性四、必须的连接器配置属性五、高级 MySQL 连接器配置属性六、Debezium 连接器数据库架构历史配置属性七、用于配置…...

vue3父组件给子组件传值,并在子组件接受
1、在父组件中定义数据: 在父组件中定义需要传递给子组件的数据。 <template><div><ChildComponent :message"parentMessage" /></div> </template><script> import { defineComponent } from vue; import ChildCom…...

Python爬虫如何快速入门
写了几篇网络爬虫的博文后,有网友留言问Python爬虫如何入门?今天就来了解一下什么是爬虫,如何快速的上手Python爬虫。 一、什么是网络爬虫 网络爬虫,英文名称为Web Crawler或Spider,是一种通过程序在互联网上自动获取…...

酷开科技依托酷开系统用“平台+产品+场景”塑造全屋智能生活!
杰弗里摩尔的“鸿沟理论”中写道:高科技企业推进产品的早期市场和产品被广泛接受的主流市场之间,存在着一条巨大的“鸿沟”。“鸿沟”,指产品吸引早期接纳者后、赢得更多客户前的那段间歇,以及其中可预知和不可预知的阻碍。多数产…...

P8649 [蓝桥杯 2017 省 B] k 倍区间:做题笔记
目录 思路 代码思路 代码 推荐 P8649 [蓝桥杯 2017 省 B] k 倍区间 思路 额嗯,这道题我刚上来是想到了前缀和,但是还要判断每个子序列,我就两层for嵌套,暴力解了题。就是我知道暴力肯定过不了但是写不出来其他的[留下了苦…...

LeetCode题练习与总结:旋转图像
一、题目描述 给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。 示例 1: 输入:matrix [[1,2,3],[4,5,6],…...

如何在家中使用手机平板电脑 公司iStoreOS软路由实现远程桌面
文章目录 简介一、配置远程桌面公网地址二、家中使用永久固定地址 访问公司电脑**具体操作方法是:** 简介 软路由是PC的硬件加上路由系统来实现路由器的功能,也可以说是使用软件达成路由功能的路由器。 使用软路由控制局域网内计算机的好处:…...

【文献分享】myMUSCLE, a New Multiphysics, Multiscale Simulation Coupling Environment
题目:myMUSCLE, a New Multiphysics, Multiscale Simulation Coupling Environment 链接: https://doi.org/10.1080/00295639.2022.2148809 myMUSCLE,一种新的多物理场、多尺度仿真耦合环境 摘要 计算能力的提高使核界能够结合有关反应…...

2024年云计算使用报告,89%组织用多云,25%广泛使用生成式AI,45%需要跨云数据集成,节省成本是云首要因素
备注:本文来自Flexera2024年的云现状调研报告的翻译。原报告地址: https://info.flexera.com/CM-REPORT-State-of-the-Cloud Flexera是一家专注于做SaaS的IT解决方案公司,有30年发展历史,5万名客户,1300名员工。Flex…...

【Python操作基础】——序列
🍉CSDN小墨&晓末:https://blog.csdn.net/jd1813346972 个人介绍: 研一|统计学|干货分享 擅长Python、Matlab、R等主流编程软件 累计十余项国家级比赛奖项,参与研究经费10w、40w级横向 文…...

Vue 与 React:前端框架对比分析
🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课签约作者、上架课程《Vue.js 和 E…...

解决kubesphere流水线docker登陆错误http: server gave HTTP response to HTTPS client
kubesphere DevOps流水线中,在登录私有的harbor仓库时,报以下错误 docker login 111.230.19.120:80 -u admin -p test123. WARNING! Using --password via the CLI is insecure. Use --password-stdin. Error response from daemon: Get "https://…...

macOS安装mongoDB(homebrew)
使用 Homebrew Homebrew 是 macOS 的一个包管理器,可以非常方便地安装 MongoDB 和其他软件。如果你还没有安装 Homebrew,可以从它的官网上找到安装指令。 已安装 Homebrew的话,先更新一下homebrew brew update 你可以使用下面的命令来安装…...

免费SSL证书和付费SSL证书的区别点
背景: 在了解免费SSL证书和付费SSL证书的区别之前,先带大家了解一下SSL证书的概念和作用。 SSL证书的概念: SSL证书就是基于http超文本传输协议的延伸,在http访问的基础上增加了一个文本传输加密的协议,由于http是明…...

【SQL】1633. 各赛事的用户注册率(COUNT函数 表达式用法)
题目描述 leetcode题目:1633. 各赛事的用户注册率 Code select contest_id, round(count(*)/(select count(*) from Users)*100, 2) as percentage from Register group by contest_id order by percentage desc, contest_id ascCOUNT()函数 COUNT函数用法&#…...

【LVGL-使用SquareLine Studio设计器 】
LVGL-使用SquareLine Studio设计器 ■ 简介■ 安装■ SquareLine Studio移植到工程 ■ 简介 SquareLine Studio 设计器是一个付费软件。 ■ 安装 SquareLine Studio 设计器的下载地址 我们点击“WINDOWS”下载 SquareLine Studio 设计器,下载完成之后我们就会得到…...

将二进制数a的每一位右移b位operator.rshift(a,b)
【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 将二进制数a的 每一位右移b位 operator.rshift(a,b) [太阳]选择题 请问执行operator.rshift(4, 1)的结果为? import operator print("【显示】二进制2:",bi…...

M芯片 mac配置Vulkan环境报错 Xcode
报错: Ignoring file ‘/usr/local/Cellar/glfw/3.3.4/lib/libglfw.3.3.dylib’: found architecture ‘x86_64’, required architecture ‘arm64’ Undefined symbols: Linker command failed with exit code 1 (use -v to see invocation) 解决:重新安…...

Day23:事务管理、显示评论、添加评论
事务管理 事务的定义 什么是事务 事务是由N步数据库操作序列组成的逻辑执行单元,这系列操作要么全执行,要么全放弃执行。 事务的特性(ACID) 原子性(Atomicity):事务是应用中不可再分的最小执行体(事务中部分执行失败就会回滚 。一致性(C…...
第一篇:概述、 目录、适用范围及术语 --- IAB/MRC《增强现实(AR)广告(效果)测量指南1.0 》
第一篇:概述、目录、适用范围及术语 - IAB与MRC及《增强现实广告效果测量指南1.0》 --- 我为什么要翻译美国IAB科技公司系列标准 翻译计划 第一篇概述—IAB与MRC及《增强现实广告效果测量指南》之目录、适用范围及术语第二篇广告效…...

pytorch常用的模块函数汇总(2)
目录 torch.utils.data:数据加载和处理模块,包括 Dataset 和 DataLoader 等工具,用于加载和处理训练数据。 torchvision:计算机视觉模块,提供了图像数据集、转换函数、预训练模型等,用于计算机视觉任务。 …...

OpenAI奥特曼豪赌1.42亿破解长生不老
生物初创公司 Retro Biosciences 由山姆奥特曼投资1.42亿英镑,公司目标是延长人类寿命。 山姆奥特曼投资背景: 38 岁的奥特曼一直是科技行业的重要参与者。尽管年纪轻轻,奥特曼凭借 ChatGPT 和 Sora 等产品席卷了科技领域。奥特曼对 Reddit…...

[晕事]今天做了件晕事29;iptables
今天办了一件晕事,主机之间做ping用tcpdump抓到了ping request,但是没有看到ping reply,查看主机的arp表,路由表都没有问题,忘记看iptables的规则。虽然在tcpdump看到包,只是代表包到了二层,并不…...

2018年亚马逊云科技推出基于Arm的定制芯片实例
2018年,亚马逊云技术推出了基于Arm的定制芯片。 据相关数据显示,基于Arm的性价比比基于x86的同类实例高出40%。 这打破了对 x86 的依赖,开创了架构的新时代,现在能够支持多种配置的密集计算任务。 这些举措为亚马逊云技术的其他创…...

用搜索引擎收集信息-常用方式
1,site csdn.net (下图表示只在csdn网站里搜索java) 2,filetype:pdf (表示只检索某pdf文件类型) 表示在浏览器里面查找有关java的pdf文件 3,intitle:花花 (表示搜索网页标题里面有花…...