MyBatis中Mapper的返回值类型
ins e r t、up d ate、d e le te语句的返回值类型
对数据库执⾏修改操作时,数据库会返回受影响的⾏数。
在MyBatis(使⽤版本3.4.6,早期版本不⽀持)中insert、update、delete语句的返回值可以是Integer、Long和Boolean。在定义Mapper接⼝时直接指定需要的类型即可,⽆需在对应的<insert><update><delete>标签中显⽰声明。
对应的代码在 org.apache.ibatis.binding.MapperMethod 类中,如下:
对于insert、update、delete语句,MyBatis都会使⽤ rowCountResult ⽅法对返回值进⾏转换;
rowCountResult ⽅法会根据Mapper声明中⽅法的返回值类型来对参数进⾏转换;
对于返回类型为Boolean的情况,如果返回的值⼤于0,则返回True,否则返回False
1public Object execute(SqlSession sqlSession, Object[] args) {
2 Object result;
3switch (Type()) {
4case INSERT: {
5 Object param = vertArgsToSqlCommandParam(args);
6 result = rowCountResult(sqlSession.Name(), param));
7break;
8 }
9case UPDATE: {
10 Object param = vertArgsToSqlCommandParam(args);
11 result = rowCountResult(sqlSession.Name(), param));
12break;
13 }
14case DELETE: {
15 Object param = vertArgsToSqlCommandParam(args);
16 result = rowCountResult(sqlSession.Name(), param));
17break;
18 }
19case SELECT:
20if (urnsVoid() && method.hasResultHandler()) {
21 executeWithResultHandler(sqlSession, args);
22 result = null;
23 } else if (urnsMany()) {
24 result = executeForMany(sqlSession, args);
25 } else if (urnsMap()) {
26 result = executeForMap(sqlSession, args);
27 } else if (urnsCursor()) {
28 result = executeForCursor(sqlSession, args);
29 } else {
30 Object param = vertArgsToSqlCommandParam(args);
31 result = sqlSession.Name(), param);
32 }
33break;
34case FLUSH:
35 result = sqlSession.flushStatements();
36break;
37default:
38throw new BindingException("Unknown execution method for: " + Name());
39 }
40if (result == null && ReturnType().isPrimitive() && !urnsVoid()) {
41throw new BindingException("Mapper method '" + Name()
42 + " attempted to return null from a method with a primitive return type (" + ReturnType() + ").");
43 }
44return result;
45 }
46
47private Object rowCountResult(int rowCount) {
48final Object result;
49if (urnsVoid()) {
50 result = null;
51 } else if (Integer.class.ReturnType()) || Integer.TYPE.ReturnType())) {
52 result = rowCount;
53 } else if (Long.class.ReturnType()) || Long.TYPE.ReturnType())) {
54result = (long)rowCount;
55 } else if (Boolean.class.ReturnType()) || Boolean.TYPE.ReturnType())) {
56 result = rowCount > 0;
57 } else {
58throw new BindingException("Mapper method '" + Name() + "' has an unsupported return type: " + ReturnType());
59 }
60return result;
61 }
s e le ct语句的返回值类型
对于select语句,必须在Mapper映射⽂件中显⽰声明返回值类型,否则会抛出异常,指出“A query was run and no Result Maps were found for the Mapped Statement”。
返回Integer或Long类型
与修改语句不同,select语句必须指定返回值类型,且mapper映射⽂件中的返回值类型需要与mapper
接⼝中声明的返回值类型⼀致,都是int或long;
mapper接⼝中的返回值类型可以是Integer、Long,也可以是int、long
不能返回Boolean类型
select语句不能返回Boolean类型
返回⾃定义类型的Bean
select语句返回的column值与Mapper⽅法返回值的属性的映射有两种⽅式(具体设置见下⽂):
通过名称实现⾃动映射
通过resultMap标签指定映射⽅式
返回List、Set、Array类型
直接指定select⽅法的返回值为List<T>、Set<T>、即可,注意此时mapper映射⽂件中select标签的 resultType类型⼀定要是⾃定义的Bean类型,⽽不是集合类型,可以理解为resultType指定的类型对应的是数据库中的⼀⾏数据
返回Map类型
返回Map类型有两种含义:
resultType的类型为map,mapper接⼝的返回值也为Map,此时返回结果将Bean的属性作为key,值作为Value返回
resultType的类型为⾮map类型(⾃定义类型、数值类型、String等),mapper接⼝的返回值为Map,且指定了mapKey,此时的返回结果以指定的mapKey作为Key,以resultType类型对象作为value
通过column别名实现⾃定义类型的⾃动映射
只要保证数据库查询返回的column名称和Bean的属性名⼀致,Mybatis便能够实现⾃动映射。如:
<select id="selectActorById" resultType="canger.study.chapter04.bean.Actor">
select actor_id as id, first_name as firstName ,last_name as lastName
from actor
where actor_id=#{id}
</select>
public class Actor {
Long id;
String firstName;
String lastName;
}
需要特别说明的有3个地⽅:
1. 返回值Bean⽆需为属性设置getter/setter⽅法,Mybatis依然能够为其赋值;
2. 如果column名称和Bean的属性名只有部分相同,那么只有名称相同的属性会被赋值,Bean依然会被创建;
3. 如果column名称与所有Bean的属性名都不相同,则select语句会返回null值,即使数据库中存在符合查询条件的记录;
设置mapUnderscoreToCamelCase属性实现⾃动映射
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
如果数据库采⽤了严格的under score命名规则,则通过设置mapUnderscoreToCamelCase属性并可实现column到实体类property的⾃动映射;
实际项⽬中,可将命名不规范的column通过resultMap进⾏显⽰声明,符合命名规范的进⾏⾃动映射
通过resultMap标签指定⾃定义类型的映射⽅式
需要在mapper映射⽂件中定义 resultMap标签
<resultMap id="actorResultMap" type="canger.study.chapter04.bean.Actor">
<id column="id" property="id" jdbcType="BIGINT" javaType="long" typeHandler="org.pe.LongTypeHandler"/>
<result column="firstName" property="firstName" jdbcType="VARCHAR" javaType="string"
typeHandler="org.pe.StringTypeHandler"/>
<result column="lastName" property="lastName" jdbcType="VARCHAR" javaType="string"
typeHandler="org.pe.StringTypeHandler"/>
</resultMap>
<select id="selectActorById" resultMap="actorResultMap">
select actor_id as id, first_name as firstName ,last_name as lastName
from actor
where actor_id=#{id}
</select>
需要注意的⼏点
id或result标签中的column属性⼀定要使⽤SQL select 语句中最终返回到数据库客户端的列名,如对于select actor_id as id,在resultMap中需要使⽤ id⽽不是 actor_id;
⽆需将查询返回的所有column都进⾏显⽰声明,没有在resultMap中声明映射关系的column将进⾏⾃动映射
typeHandler属性:如果使⽤MyBatis提供的typeHandler,则⼀定要是⽤全类名,MyBatis默认没有为typeHandler其注册别名;
jdbcType 、 javaType和typeHandler的对照关系,以及jdbcType和数据库类型的对照关系参见
MyBatis注册的默认TypeHandler参见类 org.pe.TypeHandlerRegistry,具体如下
public TypeHandlerRegistry() {
register(Boolean.class, new BooleanTypeHandler());
register(boolean.class, new BooleanTypeHandler());
register(JdbcType.BOOLEAN, new BooleanTypeHandler());
register(JdbcType.BIT, new BooleanTypeHandler());
register(Byte.class, new ByteTypeHandler());
register(byte.class, new ByteTypeHandler());
register(JdbcType.TINYINT, new ByteTypeHandler());
register(Short.class, new ShortTypeHandler());
register(short.class, new ShortTypeHandler());
register(JdbcType.SMALLINT, new ShortTypeHandler());
register(Integer.class, new IntegerTypeHandler());
register(int.class, new IntegerTypeHandler());
register(JdbcType.INTEGER, new IntegerTypeHandler());
register(Long.class, new LongTypeHandler());
register(long.class, new LongTypeHandler());
register(Float.class, new FloatTypeHandler());
register(float.class, new FloatTypeHandler());
register(JdbcType.FLOAT, new FloatTypeHandler());
register(Double.class, new DoubleTypeHandler());
register(double.class, new DoubleTypeHandler());
register(JdbcType.DOUBLE, new DoubleTypeHandler());
register(Reader.class, new ClobReaderTypeHandler());
register(String.class, new StringTypeHandler());
register(String.class, JdbcType.CHAR, new StringTypeHandler());
register(String.class, JdbcType.CLOB, new ClobTypeHandler());
register(String.class, JdbcType.VARCHAR, new StringTypeHandler());
register(String.class, JdbcType.LONGVARCHAR, new ClobTypeHandler());
register(String.class, JdbcType.NVARCHAR, new NStringTypeHandler());
register(String.class, JdbcType.NCHAR, new NStringTypeHandler());
register(String.class, JdbcType.NCLOB, new NClobTypeHandler());
register(JdbcType.CHAR, new StringTypeHandler());
register(JdbcType.VARCHAR, new StringTypeHandler());
register(JdbcType.CLOB, new ClobTypeHandler());
register(JdbcType.LONGVARCHAR, new ClobTypeHandler());
register(JdbcType.NVARCHAR, new NStringTypeHandler());
register(JdbcType.NCHAR, new NStringTypeHandler());
register(JdbcType.NCLOB, new NClobTypeHandler());
register(Object.class, JdbcType.ARRAY, new ArrayTypeHandler());
register(JdbcType.ARRAY, new ArrayTypeHandler());
register(BigInteger.class, new BigIntegerTypeHandler());
register(JdbcType.BIGINT, new LongTypeHandler());
register(BigDecimal.class, new BigDecimalTypeHandler());
register(JdbcType.REAL, new BigDecimalTypeHandler());
register(JdbcType.DECIMAL, new BigDecimalTypeHandler());
register(JdbcType.NUMERIC, new BigDecimalTypeHandler());
register(InputStream.class, new BlobInputStreamTypeHandler());
register(Byte[].class, new ByteObjectArrayTypeHandler());
register(Byte[].class, JdbcType.BLOB, new BlobByteObjectArrayTypeHandler());
register(Byte[].class, JdbcType.LONGVARBINARY, new BlobByteObjectArrayTypeHandler()); register(byte[].class, new ByteArrayTypeHandler());
register(byte[].class, JdbcType.BLOB, new BlobTypeHandler());
register(byte[].class, JdbcType.LONGVARBINARY, new BlobTypeHandler());
register(JdbcType.LONGVARBINARY, new BlobTypeHandler());
register(JdbcType.BLOB, new BlobTypeHandler());
register(Object.class, UNKNOWN_TYPE_HANDLER);
register(Object.class, JdbcType.OTHER, UNKNOWN_TYPE_HANDLER);
register(JdbcType.OTHER, UNKNOWN_TYPE_HANDLER);
register(Date.class, new DateTypeHandler());
register(Date.class, JdbcType.DATE, new DateOnlyTypeHandler());
register(Date.class, JdbcType.TIME, new TimeOnlyTypeHandler());
register(JdbcType.TIMESTAMP, new DateTypeHandler());
bigdecimal转换为integerregister(JdbcType.DATE, new DateOnlyTypeHandler());
register(JdbcType.TIME, new TimeOnlyTypeHandler());
register(java.sql.Date.class, new SqlDateTypeHandler());
register(java.sql.Time.class, new SqlTimeTypeHandler());
register(java.sql.Timestamp.class, new SqlTimestampTypeHandler());
// mybatis-typehandlers-jsr310
if (Jdk.dateAndTimeApiExists) {
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论