MyBatisMybatis基本用法–中

4.5 bind

  bind 元素可以于 OGNL 表明式中创设一个变量并以那一个绑定到上下文。比如:

<select id="selectBlogsLike" resultType="Blog">
  <bind name="pattern" value="'%' + _parameter.getTitle() + '%'" />
  SELECT * FROM BLOG
  WHERE title LIKE #{pattern}
</select>

第五有的 Java API

5.4 清理 Session 级的缓存

void clearCache()

5.1 语句子执行方(莫引进,推荐使用5.6及5.7

  这一个点子给用来举办定义在 SQL 映射的 XML 文件被之 SELECT,INSERT,UPDA
E T 和 DELETE 语句子。它们还汇合自行解释,每一样句都接纳语句的 ID
属性和参数对象,参数可以 是原生类型(自动装箱或包装类) ,JavaBean,POJO 或
Map。

<T> T selectOne(String statement, Object parameter)
<E> List<E> selectList(String statement, Object parameter)
<K,V> Map<K,V> selectMap(String statement, Object parameter, String mapKey)
int insert(String statement, Object parameter)
int update(String statement, Object parameter)
int delete(String statement, Object parameter)

  selectOne 和 selectList 的例外就是 selectOne 必须回到一个靶。
假使多被一个, 或者没回去 (或回到了 null) 那么即使会丢掉来很。
假若您不通晓得多少对象, 使用 selectList。
  假若你想检查一个靶是不是在,那么最好返总结数(0 或 1)
。因为并无是兼具语句都需
要参数,那一个形式仍然发生例外重载版本的,它们得以无需参数对象。

<T> T selectOne(String statement)
<E> List<E> selectList(String statement)
<K,V> Map<K,V> selectMap(String statement, String mapKey)
int insert(String statement)
int update(String statement)
int delete(String statement)

  最后,还有查询情势的老三独高级版本,它们允许你限制重回行数的界定,或者提供于自然
义结果决定逻辑,这便用于大气的多少集合。

<E> List<E> selectList (String statement, Object parameter, RowBounds rowBounds)
<K,V> Map<K,V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowbounds)
void select (String statement, Object parameter, ResultHandler<T> handler)
void select (String statement, Object parameter, RowBounds rowBounds, ResultHandler<T> handler)

  RowBounds 参数会告知 MyBatis
略过指定数量之笔录,还有限量重临结果的数目。 RowBounds
类有一个构造方法来收纳 offset 和 limit,否则是不行变更的。

int offset = 100;
int limit = 25;
RowBounds rowBounds = new RowBounds(offset, limit);

  ResultHandler
参数允许而本您喜爱的不二法门处理各一行。ResultHandler接口很粗略

package org.apache.ibatis.session;
public interface ResultHandler<T> {
  void handleResult(ResultContext<? extends T> context);
}

4.3 trim, where, set

  对于“if”示例,这一次大家将“ACTIVE =
1”也安装成动态的尺度,看看会来啊。

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG 
  WHERE 
  <if test="state != null">
    state = #{state}
  </if> 
  <if test="title != null">
    AND title like #{title}
  </if>
  <if test="author != null and author.name != null">
    AND author_name like #{author.name}
  </if>
</select>

  这,若一个还并未匹配上

SELECT * FROM BLOG
WHERE

  若一味分外第二独规范,则会多一个AND。此时得以<where>素。where
元素知道只有在一个以上的if条件有值的情下才去插入“WHERE”子句。而且,若最终的始末是“AND”或“OR”先导的,where
元素也晓得怎么样用她们去。

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG 
  <where> 
    <if test="state != null">
         state = #{state}
    </if> 
    <if test="title != null">
        AND title like #{title}
    </if>
    <if test="author != null and author.name != null">
        AND author_name like #{author.name}
    </if>
  </where>
</select>

  类似之用来动态更新话的化解方案叫做 set。set
元素可以为用来动态包含需要创新的排,而丢弃去其他的。比如:

<update id="updateAuthorIfNecessary">
  update Author
    <set>
      <if test="username != null">username=#{username},</if>
      <if test="password != null">password=#{password},</if>
      <if test="email != null">email=#{email},</if>
      <if test="bio != null">bio=#{bio}</if>
    </set>
  where id=#{id}
</update>

  这里,set 元素会动态前置 SET
关键字,同时也会免去无关的逗号,因为用了原则语句之后好可能就会在扭转的赋值语句之后留下这个逗号。
  其实我们可从定义 trim 元一向定制大家回忆要之效应,比如,和 where
元素等价格的自定义 trim 元素为:

<trim prefix="WHERE" prefixOverrides="AND |OR ">
  ... 
</trim>

  prefixOverrides
属性会忽略通过管道相隔的文本连串(注意此例中之空格也是必需的)。它带动的结果就是是装有以
prefixOverrides 属性中指定的情以受移除,并且插入 prefix
属性中指定的始末。

  set 元素等价格的自定义 trim 元素,注意这里我们忽略的是后缀着的价:

<trim prefix="SET" suffixOverrides=",">
  ...
</trim>

5.2 批量登时更新方法(Flush Method)

  刷新(执行)存储在JDBC驱动类吃之批量更新语句

List<BatchResult> flushStatements()

5.6 使用映射器

  上述的顺序 insert,update,delete 和 select
方法都好强大,但也粗麻烦,没有种安全,对于你的 IDE
和可能的单元测试也并未帮忙。由此,
一个再次通用的计来举行映射语句是以映射器类。推荐应用5.6备受之映射器和5.7的映射器申明
  一个映射器类即是一个简单 的接口,其中的法子定义匹配于 SqlSession
方法。

//注释中的语句对应SqlSession 方法,不推荐!
public interface AuthorMapper {
  // (Author) selectOne("selectAuthor",5);
  Author selectAuthor(int id); 
  // (List<Author>) selectList(“selectAuthors”)
  List<Author> selectAuthors();
  // (Map<Integer,Author>) selectMap("selectAuthors", "id")
  @MapKey("id")
  Map<Integer, Author> selectAuthors();
  // insert("insertAuthor", author)
  int insertAuthor(Author author);
  // updateAuthor("updateAuthor", author)
  int updateAuthor(Author author);
  // delete("deleteAuthor",5)
  int deleteAuthor(int id);
}
  • 术名必须配合配映射语句之
    ID。重回路必须配合期望的结果类型。所有常用之路且是支撑的,包括:原生类型,Map,POJO
    和 JavaBean。
  • 映射器接口不待去落实任何接口或扩充外类似。
  • 汝可以传递四个参数为一个映射器方法。 假诺你这么做了,
    默认情形下它们以会因为其
    在参数列表中之职务来定名,比如:#{param1},#{param2}等。如果您想更改参数的名号(只在多参数情况下)
    ,可以于参数上应用@Param("paramName")注解。
  • 卿啊得为艺术传递一个 RowBounds 实例来限制查询结果。

Logging Configuration

步骤1: 添加 Log4J 的 jar 包
步骤2:配置Log4J
在采纳之classpath中创设一个称呼也log4j.properties的文件,
文件的具体内容如下:

# Global logging configuration
log4j.rootLogger=ERROR, stdout
# MyBatis logging configuration...
log4j.logger.org.mybatis.example.BlogMapper=TRACE
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

累加之上配置后,Log4J就会拿 org.mybatis.example.BlogMapper
的详细实施日志记录下来,对于用中之另类则仅仅记录错误信息。

呢堪以日志从一切mapper接口级别调整至到讲话级别,从而实现再度细致粒度的控制。如下配置才记录
selectBlog 语句的日志:

log4j.logger.org.mybatis.example.BlogMapper.selectBlog=TRACE

同此相对,能够本着同样组mapper接口记录日志,只要针对mapper接口所当的管教被日志效率即可:

log4j.logger.org.mybatis.example=TRACE

某些查询可能相会回到大量的数码,只想记录该实施的SQL语句该怎么惩罚?为之,Mybatis中SQL语
句的日志级别为如为DEBUG(JDK
Logging中也FINE),结果日志的级别为TRACE(JDK
Logging中吗FINER)。所以,只要用日志级别调整为DEBUG即可达到目的:

log4j.logger.org.mybatis.example=DEBUG

若果记录日志的是看似下边的mapper文件而非是mapper接口又欠怎么为?

<?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="org.mybatis.example.BlogMapper">
  <select id="selectBlog" resultType="Blog">
    select * from Blog where id = #{id}
  </select>
</mapper>

本着之文件记录日志,只要针对命名空间多日志记录效用即可:

log4j.logger.org.mybatis.example.BlogMapper=TRACE

更为,要记录具体语句之日记可以这么做:

log4j.logger.org.mybatis.example.BlogMapper.selectBlog=TRACE

第七片段 Logging

Mybatis内置的日志工厂提供日志效能,具体的日记实现有以下两种植工具:

SLF4J
Apache Commons Logging
Log4j 2
Log4j
JDK logging

现实采取什么人日志实现工具由MyBatis的放到日志工厂确定。它会动用初找到的(按上文列举的依次查找)。
倘使一个都非找到,日志功用就是会让剥夺。
乃可通过在MyBatis的配置文件mybatis-config.xml里面加加同码setting(配置)来抉择一个例外的日志实现,logImpl可摘的价值有:SLF4J、LOG4J、LOG4J2、JDK_LOGGING、COMMONS_LOGGING、STDOUT_LOGGING、NO_LOGGING
或者是兑现了接口org.apache.ibatis.logging.Log的近乎的毕限定类名。

<configuration>
  <settings>
    ...
    <setting name="logImpl" value="LOG4J"/>
    ...
  </settings>
</configuration>

季组成部分 动态 SQL

  动态 SQL 元素和以 JSTL 或外类似基于 XML
的文本处理器相似。MyBatis 拔取功用强大的因 OGNL
的表明式来解除其他因素。

if
choose (when, otherwise)
trim (where, set)
foreach

Mybatis基本用法–中

4.4 foreach

  动态 SQL
的其它一个常用之必需操作是内需针对一个谋面举行遍历,日常是以构建 IN
条件语句的时节。比如:

<select id="selectPostIn" resultType="domain.blog.Post">
  SELECT *
  FROM POST P
  WHERE ID in
  <foreach item="item" index="index" collection="list"
      open="(" separator="," close=")">
        #{item}
  </foreach>
</select>

  它吧同意而指定开闭匹配的字符串以及当迭代中间放置分隔符。你可将另可迭代对象(如列表、集合等)和另的字典或者数组对象传递给foreach作为集参数。当以可迭代对象或数组时,index是现阶段迭代的次数,item的价是本次迭代获取的要素。当以字典(或者Map.Entry对象的汇)时,index是键,item是价值。

5.3 事务控制方法

  控制工作功用域有三只点子。 当然,
即便你曾摘了自行提交或你方选用外部事务管理器,这便从不外功效了。然则,假如您正利用
JDBC 事务管理器,由 Connection 实例来支配,那么就两个情势就碰面派上用场:

void commit()
void commit(boolean force)
void rollback()
void rollback(boolean force)

  注意MyBatis-Spring和MyBatis-Guice提供了声称事务处理,所以假使您于应用Mybatis的而用了Spring或者Guice,那么请参考其的手册以博取更多的内容。

4.1 if

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG WHERE state = ‘ACTIVE’ 
  <if test="title != null">
    AND title like #{title}
  </if>
  <if test="author != null and author.name != null">
    AND author_name like #{author.name}
  </if>
</select>

  注意这种状态传入的title中应当包含%或者_,否则,可以使下的bind素。like模糊查询中,%通配任意字符,_通配一个字符。

5.5 确保 SqlSession 被关闭

SqlSession session = sqlSessionFactory.openSession();
try {
    // following 3 lines pseudocod for "doing some work"
    session.insert(...);
    session.update(...);
    session.delete(...);
    session.commit();
} finally {
    session.close();
}

4.2 choose, when, otherwise

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG WHERE state = ‘ACTIVE’
  <choose>
    <when test="title != null">
      AND title like #{title}
    </when>
    <when test="author != null and author.name != null">
      AND author_name like #{author.name}
    </when>
    <otherwise>
      AND featured = 1
    </otherwise>
  </choose>
</select>

  有点类似于Java 中的 switch
语句,但她不需break也只是汇合进行同样种植情形依然无履行(没有匹配的)。

第六有些 SQL语句构建器类

过去大家以Java中形容sql语句:

String sql = "SELECT P.ID, P.USERNAME, P.PASSWORD, P.FULL_NAME, "
"P.LAST_NAME,P.CREATED_ON, P.UPDATED_ON " +
"FROM PERSON P, ACCOUNT A " +
"INNER JOIN DEPARTMENT D on D.ID = P.DEPARTMENT_ID " +
"INNER JOIN COMPANY C on D.COMPANY_ID = C.ID " +
"WHERE (P.ID = A.ID AND P.FIRST_NAME like ?) " +
"OR (P.LAST_NAME like ?) " +
"GROUP BY P.ID " +
"HAVING (P.LAST_NAME like ?) " +
"OR (P.FIRST_NAME like ?) " +
"ORDER BY P.ID, P.FULL_NAME";

今昔(优先用底的变长参数方法):

private String selectPersonSql() {
  return new SQL() {{
    SELECT("P.ID, P.USERNAME, P.PASSWORD, P.FULL_NAME");
    SELECT("P.LAST_NAME, P.CREATED_ON, P.UPDATED_ON");
    FROM("PERSON P");
    FROM("ACCOUNT A");
    INNER_JOIN("DEPARTMENT D on D.ID = P.DEPARTMENT_ID");
    INNER_JOIN("COMPANY C on D.COMPANY_ID = C.ID");
    WHERE("P.ID = A.ID");
    WHERE("P.FIRST_NAME like ?");
    OR();
    WHERE("P.LAST_NAME like ?");
    GROUP_BY("P.ID");
    HAVING("P.LAST_NAME like ?");
    OR();
    HAVING("P.FIRST_NAME like ?");
    ORDER_BY("P.ID");
    ORDER_BY("P.FULL_NAME");
  }}.toString();
}

给闹一部分事例:

// With conditionals (note the final parameters, required for the anonymous inner class to access them)
public String selectPersonLike(final String id, final String firstName, final String lastName) {
  return new SQL() {{
    SELECT("P.ID, P.USERNAME, P.PASSWORD, P.FIRST_NAME, P.LAST_NAME");
    FROM("PERSON P");
    if (id != null) {
      WHERE("P.ID like #{id}");
    }
    if (firstName != null) {
      WHERE("P.FIRST_NAME like #{firstName}");
    }
    if (lastName != null) {
      WHERE("P.LAST_NAME like #{lastName}");
    }
    ORDER_BY("P.LAST_NAME");
  }}.toString();
}

public String updatePersonSql() {
  return new SQL() {{
    UPDATE("PERSON");
    SET("FIRST_NAME = #{firstName}");
    WHERE("ID = #{id}");
  }}.toString();
}

public String deletePersonSql() {
  return new SQL() {{
    DELETE_FROM("PERSON");
    WHERE("ID = #{id}");
  }}.toString();
}

public String insertPersonSql() {
  return new SQL() {{
    INSERT_INTO("PERSON");
    VALUES("ID, FIRST_NAME", "#{id}, #{firstName}");
    VALUES("LAST_NAME", "#{lastName}");
  }}.toString();
}
方法 描述
SELECT(String…) 参数是使用逗号分隔的列名和别名列表,但也可以是数据库驱动程序接受的任意类型。
FROM(String…) from
JOIN(String…)
INNER_JOIN(String…)
LEFT_OUTER_JOIN(String)
LEFT_OUTER_JOIN(String…)
RIGHT_OUTER_JOIN(String)
RIGHT_OUTER_JOIN(String…)
参数可以包含由列命和join on条件组合成标准的join。
WHERE(String…) 插入新的 WHERE子句条件,由AND链接。可以多次被调用,每次都由AND来链接新条件。使用 OR() 来分隔OR。
OR() 使用OR来分隔当前的 WHERE子句条件。 可以被多次调用,但在一行中多次调用或生成不稳定的SQL。
AND() 使用AND来分隔当前的 WHERE子句条件。 可以被多次调用,但在一行中多次调用可能生成不稳定的SQL。因为 WHERE 和 HAVING 二者都会自动链接 AND,只是为了完整性才被使用,一般不用主动用。
GROUP_BY(String…) 插入新的 GROUP BY子句元素,由逗号连接。 可以被多次调用,每次都由逗号连接新的条件。
HAVING(String…) 插入新的 HAVING子句条件。 由AND连接。可以被多次调用,每次都由AND来连接新的条件。使用 OR() 来分隔OR.
ORDER_BY(String…) 插入新的 ORDER BY子句元素, 由逗号连接。可以多次被调用,每次由逗号连接新的条件。
DELETE_FROM(String) 开始一个delete语句并指定需要从哪个表删除的表名。通常它后面都会跟着WHERE语句!
INSERT_INTO(String) 开始一个insert语句并指定需要插入数据的表名。后面都会跟着一个或者多个VALUES() or INTO_COLUMNS() and INTO_VALUES()。
SET(String…) 针对update语句,插入到"set"列表中
UPDATE(String) 开始一个update语句并指定需要更新的表名。后面都会跟着一个或者多个SET(),通常也会有一个WHERE()。
VALUES(String, String) 插入到insert语句中。第一个参数是要插入的列名,第二个参数则是该列的值。
INTO_COLUMNS(String…) Appends columns phrase to an insert statement. This should be call INTO_VALUES() with together.
INTO_VALUES(String…) Appends values phrase to an insert statement. This should be call INTO_COLUMNS() with together.

从今本3.4.2,可以动用变长参数:

public String selectPersonSql() {
  return new SQL()
    .SELECT("P.ID", "A.USERNAME", "A.PASSWORD", "P.FULL_NAME", "D.DEPARTMENT_NAME", "C.COMPANY_NAME")
    .FROM("PERSON P", "ACCOUNT A")
    .INNER_JOIN("DEPARTMENT D on D.ID = P.DEPARTMENT_ID", "COMPANY C on D.COMPANY_ID = C.ID")
    .WHERE("P.ID = A.ID", "P.FULL_NAME like #{name}")
    .ORDER_BY("P.ID", "P.FULL_NAME")
    .toString();
}

public String insertPersonSql() {
  return new SQL()
    .INSERT_INTO("PERSON")
    .INTO_COLUMNS("ID", "FULL_NAME")
    .INTO_VALUES("#{id}", "#{fullName}")
    .toString();
}

public String updatePersonSql() {
  return new SQL()
    .UPDATE("PERSON")
    .SET("FULL_NAME = #{fullName}", "DATE_OF_BIRTH = #{dateOfBirth}")
    .WHERE("ID = #{id}")
    .toString();
}

5.7 映射器表明

注有脚这多少个:

注解 目标 相对应的 XML 描述
@CacheNamespace <cache> 为给定的命名空间 (比如类) 配置缓存。 属性:implemetation,eviction, flushInterval,size,readWrite,blocking 和 properties。
@Property N/A <property> 属性名和属性位置
@ConstructorArgs 方法 <constructor> 收集一组结果传递给一个对象的 构造方法。属性:value,是数组形式的参数。
@Case N/A <case> 值和它对应的映射的简单情况。属性: value,type,results。Results 属性是结 果数组,因此这个注解和实际的 ResultMap 很相似,由下面的 Results 注解指定。
@Results 方法 <resultMap> Result映射的列表, 包含列如何被映射到属性或字段的详情。 属 性:value, id。value 属性是 Result 注解的数组。这个id的属性是结果映射的名称。
@Result N/A <result><id> 在列和属性或字段之间的单独结果映射。属 性:id,column, property, javaType ,jdbcType ,type Handler, one,many。id 属性是一个布尔值,表 示了应该被用于比较(和在 XML 映射 中的相似)的属性。one 属性是单 独 的 联 系, 和 <association>相 似 , 而 many 属 性 是 对 集 合 而 言 的 , 和 <collection>相似。 它们这样命名是为了 避免名称冲突。
@One N/A <association> 复杂类型的单独属性值映射。属性: select,已映射语句(也就是映射器方 法)的完全限定名,它可以加载合适类 型的实例。
@Many N/A <collection> 映射到复杂类型的集合属性。属性:select,已映射语句(也就是映射器方法)的全限定名, 它可以加载合适类型的实例的集合
@Options 方法 映射语句的属性 它们通常在映射语句上作为 属性出现。属性:useCache=true , flushCache=FlushCachePolicy.DEFAULT , resultSetType=FORWARD_ONLY , statementType=PREPARED , fetchSize=-1 , timeout=-1 useGeneratedKeys=false , keyProperty=”id” , keyColumn=”” , resultSets=””。
@Insert
@Update
@Delete
@Select
方法 <insert><update><delete><select> 这些注解中的每一个代表了执行的真实 SQL。
@Param Parameter N/A 映射器的方法参数命名,默认:#{param1} , #{param2} 等 。 使 用 @Param(“person”),参数应该被命名为 #{person}。
@ResultMap 方法 N/A 给@Select或者@SelectProvider提供在XML映射中的<resultMap>的id。
@InsertProvider
@UpdateProvider
@DeleteProvider
@SelectProvider
Method <insert>``<update>``<delete>``<select> 允许你指定一个 类名和一个方法在运行时动态创建SQL。

可是事实上:Java
注明限制了它们的呈现和灵活,所以简单的法子运用注明,复杂的办法以xml配置。
例子:

@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);

@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();
  }
}

留意点的||凡是字符串连接符,在MySQL中,一般用concat函数。

网站地图xml地图