在基於注解的示例中,可以簡化編寫XML的過程,全部采用注解方式進行編寫,並在注解上寫SQL語句,語句和XML的語句保持一致,並且可以省略掉XML文件不用引入的好處。但還有一點,基於注解的方式還沒有百分百覆蓋所有XML標簽,所有還是有一點缺陷。
在org.apache.ibatis.annotations包下包含了所有注解。
下面引用官方文檔的說明http://www.mybatis.org/mybatis-3/zh/java-api.html:
映射器注解:
因為最初設計時,MyBatis是一個XML驅動的框架。配置信息是基於XML的,而且映射語句也是定義在XML中的。而到了MyBatis3,有新的可用的選擇了。MyBatis3構建在基於全面而且強大的Java配置API之上。這個配置API是基於XML的MyBatis配置的基礎,也是新的基於注解配置的基礎。注解提供了一種簡單的方式來實現簡單映射語句,而不會引入大量的開銷。
注意:不幸的是,Java注解限制了它們的表現和靈活。盡管很多時間都花在調查,設計和實驗上,最強大的MyBatis映射不能用注解來構建,那並不可笑。C#屬性(做示例)就沒有這些限制,因此MyBatis.NET將會比XML有更豐富的選擇。也就是說,基於Java注解的配置離不開它的特性。
注解有下面這些:
| 注解 | 目標 | 相對應的XML | 描述 |
|---|---|---|---|
| @CacheNamespace |
類 |
<cache> |
為給定的命名空間(比如類)配置緩存。屬性:implemetation,eviction,flushInterval,size,readWrite,blocking和properties。 |
| @Property |
N/A |
<property> |
指定屬性值或占位符(可以由mybatis-config.xml中定義的配置屬性替換)。屬性:name,value。(在MyBatis3.4.2+上可用) |
| @CacheNamespaceRef |
類 |
<cacheRef> |
參照另外一個命名空間的緩存來使用。屬性:value,name。如果使用此注釋,則應指定value或name屬性。value屬性指定指定命名空間的java類型(命名空間名稱成為指定的java類型的FQCN),對於name屬性(此屬性自3.4.2起可用)指定命名空間的名稱。 |
| @ConstructorArgs |
方法 |
<constructor> |
收集一組結果傳遞給一個劫奪對象的構造方法。屬性:value,是形式參數的數組。 |
| @Arg |
N/A |
|
單獨的構造方法參數,是ConstructorArgs集合的一部分。屬性:id,column,javaType,typeHandler。id屬性是布爾值,來標識用於比較的屬性,和<idArg>XML元素相似。 |
| @TypeDiscriminator |
方法 |
<discriminator> |
一組實例值被用來決定結果映射的表現。屬性:column,javaType,jdbcType,typeHandler,cases。cases屬性就是實例的數組。 |
| @Case |
N/A |
<case> |
單獨實例的值和它對應的映射。屬性:value,type,results。Results屬性是結果數組,因此這個注解和實際的ResultMap很相似,由下面的Results注解指定。 |
| @Results |
方法 |
<resultMap> |
結果映射的列表,包含了一個特別結果列如何被映射到屬性或字段的詳情。屬性:value,id。value屬性是Result注解的數組。這個id的屬性是結果映射的名稱。 |
| @Result |
N/A |
|
在列和屬性或字段之間的單獨結果映射。屬性:id,column,property,javaType,jdbcType,typeHandler,one,many。id屬性是一個布爾值,表示了應該被用於比較(和在XML映射中的<id>相似)的屬性。one屬性是單獨的聯系,和<association>相似,而many屬性是對集合而言的,和<collection>相似。它們這樣命名是為了避免名稱沖突。 |
| @One |
N/A |
<association> |
復雜類型的單獨屬性值映射。屬性:select,已映射語句(也就是映射器方法)的完全限定名,它可以加載合適類型的實例。注意:聯合映射在注解API中是不支持的。這是因為Java注解的限制,不允許循環引用。fetchType會覆蓋全局的配置參數lazyLoadingEnabled。 |
| @Many |
N/A |
<collection> |
映射到復雜類型的集合屬性。屬性:select,已映射語句(也就是映射器方法)的全限定名,它可以加載合適類型的實例的集合,fetchType會覆蓋全局的配置參數lazyLoadingEnabled。注意聯合映射在注解API中是不支持的。這是因為Java注解的限制,不允許循環引用 |
| @MapKey |
方法 |
復雜類型的集合屬性映射。屬性:select,是映射語句(也就是映射器方法)的完全限定名,它可以加載合適類型的一組實例。注意:聯合映射在Java注解中是不支持的。這是因為Java注解的限制,不允許循環引用。 |
|
| @Options |
方法 |
映射語句的屬性 |
這個注解提供訪問交換和配置選項的寬廣范圍,它們通常在映射語句上作為屬性出現。而不是將每條語句注解變復雜,Options注解提供連貫清晰的方式來訪問它們。屬性:useCache=true,flushCache=FlushCachePolicy.DEFAULT,resultSetType=FORWARD_ONLY,statementType=PREPARED,fetchSize=-1,timeout=-1useGeneratedKeys=false,keyProperty=”id”,keyColumn=””,resultSets=””。理解Java注解是很重要的,因為沒有辦法來指定“null”作為值。因此,一旦你使用了Options注解,語句就受所有默認值的支配。要注意什么樣的默認值來避免不期望的行為。 |
|
方法 |
|
這些注解中的每一個代表了執行的真實SQL。它們每一個都使用字符串數組(或單獨的字符串)。如果傳遞的是字符串數組,它們由每個分隔它們的單獨空間串聯起來。這就當用Java代碼構建SQL時避免了“丟失空間”的問題。然而,如果你喜歡,也歡迎你串聯單獨的字符串。屬性:value,這是字符串數組用來組成單獨的SQL語句。 |
|
方法 |
|
這些可選的SQL注解允許你指定一個類名和一個方法在執行時來返回運行允許創建動態的SQL。基於執行的映射語句,MyBatis會實例化這個類,然后執行由provider指定的方法.該方法可以有選擇地接受參數對象.(InMyBatis3.4orlater,it'sallowmultipleparameters)屬性:type,method。type屬性是類。method屬性是方法名。注意:這節之后是對類的討論,它可以幫助你以干凈,容於閱讀的方式來構建動態SQL。 |
| @Param |
Parameter |
N/A |
如果你的映射器的方法需要多個參數,這個注解可以被應用於映射器的方法參數來給每個參數一個名字。否則,多參數將會以它們的順序位置來被命名(不包括任何RowBounds參數)比如。#{param1},#{param2}等,這是默認的。使用@Param(“person”),參數應該被命名為#{person}。 |
| @SelectKey |
方法 |
<selectKey> |
該注解復制了<selectKey>的功能,用在注解了@Insert,@InsertProvider,@Updateor@UpdateProvider的方法上。在其他方法上將被忽略。如果你指定了一個@SelectKey注解,然后Mybatis將忽略任何生成的key屬性通過設置@Options,或者配置屬性。屬性:statement是要執行的sql語句的字符串數組,keyProperty是需要更新為新值的參數對象屬性,before可以是true或者false分別代表sql語句應該在執行insert之前或者之后,resultType是keyProperty的Java類型,statementType是語句的類型,取Statement,PreparedStatement和CallableStatement對應的STATEMENT,PREPARED或者CALLABLE其中一個,默認是PREPARED。 |
| @ResultMap |
方法 |
N/A |
這個注解給@Select或者@SelectProvider提供在XML映射中的<resultMap>的id。這使得注解的select可以復用那些定義在XML中的ResultMap。如果同一select注解中還存在@Results或者@ConstructorArgs,那么這兩個注解將被此注解覆蓋。 |
| @ResultType |
Method |
N/A |
當使用結果處理器時啟用此注解。這種情況下,返回類型為void,所以Mybatis必須有一種方式決定對象的類型,用於構造每行數據。如果有XML的結果映射,使用@ResultMap注解。如果結果類型在XML的<select>節點中指定了,就不需要其他的注解了。其他情況下則使用此注解。比如,如果@Select注解在一個方法上將使用結果處理器,返回類型必須是void並且這個注解(或者@ResultMap)是必須的。這個注解將被忽略除非返回類型是void。 |
| @Flush |
方法 |
N/A |
如果這個注解使用了,它將調用定義在Mapper接口中的SqlSession#flushStatements方法。(Mybatis3.3或者以上) |
映射申明樣例:
這個例子展示了如何使用@SelectKey注解來在插入前讀取數據庫序列的值:
@Insert("insert into table3 (id, name) values(#{nameId}, #{name})")
@SelectKey(statement="call next value for TestSequence", keyProperty="nameId", before=true, resultType=int.class)
int insertTable3(Name name);
這個例子展示了如何使用@SelectKey注解來在插入后讀取數據庫識別列的值:
@Insert("insert into table2 (name) values(#{name})")
@SelectKey(statement="call identity()", keyProperty="nameId", before=false, resultType=int.class)
int insertTable2(Name name);
這個例子展示了如何使用@Flush注解去調用SqlSession#flushStatements():
@Flush List<BatchResult> flush();
這些例子展示了如何通過指定@Result的id屬性來命名結果集:
@Results(id = "userResult", value = {
@Result(property = "id", column = "uid", id = true),
@Result(property = "firstName", column = "first_name"),
@Result(property = "lastName", column = "last_name")
})
@Select("select * from users where id = #{id}")
User getUserById(Integer id);
@Results(id = "companyResults")
@ConstructorArgs({
@Arg(property = "id", column = "cid", id = true),
@Arg(property = "name", column = "name")
})
@Select("select * from company where id = #{id}")
Company getCompanyById(Integer id);
這個例子展示了單一參數使用@SqlProvider:
@SelectProvider(type = UserSqlBuilder.class, method = "buildGetUsersByName")
List<User> getUsersByName(String name);
class UserSqlBuilder {
public String buildGetUsersByName(final String name) {
return new SQL(){{
SELECT("*");
FROM("users");
if (name != null) {
WHERE("name like #{value} || '%'");
}
ORDER_BY("id");
}}.toString();
}
}
這個列子展示了多參數使用@SqlProvider:
@SelectProvider(type = UserSqlBuilder.class, method = "buildGetUsersByName")
List<User> getUsersByName(
@Param("name") String name, @Param("orderByColumn") String orderByColumn);
class UserSqlBuilder {
// If not use @Param, you should be define same arguments with mapper method
public String buildGetUsersByName(
final String name, final String orderByColumn) {
return new SQL(){{
SELECT("*");
FROM("users");
WHERE("name like #{name} || '%'");
ORDER_BY(orderByColumn);
}}.toString();
}
// If use @Param, you can define only arguments to be used
public String buildGetUsersByName(@Param("orderByColumn") final String orderByColumn) {
return new SQL(){{
SELECT("*");
FROM("users");
WHERE("name like #{name} || '%'");
ORDER_BY(orderByColumn);
}}.toString();
}
}
示例:
0、項目整體目錄結構:
1、創建數據庫、表、模擬數據,腳本如下:
CREATE DATABASE `studenttest` ; USE `studenttest`;
DROP TABLE IF EXISTS `klass`; CREATE TABLE `klass` ( `id` int(10) NOT NULL AUTO_INCREMENT, `name` varchar(50) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=34 DEFAULT CHARSET=utf8; insert into `klass`(`id`,`name`) values (1,'一年一班'); insert into `klass`(`id`,`name`) values (2,'一年二班'); insert into `klass`(`id`,`name`) values (3,'一年三班'); insert into `klass`(`id`,`name`) values (16,'四年五班'); insert into `klass`(`id`,`name`) values (18,'二年一班1'); insert into `klass`(`id`,`name`) values (19,'二年一班2'); insert into `klass`(`id`,`name`) values (20,'二年一班3'); insert into `klass`(`id`,`name`) values (21,'二年一班4'); insert into `klass`(`id`,`name`) values (22,'二年一班5'); insert into `klass`(`id`,`name`) values (23,'二年一班6'); insert into `klass`(`id`,`name`) values (24,'二年一班7'); insert into `klass`(`id`,`name`) values (25,'二年一班8'); insert into `klass`(`id`,`name`) values (26,'二年一班9'); insert into `klass`(`id`,`name`) values (27,'二年一班0'); insert into `klass`(`id`,`name`) values (28,'二年一班1'); insert into `klass`(`id`,`name`) values (29,'二年一班2'); insert into `klass`(`id`,`name`) values (30,'二年一班3'); insert into `klass`(`id`,`name`) values (31,'二年一班4'); insert into `klass`(`id`,`name`) values (32,'二年一班5'); insert into `klass`(`id`,`name`) values (33,'二年一班6'); DROP TABLE IF EXISTS `student`; CREATE TABLE `student` ( `id` int(10) NOT NULL AUTO_INCREMENT, `name` varchar(50) DEFAULT NULL, `k_id` int(10) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8; insert into `student`(`id`,`name`,`k_id`) values (1,'jack',1); insert into `student`(`id`,`name`,`k_id`) values (2,'allen',1); insert into `student`(`id`,`name`,`k_id`) values (3,'marry',2); insert into `student`(`id`,`name`,`k_id`) values (4,'john',2); insert into `student`(`id`,`name`,`k_id`) values (5,'gumble',2); insert into `student`(`id`,`name`,`k_id`) values (6,'forest',2); insert into `student`(`id`,`name`,`k_id`) values (7,'tailer',3); insert into `student`(`id`,`name`,`k_id`) values (8,'smith',3); insert into `student`(`id`,`name`,`k_id`) values (9,'hebe',1); insert into `student`(`id`,`name`,`k_id`) values (10,'julia',3); insert into `student`(`id`,`name`,`k_id`) values (11,'mason',2); insert into `student`(`id`,`name`,`k_id`) values (12,'joe',2); insert into `student`(`id`,`name`,`k_id`) values (14,'angel',2); insert into `student`(`id`,`name`,`k_id`) values (15,'turky',2); insert into `student`(`id`,`name`,`k_id`) values (16,'eve',2);
2、引入POM依賴:
<!-- mysql-connector-java -->
<!-- http://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
<!-- mybatis -->
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.4</version>
</dependency>
3、新建config.properties配置文件,用於在MyBatis引入,使用EL表達式獲取參數(基於properties配置文件進行對XML配置文件中使用EL表達式去獲取變量)
username=root password=root driver=com.mysql.jdbc.Driver url=jdbc\:mysql\://127.0.0.1\:3306/studenttest?useUnicode\=true&characterEncoding\=UTF-8&serverTimezone\=UTC
4、新建mybatis-config.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 引入properties配置文件 -->
<properties resource="config.properties" />
<!-- a full setting configuration -->
<settings>
<setting name="cacheEnabled" value="true" />
<setting name="lazyLoadingEnabled" value="false" />
<setting name="multipleResultSetsEnabled" value="true" />
<setting name="useColumnLabel" value="true" />
<setting name="useGeneratedKeys" value="false" />
<setting name="autoMappingBehavior" value="PARTIAL" />
<setting name="defaultExecutorType" value="SIMPLE" />
<setting name="defaultStatementTimeout" value="25" />
<setting name="safeRowBoundsEnabled" value="false" />
<setting name="mapUnderscoreToCamelCase" value="false" />
<setting name="localCacheScope" value="SESSION" />
<setting name="jdbcTypeForNull" value="OTHER" />
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString" />
</settings>
<!-- 三種種使用別稱的方式 -->
<!-- 1-逐個限定 -->
<!-- <typeAliases>
<typeAlias alias="class" type="com.jsoft.testmybatis.bean.Klass" />
</typeAliases> -->
<!-- 2-限定包, 這樣此包中的bean類 別稱會 默認為類名, 效果和上面一樣 -->
<typeAliases>
<package name="com.jsoft.testmybatis.bean" />
</typeAliases>
<!-- 3-在類中使用 @Alias注解直接命名, 如@Alias("Klass") 效果和上面一樣 -->
<!-- 配置環境 -->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
</dataSource>
</environment>
</environments>
<!-- 配置mapper映射文件, 所有mapper映射文件必須填在此處,如果蠶蛹注解的方式這個可以省略 -->
<mappers>
<mapper resource="com/jsoft/testmybatis/mapper/KlassMapper.xml" />
<mapper resource="com/jsoft/testmybatis/mapper/StudentMapper.xml" />
</mappers>
</configuration>
5、新建表對應的Bean
//Klass.java
package com.jsoft.testmybatis.bean; import java.util.List; import org.apache.ibatis.type.Alias; /*@Alias("Klass")*/ public class Klass { private int id; private String name; private List<Student> students; public Klass() { } public Klass(int id) { this.id = id; } @Override public String toString() { return "Klass [id=" + id + ", name=" + name + "]"; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List<Student> getStudents() { return students; } public void setStudents(List<Student> students) { this.students = students; } }
//Student.java
package com.jsoft.testmybatis.bean; public class Student { private Integer id; private String name; private Klass klass; public Student() { } public Student(int id) { this.id = id; } @Override public String toString() { return "Student [id=" + id + ", name=" + name + ", klass=" + klass + "]"; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Klass getKlass() { return klass; } public void setKlass(Klass klass) { this.klass = klass; } }
7、新建Mapper
//StudentDao.java
package com.jsoft.testmybatis.dao; import java.util.List; import java.util.Map; import org.apache.ibatis.annotations.Delete; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Options; import org.apache.ibatis.annotations.Result; import org.apache.ibatis.annotations.Results; import org.apache.ibatis.annotations.Select; import org.apache.ibatis.annotations.Update; import com.jsoft.testmybatis.bean.Student; public interface StudentDao { // sql語句 改 final String UPDATE = "update student set name = #{name,jdbcType=VARCHAR} where id = #{id,jdbcType=INTEGER}"; // sql語句 根據id查一條 final String RETRIEVEBYPRIMARYKEY = "select s.id as s_id, s.name as s_name, k.id as k_id, k.name as k_name from student as s, klass as k where s.k_id = k.id and s.id = #{id,jdbcType=INTEGER}"; // sql語句 分頁查詢 final String RETRIEVEBYPAGE = "select s.id as s_id, s.name as s_name, k.id as k_id, k.name as k_name from student as s, klass as k where s.k_id = k.id and s.name like concat('%',#{student.name},'%') limit #{start}, #{size}"; // sql語句 使用分頁查詢同樣的條件 查詢總條數 final String RETRIEVECOUNT = "select count(*) from student as s, klass as k where s.k_id = k.id and s.name like concat('%',#{student.name},'%')"; // 增 @Insert("insert into student(name,k_id) values(#{name,jdbcType=VARCHAR},#{klass.id,jdbcType=INTEGER})") @Options(useGeneratedKeys = true, keyProperty = "id") int insert(Student student); // 刪 @Delete("delete from student where id = #{id,jdbcType=INTEGER}") int delete(Integer id); // 改 @Update(UPDATE) int update(Student student); /** * 此處如果不寫result 列名--字段名 對應的話 會自動找名字相同的 此處我寫了連接查詢 只要將查詢 返回的列名和類中的字段對應上就可以了 * * @param id * @return */ // 根據id查一條 @Select(RETRIEVEBYPRIMARYKEY) @Results(value = { @Result(property = "id", column = "s_id"), @Result(property = "name", column = "s_name"), @Result(property = "klass.id", column = "k_id"), @Result(property = "klass.name", column = "k_name") }) Student retrieveByPrimaryKey(Integer id); // 分頁+條件查詢 @Select(RETRIEVEBYPAGE) @Results(value = { @Result(property = "id", column = "s_id"), @Result(property = "name", column = "s_name"), @Result(property = "klass.id", column = "k_id"), @Result(property = "klass.name", column = "k_name") }) List<Student> retrieveByPage(Map<String, Object> map); // 使用分頁查詢同樣的條件 查詢總條數 @Select(RETRIEVECOUNT) int retrieveCount(Map<String, Object> map); }
說明:其實也是接口文件,並且是使用注解方式。
注意:如果采用注解方式的,就不用新建XML文件了,這里為了也是兩種效果,直接采用了兩種方式。
8、新建XML的Mapper
<!--KlassMapper.xml-->
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace="KlassMapper"> <resultMap id="ResultKlass" type="Klass"> <id column="k_id" property="id" jdbcType="INTEGER" /> <result column="k_name" property="name" jdbcType="VARCHAR" /> </resultMap> <resultMap type="Klass" id="ResultKlassStudentCollection" extends="ResultKlass"> <collection property="students" ofType="Student"> <id column="s_id" property="id" jdbcType="INTEGER" /> <result column="s_name" property="name" jdbcType="VARCHAR" /> </collection> </resultMap> <sql id="column_klass"> k.id as k_id, k.name as k_name </sql> <sql id="column_student"> s.id as s_id, s.name as s_name </sql> <!-- insert --> <!-- 使用數據庫設定的自增id useGeneratedKeys="true" keyProperty="id" --> <insert id="insertSelective" useGeneratedKeys="true" keyProperty="id" parameterType="Klass"> <!-- 返回新保存的這條數據的id,在保存后,用保存前對象.getId()得到--> <selectKey resultType="int" keyProperty="id" order="AFTER"> select last_insert_id() </selectKey> insert into klass <trim prefix="(" suffix=")" suffixOverrides=","> <if test="name != null"> name </if> </trim> <trim prefix="values (" suffix=")" suffixOverrides=","> <if test="name != null"> #{name,jdbcType=VARCHAR} </if> </trim> </insert> <!-- delete --> <delete id="deleteByPrimaryKey" parameterType="int"> delete from klass where id = #{id,jdbcType=INTEGER} </delete> <delete id="deleteByBatch" parameterType="java.util.List"> delete from klass where id in <foreach collection="list" item="item" index="index" open="(" separator="," close=")"> #{item} </foreach> </delete> <!-- update --> <update id="updateByPrimaryKey" parameterType="Klass"> update klass <set> <if test="name != null"> name = #{name,jdbcType=VARCHAR}, </if> </set> where id = #{id,jdbcType=INTEGER} </update> <!-- retrieve --> <select id="retrieveByPrimaryKey" resultMap="ResultKlass" parameterType="int"> select <include refid="column_klass" /> from klass as k where k.id = #{id,jdbcType=INTEGER} </select> <select id="retrieveKlassWithStudent" resultMap="ResultKlassStudentCollection" parameterType="int"> select <include refid="column_klass" />, <include refid="column_student" /> from klass as k, student as s where k.id = s.k_id and k.id = #{id,jdbcType=INTEGER} </select> <select id="retrieveByPage" resultMap="ResultKlass" parameterType="map"> select <include refid="column_klass" /> from klass as k <trim prefix="where" prefixOverrides="and|or"> <if test="klass != null"> <if test="class.name != null and class.name != ''"> and name like concat('%',#{class.name},'%') </if> </if> </trim> limit #{start}, #{size} </select> <select id="retrieveCount" resultType="int" parameterType="map"> select count(*) from company_economy_type <trim prefix="where" prefixOverrides="and|or"> <if test="klass != null"> <if test="klass.name != null and klass.name != ''"> and name like concat('%',#{klass.name},'%') </if> </if> </trim> </select> <select id="retrievePages" resultMap="ResultKlass" parameterType="map"> select <include refid="column_klass" /> from klass as k <trim prefix="where" prefixOverrides="and|or"> <if test="klass != null"> <if test="class.name != null and class.name != ''"> and name like concat('%',#{class.name},'%') </if> </if> </trim> </select> </mapper>
<!--StudentMapper.xml-->
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace="StudentMapper"> <resultMap id="ResultStudent" type="Student"> <id column="s_id" property="id" jdbcType="INTEGER" /> <result column="s_name" property="name" jdbcType="VARCHAR" /> <association property="klass" javaType="Klass" resultMap="ResultKlass" /> </resultMap> <resultMap id="ResultKlass" type="Klass"> <id column="k_id" property="id" jdbcType="INTEGER" /> <result column="k_name" property="name" jdbcType="VARCHAR" /> </resultMap> <sql id="Base_Column_List"> s.id as s_id, s.name as s_name, k.id as k_id, k.name as k_name </sql> <!-- insert --> <insert id="insertSelective" useGeneratedKeys="true" keyProperty="id" parameterType="Student"> <selectKey keyProperty="id" order="AFTER" resultType="int"> select last_insert_id() </selectKey> insert into student <trim prefix="(" suffix=")" suffixOverrides=","> <if test="name != null"> name, </if> <if test="klass != null"> <if test="klass.id != null and klass.id > 0"> k_id </if> </if> </trim> <trim prefix="values (" suffix=")" suffixOverrides=","> <if test="name != null"> #{name,jdbcType=VARCHAR}, </if> <if test="klass != null"> <if test="klass.id != null and klass.id > 0"> #{klass.id,jdbcType=INTEGER} </if> </if> </trim> </insert> <!-- delete --> <delete id="deleteByPrimaryKey" parameterType="int"> delete from student where id = #{id,jdbcType=INTEGER} </delete> <!-- update --> <update id="updateByPrimaryKey" parameterType="Student"> update student <set> <if test="name != null"> name = #{name,jdbcType=VARCHAR}, </if> <if test="klass != null"> <if test="klass.id != null and klass.id > 0"> k_id </if> </if> </set> where id = #{id,jdbcType=INTEGER} </update> <!-- retrieve --> <select id="retrieveByPrimaryKey" resultMap="ResultStudent" parameterType="int"> select <include refid="Base_Column_List" /> from student as s, klass as k where s.k_id = k.id and s.id = #{id,jdbcType=INTEGER} </select> <select id="retrieveByPage" resultType="Student" parameterType="map"> select <include refid="Base_Column_List" /> from student as s, klass as k <trim prefix="where" prefixOverrides="and|or"> s.k_id = k.id <if test="student != null"> <if test="student.name != null and student.name != ''"> and s.name like concat('%',#{student.name},'%') </if> </if> </trim> limit #{start}, #{size} </select> <select id="retrieveCount" resultType="int" parameterType="map"> select <include refid="Base_Column_List" /> from student as s, klass as k <trim prefix="where" prefixOverrides="and|or"> s.k_id = k.id <if test="student != null"> <if test="student.name != null and student.name != ''"> and s.name like concat('%',#{student.name},'%') </if> </if> </trim> </select> <select id="retrieveByMultiId" resultMap="ResultStudent" parameterType="map"> select <include refid="Base_Column_List" /> from student as s, klass as k <where> s.k_id = k.id <if test="list != null"> and s.id in <foreach collection="list" index="index" item="item" open="(" separator="," close=")"> #{item} </foreach> </if> </where> </select> <select id="retrieveStudentLike" resultMap="ResultStudent" parameterType="map"> <bind name="name" value="'%'+student.name+'%'"/> select <include refid="Base_Column_List" /> from student as s, klass as k <trim prefix="where" prefixOverrides="and|or"> s.k_id = k.id and s.name like #{name} </trim> </select> </mapper>
9、測試代碼,這里直接采用了JUnit進行測試
/***************************** 以下方法為配置文件方法 ************************************/
// 向 班級表 插入一條數據
public void test1_1() throws IOException {
Klass klass = new Klass();
klass.setName("二年一班");
// 讀取配置文件
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
// 構建SqlSessionFactory 即session工廠, 用來產生session
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
// 從session工廠中獲得session
SqlSession sqlSession = factory.openSession();
int k = sqlSession.insert("KlassMapper.insertSelective", klass);
// 利用 返回數 來控制 進行 提交或者是回滾操作
if (k == 1) {
sqlSession.commit();
} else {
sqlSession.rollback();
}
System.out.println(klass);
// 關閉session
sqlSession.close();
}
// 向 班級表 批量 插入數據
public void test1_2() throws IOException {
List<Klass> list = new ArrayList<Klass>();
for (int i = 0; i < 10; i++) {
Klass klass = new Klass();
klass.setName("二年一班" + i);
list.add(klass);
}
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
SqlSession sqlSession = factory.openSession(ExecutorType.BATCH);
for (Klass k : list) {
int i = sqlSession.insert("KlassMapper.insertSelective", k);
sqlSession.commit();
System.out.println(k);
}
sqlSession.close();
}
// 向 學生表中 插入一條數據 帶班級信息
public void test1_3() throws IOException {
Student stu = new Student();
stu.setName("hebe");
// 設置班級, 注意看StudentMapper映射文件中的寫法,如果數據庫有外鍵關聯的話, 此屬性不能為空!
stu.setKlass(new Klass(1));
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
SqlSession sqlSession = factory.openSession();
int k = sqlSession.insert("StudentMapper.insertSelective", stu);
sqlSession.commit();
System.out.println(stu);
sqlSession.close();
}
// 刪除 班級表 一條數據
public void test2_1() throws IOException {
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
SqlSession sqlSession = factory.openSession();
int i = sqlSession.delete("KlassMapper.deleteByPrimaryKey", 17);
sqlSession.commit();
System.out.println(i);
sqlSession.close();
}
// 批量刪除 班級表 數據
public void test2_2() throws IOException {
List<Integer> list = new ArrayList<Integer>();
list.add(34);
list.add(35);
list.add(36);
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
SqlSession sqlSession = factory.openSession();
int i = sqlSession.delete("KlassMapper.deleteByBatch", list);
sqlSession.commit();
System.out.println(i);
sqlSession.close();
}
// 更新 班級表 一條數據 數據, 批量修改可以參照上面的批量刪除
public void test3_1() throws IOException {
Klass klass = new Klass();
klass.setId(16);
klass.setName("四年五班");
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
SqlSession sqlSession = factory.openSession();
int i = sqlSession.update("KlassMapper.updateByPrimaryKey", klass);
sqlSession.commit();
System.out.println(i);
sqlSession.close();
}
// 查詢 根據id查詢 一個班級
public void test4_1() throws IOException {
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
SqlSession sqlSession = factory.openSession();
Klass klass = sqlSession.selectOne("KlassMapper.retrieveByPrimaryKey", 16);
System.out.println(klass);
sqlSession.close();
}
// 分頁查詢① 使用自定義參數, 控制 起始索引和返回量
public void test4_2() throws IOException {
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
SqlSession sqlSession = factory.openSession();
Map<String, Object> map = new HashMap<String, Object>();
map.put("start", 0);
map.put("size", 999);
List<Klass> list = sqlSession.selectList("KlassMapper.retrieveByPage", map);
System.out.println(list.size());
sqlSession.close();
}
// 分頁查詢② 使用mybatis提供的參數, 控制 起始索引和返回量
public void test4_3() throws IOException {
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
SqlSession sqlSession = factory.openSession();
Map<String, Object> map = new HashMap<String, Object>();
// 起始索引, 返回量
RowBounds row = new RowBounds(0, 20);
List<Klass> list = sqlSession.selectList("KlassMapper.retrievePages", map, row);
System.out.println(list.size());
sqlSession.close();
}
// 級聯查詢 根據學生id查詢 一個帶班級信息的學生對象
public void test4_4() throws IOException {
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
SqlSession sqlSession = factory.openSession();
Student stu = sqlSession.selectOne("StudentMapper.retrieveByPrimaryKey", 1);
System.out.println(stu);
sqlSession.close();
}
// 級聯查詢 根據班級id 查詢 一個帶學生列表的班級對象
public void test4_5() throws IOException {
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
SqlSession sqlSession = factory.openSession();
Klass klass = sqlSession.selectOne("KlassMapper.retrieveKlassWithStudent", 1);
System.out.println(klass.getStudents().size());
for (Student s : klass.getStudents()) {
System.out.println(s);
}
sqlSession.close();
}
// 級聯查詢 根據班級id 查詢 一個帶學生列表的班級對象,使用了foreach標簽, 迭代多個參數
public void test4_6() throws IOException {
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
SqlSession sqlSession = factory.openSession();
Map<String, Object> map = new HashMap<String, Object>();
int[] ids = new int[] { 1, 2 };
map.put("list", ids);
List<Student> stuList = sqlSession.selectList("StudentMapper.retrieveByMultiId", map);
System.out.println(stuList.size());
for (Student s : stuList) {
System.out.println(s);
}
sqlSession.close();
}
// 級聯查詢 根據班級id 查詢 一個帶學生列表的班級對象,使用了bind標簽, 綁定參數
public void test4_7() throws IOException {
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
SqlSession sqlSession = factory.openSession();
Map<String, Object> map = new HashMap<String, Object>();
Student stu = new Student();
stu.setName("m");
map.put("student", stu);
List<Student> stuList = sqlSession.selectList("StudentMapper.retrieveStudentLike", map);
System.out.println(stuList.size());
for (Student s : stuList) {
System.out.println(s);
}
sqlSession.close();
}
/***************************** 以下方法為注解方法 ************************************/
// 插入一條數據
public void testA1_1() throws IOException {
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
// 將接口 StudentMapper 加載到配置中, 如不加載, 則會報 找不到該接口的錯
Configuration config = factory.getConfiguration();
config.addMapper(StudentDao.class);
SqlSession sqlSession = factory.openSession();
StudentDao stuMapper = sqlSession.getMapper(StudentDao.class);
Student stu = new Student();
stu.setName("ella");
stu.setKlass(new Klass(2));
int k = stuMapper.insert(stu);
System.out.println("插入 : " + k + " 條!");
if (k == 1) {
sqlSession.commit();
} else {
sqlSession.rollback();
}
System.out.println(stu);
}
// 刪除一條數據
public void testA2_1() throws IOException {
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
Configuration config = factory.getConfiguration();
config.addMapper(StudentDao.class);
SqlSession sqlSession = factory.openSession();
StudentDao stuMapper = sqlSession.getMapper(StudentDao.class);
int k = stuMapper.delete(17);
System.out.println("刪除 : " + k + " 條!");
if (k == 1) {
sqlSession.commit();
} else {
sqlSession.rollback();
}
sqlSession.close();
}
// 更新一條數據
public void testA3_1() throws IOException {
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
Configuration config = factory.getConfiguration();
config.addMapper(StudentDao.class);
SqlSession sqlSession = factory.openSession();
StudentDao stuMapper = sqlSession.getMapper(StudentDao.class);
Student student = new Student(16);
student.setName("eve");
int k = stuMapper.update(student);
System.out.println("更新 : " + k + " 條!");
if (k == 1) {
sqlSession.commit();
} else {
sqlSession.rollback();
}
sqlSession.close();
}
// 查 一條數據
public void testA4_1() throws IOException {
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
Configuration config = factory.getConfiguration();
config.addMapper(StudentDao.class);
SqlSession sqlSession = factory.openSession();
StudentDao stuMapper = sqlSession.getMapper(StudentDao.class);
Student stu = stuMapper.retrieveByPrimaryKey(2);
System.out.println(stu);
sqlSession.close();
}
// 查 分頁查詢
public void testA4_2() throws IOException {
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
Configuration config = factory.getConfiguration();
config.addMapper(StudentDao.class);
SqlSession sqlSession = factory.openSession();
StudentDao stuMapper = sqlSession.getMapper(StudentDao.class);
Student stu = new Student();
stu.setName("m");
Map<String, Object> map = new HashMap<String, Object>();
map.put("student", stu);
// 注意: 起始參數是指索引值, 從0開始, 注意頁數和索引值得轉換
map.put("start", 0);
// 返回量
map.put("size", 10);
List<Student> list = stuMapper.retrieveByPage(map);
System.out.println("查詢到 " + list.size() + " 條");
for (Student s : list) {
System.out.println(s);
}
sqlSession.close();
}
// 查 總頁數
public void testA4_3() throws IOException {
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
Configuration config = factory.getConfiguration();
config.addMapper(StudentDao.class);
SqlSession sqlSession = factory.openSession();
StudentDao stuMapper = sqlSession.getMapper(StudentDao.class);
Student stu = new Student();
stu.setName("m");
Map<String, Object> map = new HashMap<String, Object>();
map.put("student", stu);
int page = stuMapper.retrieveCount(map);
System.out.println("共查到 " + page + " 條數據");
sqlSession.close();
}
測試工程:https://github.com/easonjim/5_java_example/tree/master/mybatis/test14
參考:
http://computerdragon.blog.51cto.com/6235984/1399742
原文出處:
[1] Jim, MyBatis3-基於注解的示例, https://www.cnblogs.com/EasonJim/p/7070820.html


