sql映射文件

<?xmlversion="1.0"encoding="UTF-8"?>

<!DOCTYPEmapperPUBLIC"-//mybatis.org//DTDMapper3.0//EN"

"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mappernamespace="dao.AccountDao">

</mapper>

包括子元素:

cache-配置给定命名空间的缓存。

cache-ref–从其他命名空间引用缓存配置。

resultMap–最复杂,也是最有力量的元素,用来描述如何从数据库结果集中来加载你的对象。

parameterMap–已经被废弃了!老式风格的参数映射。内联参数是首选,这个元素可能在将来被移除。这里不会记录。

sql–可以重用的SQL块,也可以被其他语句引用。

insert–映射插入语句

update–映射更新语句

delete–映射删除语句

select–映射查询语句

select

<selectid=”selectPerson”parameterType=”int”resultType=”hashmap”>

SELECT*FROMPERSONWHEREID=#{id}

</select>

这个语句被定义为selectPerson,使用一个int(或Integer)类型的参数,并返回一个HashMap类型的对象,其中的键是列名,值是列对应的值

#{id}

这就告诉MyBatis使用JDBC创建一个参数,这样的一个参数在SQL中会由一个“?”来标识,并被传递到一个新的预处理语句中,就像这样:

//SimilarJDBCcode,NOTMyBatis…

StringselectPerson=“SELECT*FROMPERSONWHEREID=?”;

PreparedStatementps=conn.prepareStatement(selectPerson);

ps.setInt(1,id);

select有很多参数

id

在命名空间中唯一的标识符,可以被用来引用这条语句。

parameterType

将会传入这条语句的参数类的完全限定名或别名。

parameterMap

这是引用外部parameterMap的已经被废弃的方法。使用内联参数映射和parameterType属性。

resultType

从这条语句中返回的期望类型的类的完全限定名或别名。注意集合情形,那应该是集合可以包含的类型,而不能是集合本身。使用resultType或resultMap,但不能同时使用。

resultMap

命名引用外部的resultMap。返回map是MyBatis最具力量的特性,对其有一个很好的理解的话,许多复杂映射的情形就能被解决了。使用resultMap或resultType,但不能同时使用。

flushCache

将其设置为true,不论语句什么时候被带哦用,都会导致缓存被清空。默认值:false。

useCache

将其设置为true,将会导致本条语句的结果被缓存。默认值:true。

timeout

这个设置驱动程序等待数据库返回请求结果,并抛出异常时间的最大等待值。默认不设置(驱动自行处理)。

fetchSize

这是暗示驱动程序每次批量返回的结果行数。默认不设置(驱动自行处理)。

statementType

STATEMENT,PREPARED或CALLABLE的一种。这会让MyBatis使用选择使用Statement,PreparedStatement或CallableStatement。默认值:PREPARED。

resultSetType

FORWARD_ONLY|SCROLL_SENSITIVE|SCROLL_INSENSITIVE中的一种。默认是不设置(驱动自行处理)。

insert,update,delete

属性

id

在命名空间中唯一的标识符,可以被用来引用这条语句。

parameterType

将会传入这条语句的参数类的完全限定名或别名。

parameterMap

这是引用外部parameterMap的已经被废弃的方法。使用内联参数映射和parameterType属性。

flushCache

将其设置为true,不论语句什么时候被带哦用,都会导致缓存被清空。默认值:false。

timeout

这个设置驱动程序等待数据库返回请求结果,并抛出异常时间的最大等待值。默认不设置(驱动自行处理)。

statementType

STATEMENT,PREPARED或CALLABLE的一种。这会让MyBatis使用选择使用Statement,PreparedStatement或CallableStatement。默认值:PREPARED。

useGeneratedKeys

(仅对insert有用)这会告诉MyBatis使用JDBC的getGeneratedKeys方法来取出由数据(比如:像MySQL和SQLServer这样的数据库管理系统的自动递增字段)内部生成的主键。默认值:false。

keyProperty

(仅对insert有用)标记一个属性,MyBatis会通过getGeneratedKeys或者通过insert语句的selectKey子元素设置它的值。默认:不设置。

例子:

<insertid="insertAuthor"parameterType="domain.blog.Author">

insertintoAuthor(id,username,password,email,bio)

values(#{id},#{username},#{password},#{email},#{bio})

</insert>

<updateid="updateAuthor"parameterType="domain.blog.Author">

updateAuthorset

username=#{username},

password=#{password},

email=#{email},

bio=#{bio}

whereid=#{id}

</update>

<deleteid="deleteAuthor”parameterType="int">

deletefromAuthorwhereid=#{id}

</delete>

如果你的数据库支持自动生成主键的字段(比如MySQL和SQLServer),那么你可以设置useGeneratedKeys=”true”,而且设置keyProperty到你已经做好的目标属性上。例如,如果上面的Author表已经对id使用了自动生成的列类型,那么语句可以修改为:

<insertid="insertAuthor"parameterType="domain.blog.Author"

useGeneratedKeys=”true”keyProperty=”id”>

insertintoAuthor(username,password,email,bio)

values(#{username},#{password},#{email},#{bio})

</insert>

MyBatis有另外一种方法来处理数据库不支持自动生成类型,或者可能JDBC驱动不支持自动生成主键时的主键生成问题。

这里有一个简单(甚至很傻)的示例,它可以生成一个随机ID(可能你不会这么做,但是这展示了MyBatis处理问题的灵活性,因为它并不真的关心ID的生成):

<insertid="insertAuthor"parameterType="domain.blog.Author">

<selectKeykeyProperty="id"resultType="int"order="BEFORE">

selectCAST(RANDOM()*1000000asINTEGER)afromSYSIBM.SYSDUMMY1

</selectKey>

insertintoAuthor

(id,username,password,email,bio,favourite_section)

values

(#{id},#{username},#{password},#{email},#{bio},

#{favouriteSection,jdbcType=VARCHAR}

)

</insert>

在上面的示例中,selectKey元素将会首先运行,Author的id会被设置,然后插入语句会被调用。这给你了一个简单的行为在你的数据库中来处理自动生成的主键,而不需要使你的Java代码变得复杂。

selectKey元素描述如下:

keyProperty

selectKey语句结果应该被设置的目标属性。

resultType

结果的类型。MyBatis通常可以算出来,但是写上也没有问题。MyBatis允许任何简单类型用作主键的类型,包括字符串。

order

这可以被设置为BEFORE或AFTER。如果设置为BEFORE,那么它会首先选择主键,设置keyProperty然后执行插入语句。如果设置为AFTER,那么先执行插入语句,然后是selectKey元素-这和如Oracle数据库相似,可以在插入语句中嵌入序列调用。

statementType

和前面的相同,MyBatis支持STATEMENT,PREPARED和CALLABLE语句的映射类型,分别代表PreparedStatement和CallableStatement类型。

sql

这个元素可以被用来定义可重用的SQL代码段,可以包含在其他语句中。比如:

<sqlid=”userColumns”>id,username,password</sql>

这个SQL片段可以被包含在其他语句中,例如:

<selectid=”selectUsers”parameterType=”int”resultType=”hashmap”>

select<includerefid=”userColumns”/>

fromsome_table

whereid=#{id}

</select>

Parameters

简单的参数传递

<selectid=”selectUsers”parameterType=”int”resultType=”User”>

selectid,username,password

fromusers

whereid=#{id}

</select>

然而,如果你传递了一个复杂的对象,那么MyBatis的处理方式就会有一点不同。比如:

<insertid=”insertUser”parameterType=”User”>

insertintousers(id,username,password)

values(#{id},#{username},#{password})

</insert>

如果User类型的参数对象传递到了语句中,它的id、username和password属性将会被查找,然后它们的值就被传递到参数中。

这点对于传递参数到语句中非常好。但是对于参数映射也有一些其他的特性。

首先,像MyBatis的其他功能,参数可以指定一个确定的数据类型。

#{propertyName,javaType=int,jdbcType=NUMERIC}

如果参数对象是一个hashMap,javaType应该被保证使用正确类型处理器。

如果查询某个值为空的列null,JDBCType就需要写了。

如果使用自定义类型处理器,你需要指定一个类型处理器的类名或者缩写别名,如

#{age,javaType=int,jdbcType=NUMERIC,typeHandler=MyTypeHandler}

#{height,javaType=double,jdbcType=NUMERIC,numericScale=2}

最后,mode属性允许你指定IN,OUT或INOUT参数。如果参数为OUT或INOUT,参数对象属性的值将会被改变,否则保持不变。注意!要确保始终只使用JDBC标准的存储过程语法。参考JDBC的CallableStatement文档以获得更详细的信息。

字符串替换

#{}格式的语法会创建参数华。如果不想创建参数化,使用

${columnName}

方式,将直接用参数值替换sql中的该部分内容。

resultMap

首先需要了解resultType的作用。

<selectid=”selectUsers”parameterType=”int”resultType=”hashmap”>

selectid,username,hashedPassword

fromsome_table

whereid=#{id}

</select>

或者使用javabean

packagecom.someapp.model;

publicclassUser{

privateintid;

privateStringusername;

privateStringhashedPassword;

publicintgetId(){

returnid;

}

publicvoidsetId(intid){

this.id=id;

}

publicStringgetUsername(){

returnusername;

}

publicvoidsetUsername(Stringusername){

this.username=username;

}

publicStringgetHashedPassword(){

returnhashedPassword;

}

publicvoidsetHashedPassword(StringhashedPassword){

this.hashedPassword=hashedPassword;

}

}

<selectid=”selectUsers”parameterType=”int”

resultType=”com.someapp.model.User”>

selectid,username,hashedPassword

fromsome_table

whereid=#{id}

</select>

因为数据库字段和属性一一对应,所有会自动匹配。如果添加的类型别名定义。那么可以使用别名来设置。

<!--InConfigXMLfile-->

<typeAliastype=”com.someapp.model.User”alias=”User”/>

<!--InSQLMappingXMLfile-->

<selectid=”selectUsers”parameterType=”int”

resultType=”User”>

selectid,username,hashedPassword

fromsome_table

whereid=#{id}

</select>

如果字段名和数据库列名不是一一对应的,可以使用sql语句的as语法,来定义列别名,让它和字段对应

<selectid=”selectUsers”parameterType=”int”resultType=”User”>

select

user_idasid,

user_nameasuserName,

hashed_passwordashashedPassword

fromsome_table

whereid=#{id}

</select>

而resultMap则可以更好的解决上面的问题

//实体类

packagecom.liyixing.ibatis.model;

importjava.io.Serializable;

publicclassAccountimplementsSerializable{

/**

*

*/

privatestaticfinallongserialVersionUID=1L;

privateintid;

privateStringuserName;

privateintage;

publicAccount(){

super();

}

publicAccount(intid,StringuserName,intage){

super();

this.id=id;

this.userName=userName;

this.age=age;

}

publicintgetId(){

returnid;

}

publicvoidsetId(intid){

this.id=id;

}

publicStringgetUserName(){

returnuserName;

}

publicvoidsetUserName(StringuserName){

this.userName=userName;

}

publicintgetAge(){

returnage;

}

publicvoidsetAge(intage){

this.age=age;

}

}

映射配置

<?xmlversion="1.0"encoding="UTF-8"?>

<!DOCTYPEmapperPUBLIC"-//mybatis.org//DTDMapper3.0//EN"

"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mappernamespace="com.liyixing.ibatis.dao.IAccountDao">

<resultMaptype="com.liyixing.ibatis.model.Account"id="account">

<idproperty="id"column="ID"/>

<resultproperty="userName"column="USER_NAME"/>

<resultproperty="age"column="AGE"/>

</resultMap>

<selectid="getAccount"parameterType="int"resultMap="account">

SELECT

ID,USER_NAME,AGEFROMaccount

WHEREID=#{id}

</select>

<!---->

<!--<selectid="getAccount"parameterType="string"-->

<!--resultType="com.liyixing.ibatis.model.Account">-->

<!--SELECTID,USER_NAME,AGEFROMaccount-->

<!--WHEREUSER_NAME=#{userName}-->

<!--</select>-->

<insertid="addAccount"parameterType="com.liyixing.ibatis.model.Account">

INSERTINTOaccount

(USER_NAME,AGE)

VALUES

(#{userName},#{age})

<selectKeyresultType="int"keyProperty="id">

select

last_insert_id()asIDfromaccountlimit1

</selectKey>

</insert>

</mapper>

以上映射配置中可以看到一个resultMap元素

而select的配置中,不再使用resultType,而是改为resultMap

表结构

CREATETABLE`account`(

`ID`int(11)NOTNULLauto_increment,

`USER_NAME`varchar(50)defaultNULL,

`AGE`int(11)defaultNULL,

PRIMARYKEY(`ID`)

)ENGINE=MyISAMDEFAULTCHARSET=utf8;

这里不再使用resultType,而是使用了resultMap。

resultMap也用来做关联关系等操作。

resultMap元素子元素

constructor–类在实例化时,用来注入结果到构造方法中

idArg–ID参数;标记结果作为ID可以帮助提高整体效能

arg–注入到构造方法的一个普通结果

id–一个ID结果;标记结果作为ID可以帮助提高整体效能

result–注入到字段或JavaBean属性的普通结果

association–一个复杂的类型关联;许多结果将包成这种类型

嵌入结果映射–结果映射自身的关联,或者参考一个

collection–复杂类型的集

嵌入结果映射–结果映射自身的集,或者参考一个

discriminator–使用结果值来决定使用哪个结果映射

case–基于某些值的结果映射

嵌入结果映射–这种情形结果也映射它本身,因此可以包含很多相同的元素,或者它可以参照一个外部的结果映射。

id,result

这些是结果映射最基本内容。id和result都映射一个单独列的值到简单数据类型(字符串,整型,双精度浮点数,日期等)的单独属性或字段。

这两者之间的唯一不同是id表示的结果将是当比较对象实例时用到的标识属性。这帮助来改进整体表现,特别是缓存和关联关系映射。

他们的属性:

property

映射到列结果的字段或属性。如果匹配的是存在的,和给定名称相同的JavaBeans的属性,那么就会使用。否则MyBatis将会寻找给定名称的字段。这两种情形你可以使用通常点式的复杂属性导航。比如,你可以这样映射一些东西:“username”,或者映射到一些复杂的东西:“address.street.number”。

column

从数据库中得到的列名,或者是列名的重命名标签。这也是通常和会传递给resultSet.getString(columnName)方法参数中相同的字符串。

javaType

一个Java类的完全限定名,或一个类型别名(参加上面内建类型别名的列表)。如果你映射到一个JavaBean,MyBatis通常可以断定类型。然而,如果你映射到的是HashMap,那么你应该明确地指定javaType来保证所需的行为。

jdbcType

在这个表格之后的所支持的JDBC类型列表中的类型。JDBC类型是仅仅需要对插入,更新和删除操作可能为空的列进行处理。这是JDBC的需要,而不是MyBatis的。如果你直接使用JDBC编程,你需要指定这个类型-但仅仅对可能为空的值。

typeHandler

我们在前面讨论过默认的类型处理器。使用这个属性,你可以覆盖默认的类型处理器。这个属性值是类的完全限定名或者是一个类型处理器的实现,或者是类型别名。

支持的JDBC类型

BIT

FLOAT

CHAR

TIMESTAMP

OTHER

UNDEFINED

TINYINT

REAL

VARCHAR

BINARY

BLOB

NVARCHAR

SMALLINT

DOUBLE

LONGVARCHAR

VARBINARY

CLOB

NCHAR

INTEGER

NUMERIC

DATE

LONGVARBINARY

BOOLEAN

NCLOB

BIGINT

DECIMAL

TIME

NULL

CURSOR

<resultMaptype="com.liyixing.ibatis.model.Account"id="account">

<idproperty="id"column="ID"/>

<resultproperty="userName"column="USER_NAME"/>

<resultproperty="age"column="AGE"/>

</resultMap>

constructor构造方法

<constructor>

<idArgcolumn="id"javaType="int"/>

<argcolumn=”username”javaType=”String”/>

</constructor>

构造方法注入允许你在初始化时为类设置属性的值,而不用暴露出公有方法。MyBatis也支持私有属性和私有JavaBeans属性来达到这个目的,但是我们可能更青睐构造方法注入。

<resultMaptype="com.liyixing.ibatis.model.Account"id="account">

<constructor>

<idArgcolumn="ID"javaType="_int"/>

<argcolumn="USER_NAME"javaType="string"/>

</constructor>

<idproperty="id"column="ID"/>

<resultproperty="userName"column="USER_NAME"/>

<resultproperty="age"column="AGE"/>

</resultMap>

注意上面的情况,我们不仅仅在构造定义了构造,而且定义了属性id,和username,这个时候ibatis会在构造的时候把id和userName两个参数传递进去,因为后面还定义了id属性值id,和result属性值userName,那么它还会再构造完毕后,再次把id和userName传递进去。

还有一点就是参数定义的顺序要和我们在constructor中定义的顺序一样,因为java反射机制无法获取参数的名字的。

他们的属性:

column

来自数据库的类名,或重命名的列标签。这和通常传递给resultSet.getString(columnName)方法的字符串是相同的。

javaType

一个Java类的完全限定名,或一个类型别名(参加上面内建类型别名的列表)。如果你映射到一个JavaBean,MyBatis通常可以断定类型。然而,如果你映射到的是HashMap,那么你应该明确地指定javaType来保证所需的行为。

jdbcType

在这个表格之前的所支持的JDBC类型列表中的类型。JDBC类型是仅仅需要对插入,更新和删除操作可能为空的列进行处理。这是JDBC的需要,而不是MyBatis的。如果你直接使用JDBC编程,你需要指定这个类型-但仅仅对可能为空的值。

typeHandler

我们在前面讨论过默认的类型处理器。使用这个属性,你可以覆盖默认的类型处理器。这个属性值是类的完全限定名或者是一个类型处理器的实现,或者是类型别名。

association一对一关联。

添加表address

CREATETABLE`address`(

`ID`int(11)NOTNULLauto_increment,

`ADDRESS`varchar(200)defaultNULL,

PRIMARYKEY(`ID`)

)ENGINE=MyISAMDEFAULTCHARSET=utf8;

修改account表结构

CREATETABLE`account`(

`ID`int(11)NOTNULLauto_increment,

`USER_NAME`varchar(50)defaultNULL,

`AGE`int(11)defaultNULL,

`ADDRESS_ID`int(11)NOTNULL,

PRIMARYKEY(`ID`)

)ENGINE=MyISAMDEFAULTCHARSET=utf8;

增加了一个ADDRESS_ID字段

添加类Address

packagecom.liyixing.ibatis.model;

importjava.io.Serializable;

publicclassAddressimplementsSerializable{

/**

*

*/

privatestaticfinallongserialVersionUID=1L;

privateintid;

privateStringaddress;

publicAddress(){

super();

}

publicintgetId(){

returnid;

}

publicvoidsetId(intid){

this.id=id;

}

publicStringgetAddress(){

returnaddress;

}

publicvoidsetAddress(Stringaddress){

this.address=address;

}

}

修改Account实体,添加属性

privateAddressaddress;

Account映射中的resultMap

<resultMaptype="com.liyixing.ibatis.model.Account"id="account">

<constructor>

<idArgcolumn="ACCOUNT_ID"javaType="_int"/>

<argcolumn="ACCOUNT_USER_NAME"javaType="string"/>

</constructor>

<idproperty="id"column="ACCOUNT_ID"/>

<resultproperty="userName"column="ACCOUNT_USER_NAME"/>

<resultproperty="age"column="ACCOUNT_AGE"/>

<associationproperty="address"column="ACCOUNT_ADDRESS_ID"

javaType="com.liyixing.ibatis.model.Address">

<idproperty="id"column="ADDRESS_ID"/>

<resultproperty="address"column="ADDRESS"/>

</association>

</resultMap>

<associationproperty="address"column="ACCOUNT_ADDRESS_ID"

javaType="com.liyixing.ibatis.model.Address">这里的javaType,官方文档说是会自动算出类型,但是我不写javaType发现它获取的Classtype是null。抛出了空指针异常。所以我写上了。安全一些。

column="ACCOUNT_ADDRESS_ID"这个属性主要是应用于嵌套查询方式。

select

<selectid="getAccount"parameterType="int"resultMap="account">

SELECT

a.IDasACCOUNT_ID,

a.USER_NAMEasACCOUNT_USER_NAME,

a.AGEas

ACCOUNT_AGE,

a.ADDRESS_IDasACCOUNT_ADDRESS_ID,

ad.IDas

ADDRESS_ID,

ad.ADDRESSasADDRESS

FROMaccountasa

leftjoinaddressasad

onad.ID

=a.ADDRESS_ID

WHEREa.ID=#{id}

</select>

我们需要告诉batis如何加载关联。有两种方式。

嵌套查询,通过执行另一个sql映射语句来返回。

嵌套结果,使用嵌套结果映射来同时返回本对象和关联的对象。我上面使用的就是这一种。

association属性:

property

映射到列结果的字段或属性。如果匹配的是存在的,和给定名称相同的JavaBeans的属性,那么就会使用。否则MyBatis将会寻找给定名称的字段。这两种情形你可以使用通常点式的复杂属性导航。比如,你可以这样映射一些东西:“username”,或者映射到一些复杂的东西:“address.street.number”。

column

应用于嵌套查询语句方式。来自数据库的类名,或重命名的列标签。这和通常传递给resultSet.getString(columnName)方法的字符串是相同的。

注意:要处理复合主键,你可以指定多个列名通过column=”{prop1=col1,prop2=col2}”这种语法来传递给嵌套查询语句。这会引起prop1和prop2以参数对象形式来设置给目标嵌套查询语句。

javaType

一个Java类的完全限定名,或一个类型别名(参加上面内建类型别名的列表)。如果你映射到一个JavaBean,MyBatis通常可以断定类型。然而,如果你映射到的是HashMap,那么你应该明确地指定javaType来保证所需的行为。

jdbcType

在这个表格之前的所支持的JDBC类型列表中的类型。JDBC类型是仅仅需要对插入,更新和删除操作可能为空的列进行处理。这是JDBC的需要,而不是MyBatis的。如果你直接使用JDBC编程,你需要指定这个类型-但仅仅对可能为空的值。

typeHandler

我们在前面讨论过默认的类型处理器。使用这个属性,你可以覆盖默认的类型处理器。这个属性值是类的完全限定名或者是一个类型处理器的实现,或者是类型别名。

嵌套查询方式:

select属性

<resultMaptype="com.liyixing.ibatis.model.Account"id="account">

<constructor>

<idArgcolumn="ID"javaType="_int"/>

<argcolumn="USER_NAME"javaType="string"/>

</constructor>

<idproperty="id"column="ACCOUNT_ID"/>

<resultproperty="userName"column="USER_NAME"/>

<resultproperty="age"column="AGE"/>

<associationproperty="address"column="ADDRESS_ID"

javaType="com.liyixing.ibatis.model.Address"select="getAddress">

</association>

</resultMap>

这里的关联配置中,使用select属性,值是getAddress,batis会调用这个id=getAddress的select,也就是说会执行两个sql语句。

associationproperty="address"column="ADDRESS_ID"的column属性会作为参数传递给参数语句中id为getAddress的参数语句。

<selectid="getAddress"parameterType="int"

resultType="com.liyixing.ibatis.model.Address">

select*fromaddresswhereid=#{id}

</select>

<selectid="getAccount"parameterType="int"resultMap="account">

SELECTID,

USER_NAME,

AGE,

ADDRESS_ID

FROMaccount

WHEREID=#{id}

</select>

这种方式会造成sql语句执行过多。

如果我们想在address中,对account进行关联。表结构,模型都不变,添加address的映射文件。

<?xmlversion="1.0"encoding="UTF-8"?>

<!DOCTYPEmapperPUBLIC"-//mybatis.org//DTDMapper3.0//EN"

"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mappernamespace="com.liyixing.ibatis.dao.AddressDao">

<resultMaptype="com.liyixing.ibatis.model.Address"id="address">

<idproperty="id"column="ID"/>

<resultproperty="address"column="ADDRESS"/>

<associationproperty="account"column="ID"

javaType="com.liyixing.ibatis.model.Account"select="getAccount">

</association>

</resultMap>

<selectid="getAddress"parameterType="int"resultMap="address">

select*

fromaddresswhereid=#{id}

</select>

<selectid="getAccount"parameterType="int"

resultType="com.liyixing.ibatis.model.Account">

select*fromaccountwhereADDRESS_ID=#{id}

</select>

</mapper>

可以从上面的例子中看出来。<associationproperty="account"column="ID"

javaType="com.liyixing.ibatis.model.Account"select="getAccount">这个元素的column属性会被作为参数传递过去给对应的sql。

collection集合

添加表message,是account用户的发言

CREATETABLE`message`(

`ID`int(11)NOTNULLauto_increment,

`ACCOUNT_ID`int(11)NOTNULL,

`MESSAGE`varchar(255)defaultNULL,

PRIMARYKEY(`ID`)

)ENGINE=MyISAMDEFAULTCHARSET=utf8;

<resultMaptype="com.liyixing.ibatis.model.Account"id="account">

<constructor>

<idArgcolumn="ID"javaType="_int"/>

<argcolumn="USER_NAME"javaType="string"/>

</constructor>

<idproperty="id"column="ACCOUNT_ID"/>

<resultproperty="userName"column="USER_NAME"/>

<resultproperty="age"column="AGE"/>

<associationproperty="address"column="ADDRESS_ID"

javaType="com.liyixing.ibatis.model.Address"select="getAddress">

</association>

<collectionproperty="messages"javaType="ArrayList"

column="ID"ofType="com.liyixing.ibatis.model.Message"

select="selectMyMessages">

<idproperty="id"column="ID"/>

<resultproperty="message"column="MESSAGE"/>

</collection>

</resultMap>

<selectid="selectMyMessages"parameterType="int"

resultType="com.liyixing.ibatis.model.Message">

select*frommessagewhereACCOUNT_ID=#{accountId}

</select>

以上的配置<collectionproperty="messages"javaType="ArrayList"

column="ID"ofType="com.liyixing.ibatis.model.Message"

select="selectMyMessages">中依然可以看到column会被做为参数传递过去。

一个嵌套结果的方式

<resultMaptype="com.liyixing.ibatis.model.Account"id="account">

<constructor>

<idArgcolumn="ACOUNT_ID"javaType="_int"/>

<argcolumn="ACOUNT_USER_NAME"javaType="string"/>

</constructor>

<idproperty="id"column="ACCOUNT_ID"/>

<resultproperty="userName"column="ACOUNT_USER_NAME"/>

<resultproperty="age"column="ACOUNT_AGE"/>

<collectionproperty="messages"javaType="ArrayList"

ofType="com.liyixing.ibatis.model.Message">

<idproperty="id"column="MESSAGE_ID"/>

<resultproperty="message"column="MESSAGE"/>

</collection>

</resultMap>

这里的column可以省略。

ofType属性:

这个属性用来区分JavaBean(或字段)属性类型,是用来指定集合中的包含(泛型)类型的。

discriminator鉴别器

类似于java的switch可以根据结果制定实际的映射器

有一个Message类

packagecom.liyixing.ibatis.model;

importjava.io.Serializable;

publicclassMessageimplementsSerializable{

/**

*

*/

privatestaticfinallongserialVersionUID=1L;

privateintid;

privateAccountaccount;

privateStringmessage;

privateshortmessageType=(short)-1;

publicintgetId(){

returnid;

}

publicvoidsetId(intid){

this.id=id;

}

publicAccountgetAccount(){

returnaccount;

}

publicvoidsetAccount(Accountaccount){

this.account=account;

}

publicStringgetMessage(){

returnmessage;

}

publicvoidsetMessage(Stringmessage){

this.message=message;

}

publicshortgetMessageType(){

returnmessageType;

}

publicvoidsetMessageType(shortmessageType){

this.messageType=messageType;

}

}

这里的messageType=-1,是因为数据库中我的测试数据,是一条message记录的messageType=0,另一条messageType=1;而java的short自动初始化的时候,值也是0.改成-1就能更清楚的看到结果。

message.xml

<?xmlversion="1.0"encoding="UTF-8"?>

<!DOCTYPEmapperPUBLIC"-//mybatis.org//DTDMapper3.0//EN"

"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mappernamespace="com.liyixing.ibatis.dao.IMessageDao">

<resultMaptype="com.liyixing.ibatis.model.Message"id="message">

<idproperty="id"column="ID"/>

<discriminatorjavaType="_int"column="MESSAGE_TYPE">

<casevalue="1"resultMap="messageType"></case>

</discriminator>

</resultMap>

<resultMaptype="com.liyixing.ibatis.model.Message"id="messageType">

<resultproperty="messageType"column="MESSAGE_TYPE"/>

</resultMap>

</mapper>

这里有<discriminatorjavaType="_int"column="MESSAGE_TYPE">

<casevalue="1"resultMap="messageType"></case>

</discriminator>

当值为1才会映射MESSAGE_TYPE

Account.xml

<?xmlversion="1.0"encoding="UTF-8"?>

<!DOCTYPEmapperPUBLIC"-//mybatis.org//DTDMapper3.0//EN"

"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mappernamespace="com.liyixing.ibatis.dao.IAccountDao">

<resultMaptype="com.liyixing.ibatis.model.Account"id="account">

<idproperty="id"column="ID"/>

<resultproperty="userName"column="USER_NAME"/>

<collectionproperty="messages"javaType="ArrayList"

column="ID"ofType="com.liyixing.ibatis.model.Message"select="getMyMessage">

</collection>

</resultMap>

<selectid="getMyMessage"parameterType="_int"

resultMap="message">

SELECTID,

USER_ID,

MESSAGE,

MESSAGE_TYPE

FROMmessage

WHEREUSER_ID=#{id}

</select>

<selectid="getAccount"parameterType="_int"resultMap="account">

SELECT*

FROMaccountWHEREID=#{id}

</select>

</mapper>

这里我同时测试了collection和跨文件访问resultMap,发现跨文件访问resultMap是允许的。

调用getAccount的select,发现当message_type字段值为1,才会调用id=messageType的resultMap

相关推荐