MyBatis实现SQL映射文件
作者:花落随风轻飘舞
1 SQL 映射文件介绍
映射器是 MyBatis 中最复杂并且是最重要的组件。它由一个接口和 SQL 映射文件(或者注解)组成。在映射器中我们可以配置各类 SQL、动态 SQL、缓存、存储过程、级联等复杂的内容。
以下是 SQL 映射文件的部分元素介绍
元素 | 描述 |
---|---|
cache | 该命名空间的缓存配置 |
cache-ref | 引用其它命名空间的缓存配置 |
resultMap | 描述如何从数据库结果集中加载对象,它是最复杂也是最强大的元素 |
sql | 可被其它语句引用的可重用语句块 |
select | 映射查询语句 |
insert | 映射插入语句 |
update | 映射更新语句 |
delete | 映射删除语句 |
2 select 元素
select 元素表示 SQL 的 select 语句,用于查询,以下是 select 元素的部分属性
属性 | 描述 |
---|---|
id | 在命名空间中唯一的标识符,可以被用来引用这条语句 |
parameterType | 将会传入这条语句的参数类的全类名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器(TypeHandler) 推断出具体传入语句的参数,默认值为未设置(unset) |
resultType | 从这条语句中返回的期望类型的类的全类名或别名。 注意如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身。可以使用 resultType 或 resultMap,但不能同时使用 |
resultMap | 外部 resultMap 的命名引用。结果集的映射是 MyBatis 最强大的特性,如果你对其理解透彻,许多复杂映射的情形都能迎刃而解。可以使用 resultMap 或 resultType,但不能同时使用 |
flushCache | 将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:false |
useCache | 将其设置为 true 后,将会导致本条语句的结果被二级缓存缓存起来,默认值:对 select 元素为 true |
timeout | 这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为未设置(unset)(依赖驱动) |
fetchSize | 这是一个给驱动的提示,尝试让驱动程序每次批量返回的结果行数和这个设置值相等。 默认值为未设置(unset)(依赖驱动) |
statementType | STATEMENT,PREPARED 或 CALLABLE 中的一个。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED |
resultSetType | FORWARD_ONLY,SCROLL_SENSITIVE, SCROLL_INSENSITIVE 或 DEFAULT(等价于 unset) 中的一个,默认值为 unset (依赖驱动) |
databaseId | 如果配置了数据库厂商标识 (databaseIdProvider) 并且存在两个相同的语句,一个带 databaseId 而另一个不带,MyBatis 会优先加载带有 databaseId 的语句。如果 databaseId 与当前数据库匹配,则不带 databaseId 的相同语句将被忽略。未设置 databaseId 使用通用 SQL 规则 |
resultOrdered | resultOrdered:这个设置仅对嵌套结果 select 语句适用:如果为 true,就是假设包含了嵌套结果集或是分组,这样的话当返回一个主结果行的时候,就不会发生有对前面结果集的引用的情况。 这就使得在获取嵌套的结果集的时候不至于导致内存不够用。默认值:false |
resultSets | 这个设置仅对多结果集的情况适用。它将列出语句执行后返回的结果集并给每个结果集一个名称,名称是逗号分隔的 |
3 insert 元素
属性 | 描述 |
---|---|
id | 在命名空间中唯一的标识符,可以被用来引用这条语句 |
parameterType | 将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset) |
flushCache | 将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:(对 insert、update 和 delete 语句)true |
timeout | 这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为未设置(unset)(依赖数据库驱动) |
statementType | 可选 STATEMENT,PREPARED 或 CALLABLE。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED |
useGeneratedKeys | (仅适用于 insert 和 update)这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server 这样的关系型数据库管理系统的自动递增字段),默认值:false |
keyProperty | (仅适用于 insert 和 update)指定能够唯一识别对象的属性,MyBatis 会使用 getGeneratedKeys 的返回值或 insert 语句的 selectKey 子元素设置它的值,默认值:未设置(unset)。如果生成列不止一个,可以用逗号分隔多个属性名称。不能和keyColumn连用 |
keyColumn | (仅适用于 insert 和 update)设置生成键值在表中的列名,在某些数据库(像 PostgreSQL)中,当主键列不是表中的第一列的时候,是必须设置的。如果生成列不止一个,可以用逗号分隔多个属性名称。不能和keyProperty连用 |
databaseId | 同 select 元素 |
主键回填
在 MyBatis 中,若表中的主键设置为自增,插入数据时没有插入主键,但是又想获得数据库中该条数据的主键,那么可以通过设置 useGeneratedKeys=”true”,然后再把 keyProperty 设置到目标属性(如 User 类中的 id 属性)上来获得该值。
<insert id="insertUser" parameterType="com.entity.User" useGeneratedKeys="true" keyProperty="id"> insert into person(name, age, sex) values (#{name}, #{age}, #{sex}); </insert>
//添加一个用户数据 @Test public void testInsertUser() { String statement = "com.mapper.UserMapper.insertUser"; User user = new User(); user.setName("孙尚香"); user.setAge(24); user.setSex("女"); int i = sqlSession.insert(statement, user); System.out.println( (i>0)? "添加成功!":"添加失败!"); //提交插入的数据 sqlSession.commit(); sqlSession.close(); // 输出返回的主键值 System.out.println("返回的主键值=" + user.getId()); }
自定义主键并且可以在 Java 中通过属性获得该值
在 MyBatis 中可以通过 selectKey 元素自定义主键,以下是其属性介绍
- keyProperty:selectKey 需要设置的目标属性
- resultType:结果类型
- order:可以设置为 BEFORE 或 AFTER ,表示先设置主键,后执行插入语句或先执行插入语句,后设置主键
<insert id="insertUser" parameterType="com.entity.User" > <selectKey keyProperty="id" resultType="int" order="BEFORE"> select ROUND(RAND()*1000) </selectKey> insert into person(id, name, age, sex) values (#{id}, #{name}, #{age}, #{sex}); </insert>
@Test public void testInsertUser() { String statement = "com.mapper.UserMapper.insertUser"; User user = new User(); user.setName("郑旦"); user.setAge(24); user.setSex("女"); int i = sqlSession.insert(statement, user); System.out.println( (i>0)? "添加成功!":"添加失败!"); //提交插入的数据 sqlSession.commit(); sqlSession.close(); // 输出返回的主键值 System.out.println("返回的主键值=" + user.getId()); }
4 update 和 delete 元素
update 和 delete 元素在使用上比较简单,所以这里把它们放在一起论述。它们和 insert 元素的属性差不多,执行完后也会返回一个整数,用来表示该 SQL 语句影响了多少条数据库记录。
<!-- 根据 id 更新用户 --> <update id="updateUser"> update person set name = #{name}, age = #{age},sex = #{sex} where id = #{id} </update> <!-- 根据 id 删除用户 --> <delete id="deleteUser" parameterType="int"> delete from person where id = #{id} </delete>
5 sql 元素
sql 元素是用来定义可重用的 sql 代码片段,这样在字段比较多的时候,以便在其它语句中使用。需要结合 include 元素一起使用,以下是代码示例。
<!--定义sql代码片段--> <sql id="userCols"> id,username,age,sex </sql> <!-- 查询所有用户 --> <select id="selectAllUser" resultType="com.entity.User"> select <include refid="userCols"/> from person </select>
6 parameterType 元素
parameterType 元素可以输入以下类型:
- Java 基本数据类型
- POJO 类型
- Map 类型
<!-- 通过 普通数据类型 int 查询一个用户 --> <select id="selectUserById" parameterType="int" resultType="com.entity.User"> select * from person where id = #{id}; </select> <!-- 通过 POJO 类型 User 添加用户--> <insert id="insertUser" parameterType="com.entity.User"> insert into person(id,username,age,sex) values (#{id},#{username},#{age},#{sex}); </insert> <!-- 通过 嵌套 POJO 类型 查询一个用户,QueryVo 类中定义了 User user 属性 --> <select id="selectUserByUserNameAndAge" parameterType="com.entity.QueryVo" resultType="com.entity.User"> select * from person where name = #{user.name} and age = #{user.age}; </select> <!-- 通过 Map 类型 查询一个用户, HashMap<String, Object> map = new HashMap<>(); map.put("name","赵飞燕"); map.put("age",24); 通过 key 获得 map 中的 value--> <select id="selectUserByMap" parameterType="hashmap" resultType="com.entity.User"> select * from person where name = #{name} and age = #{age}; </select>
7 resultType 元素
resultType 元素和 parameterType 元素用法差不多,一个是输出,一个是输入。resultType 元素可以输出以下类型:
- Java 基本数据类型
- POJO 对象
- POJO 对象列表
- Map 对象列表
<!-- 统计用户总数量,输出为一个整数 int --> <select id="countUsers" resultType="int"> select count(1) from person </select> <!-- 通过 id 查询一个用户,输出为一个 User --> <select id="selectUserById" parameterType="int" resultType="com.entity.User"> select * from personwhere id = #{id}; </select> <!-- 查询所有用户,输出为一个 List<User> 列表 --> <select id="selectAllUser" resultType="com.entity.User"> select * from person </select> <!-- 查询所有用户, 输出为一个 List<HashMap<String, Object>> Map 列表--> <select id="selectAllUser" resultType="hashmap"> select * from person </select>
8 resultMap 元素(重要)
我们在使用 resultType 的时候,需要保证数据库表中的字段名和表对应实体类的属性名称一致才行(包括驼峰命名规则)。那不一致怎么办,查询的时候可以给列名起个别名,但是一般不建议这样做,而是通过 resultMap 元素进行一个转换。
<!-- id:唯一标识,type:需要映射的 Java 类型--> <resultMap id="userMap" type="com.entity.User"> <!-- 与主键字段的对应,property对应实体属性,column对应表字段 --> <id property="userId" column="id"/> <!-- 与非主键字段的对应,property对应实体属性,column对应表字段 --> <result property="userName" column="username"/> <result property="userAge" column="age"/> <result property="userSex" column="sex"/> </resultMap> <!-- 查询所有用户,返回集为resultMap类型,resultMap的value上面配置的 id=userMap 要一致--> <select id="selectAllUser" resultMap="userMap"> select * from person </select>
上述代码是不是很眼熟,在 MyBatis 案例中使用了 @ResultMap 注解来实现上述代码
resultMap 元素的组成
<!-- autoMapping:指定是否自动映射查询结果的列到 Java 对象的属性。 默认为开启(true),如果设置为 false,则需要手动配置每个属性的映射关系 --> <resultMap id="标识" type="输出类型" extends="继承其他 <resultMap>" autoMapping="自动映射"> <constructor><!--构造器注入属性值--> <!-- 构造器标识,一般为主键 --> <!-- column对应表字段,name对应实体属性 --> <idArg column="id" name="userId" javaType="int"/> <!-- 构造器参数 --> <arg column="username" name="userName" javaType="string"/> </constructor> <!-- id 与主键字段的对应,property对应实体属性,column对应表字段 --> <id property="userId" column="id"/> <!-- result 与非主键字段的对应,property对应实体属性,column对应表字段 --> <result property="userName" column="username"/> <association/><!--高级映射,一对一映射--> <collection /><!--高级映射,一对多映射--> <discriminator> <case/> </discriminator><!--根据返回的字段的值封装不同的类型--> </resultMap>
9 参考文档
到此这篇关于MyBatis实现SQL映射文件的文章就介绍到这了,更多相关MyBatis SQL映射文件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!