• content
    {:toc}

Mybatis基础。

Mybatis

XML

properties

1
2
3
4
5
6
7
8
9
10
11
<properties resource="org/mybatis/example/config.properties">
<property name="username" value="dev_user"/>
<property name="password" value="F2Fa3!33TYyg"/>
</properties>

<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>

通过resource属性,可以读取properties文件里的配置

Mapper XML 文件

select

1
2
3
4
5
6
7
8
9
10
11
<select
id="selectPerson"
parameterType="int"
resultType="hashmap"
resultMap="personResultMap"
flushCache="false"
useCache="true"
timeout="10000"
fetchSize="256"
statementType="PREPARED"
resultSetType="FORWARD_ONLY">

flushCache,清空本地缓存和二级缓存。default false。

useCache,本条语句的结果被二级缓存。

fetchSize,每次批量返回的结果行数

statementType,STATEMENT,PREPARED,CALLABLE使用Statement,PreparedStatement,CallableStatement之一。默认PREPARED.

insert,update和delete

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<insert
id="insertAuthor"
parameterType="domain.blog.Author"
flushCache="true"
statementType="PREPARED"
keyProperty=""
keyColumn=""
useGeneratedKeys=""
timeout="20">

<update
id="updateAuthor"
parameterType="domain.blog.Author"
flushCache="true"
statementType="PREPARED"
timeout="20">

<delete
id="deleteAuthor"
parameterType="domain.blog.Author"
flushCache="true"
statementType="PREPARED"
timeout="20">

flushCache,任何时候只要语句被调用,都会导致本地缓存和二级缓存被清空。default true。

useGeneratedKeys,insert和update,使用JDBC的getGeneratedKeys,取出数据库内部生成的主键。

keyProperty,对insert和update,

selectKey

1
2
3
4
5
<selectKey
keyProperty="id"
resultType="int"
order="BEFORE"
statementType="PREPARED">

keyProperty,目标值

resultType,结果类型,作为主键的类型。

order,BEFORE或AFTER,首先选择主键,然后执行插入语句。先执行插入语句,

Sql

定义可重用的sql代码,可以包含在其他语句中。

类似于<properties>里声明的, 可以在其他地方使用形如${xx}的形式写入。

1
2
3
4
5
6
7
8
9
<sql id="userColumns">
${alias}.id,${alias}.name,${alias}.password
</sql>

<select id="selectUsers" resultType="map">
select
<include refid="userColumns"><property name="alias" value="t1"/></include>
from table1 t1
</select>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<sql id="sometable">
${prefix}Table
</sql>

<sql id="someinclude">
from
<include refid="${include_target}"/>
</sql>

<select id="select" resultType="map">
select
field1, field2, field3
<include refid="someinclude">
<property name="prefix" value="Some"/>
<property name="include_target" value="sometable"/>
</include>
</select>

Parameters

是指#{}。

/Users/liqianlong/peter/springside4-4.2.3.GA/springside4-4.2.3.GA/modules/core/target

springside-core-4.2.3-GA.jar

mvn install:install-file -Dfile=/Users/liqianlong/peter/springside4-4.2.3.GA/springside4-4.2.3.GA/modules/core/target/springside-core-4.2.3-GA.jar -DgroupId=org.springside -DartifactId=springside-core -Dversion=4.2.3-GA -Dpackaging=jar

Result Maps

解决 数据库字段类属性 之间的映射关系。

1
2
3
4
5
6
7
8
9
10
11
<resultMap id="userResultMap" type="User">
<id property="id" column="user_id" />
<result property="username" column="user_name" />
<result property="password" column="hashed_password"/>
</resultMap>

<select id="selectUsers" resultMap="userResultMap">
select user_id,user_name,hashed_password
from table1
where id=#{id}
</select>

更复杂,更强大:

概述:

resultMap:

  • constructor - 构造方法的参数
    • idArg - Id参数;
    • arg - 普通参数
  • id - 一个ID参数。
  • result - 对应一个普通的字段结果
  • association - 复杂的类型关联
    • 嵌入结果映射 - 仅用一次的
  • collection - 集合类型
    • 嵌入结果映射 - 仅用一次的
  • discriminator - 使用结果值来决定使用哪个结果映射
    • case - 基于某些值的结果映射
      • 嵌入结果映射 -

<resultmap>标记的属性:

id,

type,一个类的全限定名称或别名。 指代这个resultmap描述的是哪个类。

autoMapping,默认unset

id & result

id和result 都映射一个单独的列的值到简单数据类型(String,int,double,date等)的单独属性或字段。

id和result,唯一区别是,id表示的是主键。可能用于比较对象实例时用到的标识属性。

属性:

property : 类中的属性名

column : 数据库表中的字段名

javaType :

jdbcType :

typeHandler :

constructor

resultMap目的是返回一个类的实例, 可以通过constructor来应用对应的构造方法,用于创建这个要返回的实例。

1
2
3
4
5
6
7
8
9
10
11
<constructor>
<idArg column="id" javaType="int"/>
<arg column="username" javaType="String"/>
</constructor>

public class User {

public User(int id,String username){

}
}

association

映射的不是一个简单数据类型, 而是一个类。 需要使用association元素标记,表示关联的意思。

property: 对应java类中的属性名称

column: 对应数据库表的id字段的名称

javaType: 对应java类中属性的类型。

有两种可能 :

  1. 嵌套关联查询 :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<resultMap id="blogResult" type="Blog">
<association property="author" javaType="Author" column="authod_id" select="selectAuthorById" />
</resultMap>

<select id="selectAuthorById" parameterType="int" resultType="Author">
select *
from p_author
where id=#{id}
</select>

<select id="selectBlogById" parameterType="int" resultMap="blogResult">
select *
from p_blog
where id=#{id}
</select>

上述形式, 通过blog的id查询blog记录,blog属于一个作者,通过关联查询,有再次执行sql语句查询author的记录。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<resultMap id="authorResult" type="Author">
<id property="id" column="author_id"/>
<result property="name" column="author_name"/>
<result property="email" column="author_email"/>
</resultMap>

<resultMap id="blogResult" type="Blog">
<id property="id" column="blog_id"/>
<result property="title" column="blog_title"/>
<association property="author" javaType="Author" column="blog_author_id" resultMap="authorResult"/>
</resultMap>


<select id="selectBlogById" parameterType="int" resultMap="blogResult">
select
a.blog_id as blog_id,
a.blog_title as blog_title,
a.blog_author_id as blog_author_id,
b.author_id as author_id,
b.author_name as author_name,
b.author_email as author_email
from Blog a left outer join Author b on a.blog_author_id=b.id
where a.id=#{id}
</select>

通过关联查询,一次性查出所有结果,然后通过<association>的 resultMap属性,指定关联的类,进行映射。

且:

1
2
3
4
5
6
7
8
9
<resultMap id="blogResult" type="Blog">
<id property="id" column="blog_id"/>
<result property="title" column="blog_title"/>
<association property="author" javaType="Author">
<id property="id" column="blog_author_id" />
<result property="name" column="author_name" />
<result property="email" column="author_email" />
</association>
</resultMap>

单独将authorResult拿出来,可以重用,

不重用的可以通过以上方式进行简写。

且:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<select id="selectBlog" resultMap="blogResult">
select
B.id as blog_id,
B.title as blog_title,
A.id as author_id,
A.username as author_username,
A.password as author_password,
A.email as author_email,
A.bio as author_bio,
CA.id as co_author_id,
CA.username as co_author_username,
CA.password as co_author_password,
CA.email as co_author_email,
CA.bio as co_author_bio
from Blog B
left outer join Author A on B.author_id = A.id
left outer join Author CA on B.co_author_id = CA.id
where B.id = #{id}
</select>

<resultMap id="authorResult" type="Author">
<id property="id" column="author_id"/>
<result property="username" column="author_username"/>
<result property="password" column="author_password"/>
<result property="email" column="author_email"/>
<result property="bio" column="author_bio"/>
</resultMap>


<resultMap id="blogResult" type="Blog">
<id property="id" column="blog_id" />
<result property="title" column="blog_title"/>
<association property="author"
resultMap="authorResult" />
<association property="coAuthor"
resultMap="authorResult"
columnPrefix="co_" />
</resultMap>

collection

即,映射的java属性是一个集合类型的。

嵌套查询

1
2
3
4
5
6
7
8
9
10
11
<resultMap id="blogResult" type="Blog">
<collection property="posts" javaType="ArrayList" column="id" ofType="Post" select="selectPostByBlog"/>
</resultMap>

<select id="selectBlogById" resultMap="blogResult">
select * from blog where id=#{id}
</select>

<select id="selectPostByBlog" resultType="Blog">
select * from blog where blog_id=#{id}
</select>

首先执行通过id查询blog,然后通过查询的blog 的结果中的post 的id,去查询post表的记录。 嵌套查询。

嵌套结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<select id="selectBlog" resultMap="blogResult">
select
B.id as blog_id,
B.title as blog_title,
B.author_id as blog_author_id,
P.id as post_id,
P.subject as post_subject,
P.body as post_body,
from Blog B
left outer join Post P on B.id = P.blog_id
where B.id = #{id}
</select>

<resultMap id="blogResult" type="Blog">
<id property="id" column="blog_id"/>
<collection property="posts" ofType="Post" resultMap="blogPostResult" columnPrefix="post_"/>
</resultMap>

<resultMap id="blogPostResult" type="Post">
<id property="id" column="id"/>
<result property="subject" column="subject"/>
<result property="body" column="body"/>
</resultMap>
1
2
3
4
5
6
7
8
9
10

<resultMap id="blogResult" type="Blog">
<id property="id" column="blog_id" />
<result property="title" column="blog_title"/>
<collection property="posts" ofType="Post">
<id property="id" column="post_id"/>
<result property="subject" column="post_subject"/>
<result property="body" column="post_body"/>
</collection>
</resultMap>

一次性查询完,然后对结果进行嵌套映射。

discriminator

鉴别器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<discriminator javaType="int" column="draft">
<case value="1" resultType="DraftPost"/>
</discriminator>

<resultMap id="vehicleResult" type="Vehicle">
<id property="id" column="id" />
<result property="vin" column="vin"/>
<result property="year" column="year"/>
<result property="make" column="make"/>
<result property="model" column="model"/>
<result property="color" column="color"/>
<discriminator javaType="int" column="vehicle_type">
<case value="1" resultMap="carResult"/>
<case value="2" resultMap="truckResult"/>
<case value="3" resultMap="vanResult"/>
<case value="4" resultMap="suvResult"/>
</discriminator>
</resultMap>

<resultMap id="carResult" type="Car">
<result property="doorCount" column="door_count" />
</resultMap>

<resultMap id="carResult" type="Car" extends="vehicleResult">
<result property="doorCount" column="door_count" />
</resultMap>

<resultMap id="vehicleResult" type="Vehicle">
<id property="id" column="id" />
<result property="vin" column="vin"/>
<result property="year" column="year"/>
<result property="make" column="make"/>
<result property="model" column="model"/>
<result property="color" column="color"/>
<discriminator javaType="int" column="vehicle_type">
<case value="1" resultType="carResult">
<result property="doorCount" column="door_count" />
</case>
<case value="2" resultType="truckResult">
<result property="boxSize" column="box_size" />
<result property="extendedCab" column="extended_cab" />
</case>
<case value="3" resultType="vanResult">
<result property="powerSlidingDoor" column="power_sliding_door" />
</case>
<case value="4" resultType="suvResult">
<result property="allWheelDrive" column="all_wheel_drive" />
</case>
</discriminator>
</resultMap>

自动映射

1
2
3
4
5
6
7
8
9
10
11
12
<select id="selectUsers" resultMap="userResultMap">
select
user_id as "id",
user_name as "userName",
hashed_password
from some_table
where id = #{id}
</select>

<resultMap id="userResultMap" type="User">
<result property="password" column="hashed_password"/>
</resultMap>

结合使用,如上, id和username将自动映射到User类的对应字段上,根据配置,hashed_password将映射到password属性。