MyBatis使用大全(4)------XML映射文件配置

MyBatis真正的强大,在于其映射语句的魔力。

SQL 映射文件有很少的几个顶级元素(按照它们应该被定义的顺序):

(1)cache  给定命名空间的配置缓存。

(2)cache-ref  其他命名空间缓存配置的引用。

(3)resultMap  是最复杂也是最强大的元素,用来描述如何从数据库结果集中来加载对象

(4)sql 可被其他语句引用的可重用语句块。

(5)insert 映射插入语句

(6)update  映射更新语句

(7)delete   映射删除语句

(8)select   映射查询语句


在我们描述每个元素细节之前,我们先感受一些元素的使用实例,

以下实例分为UserMainMapper.XML配置的XML版本和java注解版本,

也可以根据实际情况两种都用,但是同名方法只能用XML或java注解,

先不多少,看实例,这里将入门体验文章做简化,分析元素。

一,准备条件

--jar

mybatis-3.2.2.jar --mybatisjar

ojdbc6.jar --数据库驱动,这个地方用的是oracle,而入门体验中用的是Mysql,所以驱动不一样

junit-4.4.jar --单元测试

--数据库表

--建表
CREATE TABLE t_user_main(
       f_id NUMBER(3) PRIMARY KEY,
       f_username VARCHAR(4),
       f_age NUMBER(3)
);
--设置主键自增长
CREATE SEQUENCE user_sequence
INCREMENT BY 1 -- 每次加几个
START WITH 1 -- 从1开始计数
NOMAXVALUE -- 不设置最大值
NOCYCLE -- 一直累加,不循环
--插入测试数据
INSERT INTO t_user_main(f_id,f_username,f_age)VALUES(1,'one',25);
INSERT INTO t_user_main(f_id,f_username,f_age)VALUES(2,'two',25);
COMMIT;
--查询
SELECT * FROM t_user_main;

二,项目结构


三,test-jdbc.properties和mybatis-config.xml配置

test-jdbc.properties:

jdbc.driver=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@localhost:1521/XE
jdbc.username=system
jdbc.password=123456

mybatis-config:

<?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="test-jdbc.properties"/>
	<!-- 设置(settings) -->
	<!-- <settings>
	  <setting name="cacheEnabled" value="true"/>
	  <setting name="lazyLoadingEnabled" value="true"/>
	  <setting name="multipleResultSetsEnabled" value="true"/>
	  <setting name="useColumnLabel" value="true"/>
	  <setting name="useGeneratedKeys" value="false"/>
	  <setting name="autoMappingBehavior" value="PARTIAL"/>
	  <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
	  <setting name="defaultExecutorType" value="SIMPLE"/>
	  <setting name="defaultStatementTimeout" value="25"/>
	  <setting name="defaultFetchSize" value="100"/>
	  <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> -->
	<!-- 别名(typeAliases) -->
	<!-- <typeAliases>
		<typeAlias alias="User" type="com.lanhuigu.mybatis.entity.User"/>
	</typeAliases> -->
	<!-- 
		environments环境
			*environment 环境变量 
				*transactionManager 事务管理器
				*dataSource 数据源
	 -->
	 <environments default="development">
	 	<environment id="development">
	 		<transactionManager type="JDBC"/>
	 		<dataSource type="POOLED">
	 			<property name="driver" value="${jdbc.driver}"/>
	 			<property name="url" value="${jdbc.url}"/>
	 			<property name="username" value="${jdbc.username}"/>
	 			<property name="password" value="${jdbc.password}"/>
	 		</dataSource>
	 	</environment>
	 </environments>
	<!-- mappers映射器 -->
	<mappers>
		<!-- <mapper resource="com/lanhuigu/mybatis/map/UserMainMapper.xml"/> -->
		<package name="com.lanhuigu.mybatis.map"/>
	</mappers>
</configuration>

四,User.java,UserMainMapper.java接口和UserMainMapper.xml配置(Mapper)

User.java

package com.lanhuigu.mybatis.entity;

import java.io.Serializable;

public class User implements Serializable{

	private static final long serialVersionUID = -3412068097348759984L;
	
	private Integer id;
	private String username;
	private Integer age;
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}

}

UserMainMapper.java(接口)

package com.lanhuigu.mybatis.map;

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.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

import com.lanhuigu.mybatis.entity.User;

public interface UserMainMapper {
	//=======================XML版=======================
	/**
	 * 查询用户对象--返回User对象
	 */
	public User queryUserMainById(int id);
	/**
	 * 查询用户对象--返回多个--List<User>
	 */
	public List<User> queryUserMainList();
	/**
	 * 查询用户对象--返回map
	 */
	public Map<String,Object> queryUserMainResultMap(int id);
	/**
	 * 查询用户对象--返回多个--List<Map<String,Object>>
	 */
	public List<Map<String,Object>> queryUserMainResultListMap();
	/**
	 * 插入用户对象
	 */
	public int insertUser(User user);
	/**
	 * 更新用户对象
	 */
	public int updateUser(User user);
	/**
	 * 删除用户对象
	 */
	public int deleteUser(int id);
	
	//=======================注解版==========================
	/**
	 * 查询用户对象--返回User对象
	 */
	@Select(" select f_id id,f_username username,f_age age from t_user_main where f_id = #{id} ")
	@Options(flushCache=true)
	public User queryUserMainByIdNew(@Param("id") int id);
	/**
	 * 查询用户对象--返回多个--List<User>
	 */
	@Select("select f_id id,f_username username,f_age age from t_user_main ")
	@Options(flushCache=true)
	public List<User> queryUserMainListNew();
	/**
	 * 查询用户对象--返回map
	 */
	@Select("select f_id id,f_username username,f_age age from t_user_main where f_id = #{id}")
	@Options(flushCache=true)
	public Map<String,Object> queryUserMainResultMapNew(@Param("id") int id);
	/**
	 * 查询用户对象--返回多个--List<Map<String,Object>>
	 */
	@Select("select f_id id,f_username username,f_age age from t_user_main")
	@Options(flushCache=true)
	public List<Map<String,Object>> queryUserMainResultListMapNew();
	/**
	 * 插入用户对象
	 */
	@Insert("insert into t_user_main (f_id,f_username,f_age) "
			+ " values(#{id},#{username},#{age}) ")
	@Options(useGeneratedKeys=false)
	public int insertUserNew(User user);
	/**
	 * 更新用户对象
	 */
	@Update("update t_user_main set f_username=#{username},f_age=#{age} "
			+ " where f_id=#{id} ")
	public int updateUserNew(User user);
	/**
	 * 删除用户对象
	 */
	@Delete("delete from t_user_main where f_id=#{id}")
	@Options(flushCache=true)
	public int deleteUserNew(@Param("id") int id);
}

UserMainMapper.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="com.lanhuigu.mybatis.map.UserMainMapper">
  <!-- 查询用户对象,返回User对象 -->
  <select id="queryUserMainById" 
    parameterType="int" 
    flushCache="true" 
  	resultType="com.lanhuigu.mybatis.entity.User">
    select 
    	f_id id,
    	f_username username,
    	f_age age
    from t_user_main 
    where f_id = #{id}
  </select>
  <!-- 查询用户对象,返回list<User> -->
  <select id="queryUserMainList" 
    flushCache="true" 
  	resultType="com.lanhuigu.mybatis.entity.User">
    select 
    	f_id id,
    	f_username username,
    	f_age age
    from t_user_main 
  </select>
  <!-- 查询用户对象,返回Map -->
  <select id="queryUserMainResultMap" 
  	parameterType="int" 
  	flushCache="true"
  	resultType="java.util.HashMap">
    select 
    	f_id id,
    	f_username username,
    	f_age age
    from t_user_main 
    where f_id = #{id}
  </select>
 <!--  查询用户对象,返回List<Map<String,Object>> -->
  <select id="queryUserMainResultListMap" 
    flushCache="true"
  	resultType="java.util.HashMap">
    select 
    	f_id id,
    	f_username username,
    	f_age age
    from t_user_main 
  </select>
  <!-- 插入用户对象(insert) -->
  <insert id="insertUser" 
  	parameterType="com.lanhuigu.mybatis.entity.User"
  	useGeneratedKeys="false">
  	insert into t_user_main (f_id,f_username,f_age) 
  	values(#{id},#{username},#{age})
  </insert>
  
  <!-- 更新用户对象(update) -->
  <update id="updateUser"
        parameterType="com.lanhuigu.mybatis.entity.User"
       flushCache="true">
  	update t_user_main set f_username=#{username},f_age=#{age}
  	where f_id=#{id}
  </update>
  
 <!--  删除用户对象(delete) -->
  <delete id="deleteUser"
        parameterType="int"
       flushCache="true">
  	delete from t_user_main where f_id=#{id}
  </delete>
  
</mapper>

五,测试代码

package com.lanhuigu.mybatis;

import java.io.InputStream;
import java.util.List;
import java.util.Map;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import com.lanhuigu.mybatis.entity.User;
import com.lanhuigu.mybatis.map.UserMainMapper;

public class MyBatisTest {
	@Test
	public void testMyBatis() {
		String resource = "mybatis-config.xml";
		SqlSessionFactory sqlSessionFactory = null;
		SqlSession session = null;
		try {
			//读取资源文件
			InputStream is = Resources.getResourceAsStream(resource);
			sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
			session = sqlSessionFactory.openSession();
			//mapper调用
			UserMainMapper userMainMapper = session.getMapper(UserMainMapper.class);
			//================XML测试=================
			//查询--select--返回User对象
			User user = userMainMapper.queryUserMainById(1);
			System.out.println("user="+user);
			System.out.println(user.getUsername());
			//查询--select--返回多个User对象--List<User>
			/*List<User> list = userMainMapper.queryUserMainList();
			for(int i=0;i<list.size();i++ ){
				User user = list.get(i);
				System.out.println(user.getUsername());
			}*/
			//查询--select--返回map
			/*Map<String,Object> userMap = userMainMapper.queryUserMainResultMap(1);
			System.out.println("userMap="+userMap);
			System.out.println(userMap.get("USERNAME"));*/
			//查询--select--返回List<Map<String,Object>>
			/*List<Map<String,Object>> list = userMainMapper.queryUserMainResultListMap();
			System.out.println("ListMap="+list);
			for (int i=0;i<list.size();i++) {
				Map<String,Object> userMap = list.get(i);
				System.out.println(userMap.get("USERNAME"));
			}*/
			
			//插入--insert
			/*User user = new User();
			user.setId(3);
			user.setUsername("three");
			user.setAge(25);
			
			int result = userMainMapper.insertUser(user);
			if (result > 0) {
				System.out.println("添加用户成功");
				//事务提交
				session.commit();
			} else {
				System.out.println("添加用户失败");
				//事务回滚
				session.rollback();
			}*/
			
			//更新--update
			/*User user = new User();
			user.setId(3);
			user.setUsername("this three update");
			user.setAge(25);
			
			int result = userMainMapper.updateUser(user);
			if (result > 0) {
				System.out.println("更新成功");
				//事务提交
				session.commit();
			} else {
				System.out.println("更新失败");
				//事务回滚
				session.rollback();
			}*/
			
			//删除--delete
			/*int result = userMainMapper.deleteUser(3);
			if (result > 0) {
				System.out.println("删除成功");
				//事务提交
				session.commit();
			} else {
				System.out.println("删除失败");
				//事务回滚
				session.rollback();
			}*/
			
			//=================注解测试===================
			/*
			 * 只需将xml测试代码copy一份,然后将方法名都加上一个New即可
			 * 在UserMainMapper.java映射器中原本可以将xml部分注释,
			 * 注解部分方法用同名,但是这样做我们就得将UserMainMapper.xml删掉,
			 * 或者改名,否则注解不能查询出数值,着跟命名空间和class,xml加载有关系.
			 * 总之class中和xml中不能出现注解和xml同时使用,对于单个方法,二者
			 * 只能存在其一,否则mybatis不知道你到底想干啥,只能什么都不做了
			 */
			//eg.
			/*User user = userMainMapper.queryUserMainByIdNew(1);
			System.out.println("user="+user);
			System.out.println(user.getUsername());*/
		} catch (Exception e) {
			if (session != null) {
				session.close();
			}
		}
	}	
}


有了上面的体验,我们在对每个元素等等进行分析,然后在参考实例,能体验更深。

结合上面的实例对元素进行分析和补充。

select元素

查询语句是MyBatis中最常用的元素,作为一个持久层框架,把数据放入数据库是一个方面,

把数据取一条或多条更是重中之重。简单查询语句:

  <select id="queryUserMainById" 
    parameterType="int" 
    flushCache="true" 
  	resultType="com.lanhuigu.mybatis.entity.User">
    select 
    	f_id id,
    	f_username username,
    	f_age age
    from t_user_main 
    where f_id = #{id}
  </select>

这个语句称之为queryUserMainById,接受一个int或Integer的参数,

返回一个com.lanhuigu.mybatis.entity.User的对象,这个如果嫌写起来长,

可以在mybatis-config.xml中配置别名,这个地方直接用别名替代。

别名配置:

<typeAliases>
	<typeAlias alias="User" type="com.lanhuigu.mybatis.entity.User"/>
</typeAliases>
select语句中参数id符号:

#{id}获取传入的参数。

这样MyBatis处理时底层用JDBC生产预编译语句,JDBC底层MyBatis替我们做了,

这样我们只需关注MyBatis的应用,避免写大量的JDBC代码,提高工作效率,调用时直接执行。

select元素有很多属性可供选择,如下:

<select
  id="queryUserMainById"
  parameterType="int"
  parameterMap="deprecated"
  resultType="hashmap"
  resultMap="userMainResultMap"
  flushCache="false"
  useCache="true"
  timeout="10000"
  fetchSize="256"
  statementType="PREPARED"
  resultSetType="FORWARD_ONLY">
select元素相关属性的描述,如下:

属性 描述
id 在命名空间中唯一的标识符,可以被用来引用这条语句。
parameterType 将会传入这条语句的参数类的完全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过 TypeHandler 推断出具体传入语句的参数,默认值为 unset。
parameterMap 这是引用外部 parameterMap 的已经被废弃的方法。使用内联参数映射和 parameterType 属性。
resultType 从这条语句中返回的期望类型的类的完全限定名或别名。注意如果是集合情形,那应该是集合可以包含的类型,而不能是集合本身。使用 resultType 或 resultMap,但不能同时使用。
resultMap 外部 resultMap 的命名引用。结果集的映射是 MyBatis 最强大的特性,对其有一个很好的理解的话,许多复杂映射的情形都能迎刃而解。使用 resultMap 或 resultType,但不能同时使用。
flushCache 将其设置为 true,任何时候只要语句被调用,都会导致本地缓存和二级缓存都会被清空,默认值:false。
useCache 将其设置为 true,将会导致本条语句的结果被二级缓存,默认值:对 select 元素为 true。
timeout 这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为 unset(依赖驱动)。
fetchSize 这是尝试影响驱动程序每次批量返回的结果行数和这个设置值相等。默认值为 unset(依赖驱动)。
statementType STATEMENT,PREPARED 或 CALLABLE 的一个。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。
resultSetType FORWARD_ONLY,SCROLL_SENSITIVE 或 SCROLL_INSENSITIVE 中的一个,默认值为 unset (依赖驱动)。
databaseId 如果配置了 databaseIdProvider,MyBatis 会加载所有的不带 databaseId 或匹配当前 databaseId 的语句;如果带或者不带的语句都有,则不带的会被忽略。
resultOrdered 这个设置仅针对嵌套结果 select 语句适用:如果为 true,就是假设包含了嵌套结果集或是分组了,这样的话当返回一个主结果行的时候,就不会发生有对前面结果集的引用的情况。这就使得在获取嵌套的结果集的时候不至于导致内存不够用。默认值:false
resultSets 这个设置仅对多结果集的情况适用,它将列出语句执行后返回的结果集并每个结果集给一个名称,名称是逗号分隔的。

insert,update和delete元素

数据插入(insert),数据更新(update),数据删除(delete)实现大同小异。例如:

<span><!-- 插入用户对象(insert) -->
  <insert id="insertUser" 
  	parameterType="com.lanhuigu.mybatis.entity.User"
  	useGeneratedKeys="false">
  	insert into t_user_main (f_id,f_username,f_age) 
  	values(#{id},#{username},#{age})
  </insert>
  
  <!-- 更新用户对象(update) -->
  <update id="updateUser"
  	parameterType="com.lanhuigu.mybatis.entity.User"
  	flushCache="true">
  	update t_user_main set f_username=#{username},f_age=#{age}
  	where f_id=#{id}
  </update>
  
 <!--  删除用户对象(delete) -->
  <delete id="deleteUser"
  	parameterType="int"
  	flushCache="true">
  	delete from t_user_main where f_id=#{id}
  </delete></span>
这三个元素的属性描述如下:

属性 描述
id 命名空间中的唯一标识符,可被用来代表这条语句。
parameterType 将要传入语句的参数的完全限定类名或别名。这个属性是可选的,因为 MyBatis 可以通过 TypeHandler 推断出具体传入语句的参数,默认值为 unset。
parameterMap 这是引用外部 parameterMap 的已经被废弃的方法。使用内联参数映射和 parameterType 属性。
flushCache 将其设置为 true,任何时候只要语句被调用,都会导致本地缓存和二级缓存都会被清空,默认值:true(对应插入、更新和删除语句)。
timeout 这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为 unset(依赖驱动)。
statementType STATEMENT,PREPARED 或 CALLABLE 的一个。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。
useGeneratedKeys (仅对 insert 和 update 有用)这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server 这样的关系数据库管理系统的自动递增字段),默认值:false。
keyProperty (仅对 insert 和 update 有用)唯一标记一个属性,MyBatis 会通过 getGeneratedKeys 的返回值或者通过 insert 语句的 selectKey 子元素设置它的键值,默认:unset。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。
keyColumn (仅对 insert 和 update 有用)通过生成的键值设置表中的列名,这个设置仅在某些数据库(像 PostgreSQL)是必须的,当主键列不是表中的第一列的时候需要设置。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。
databaseId 如果配置了 databaseIdProvider,MyBatis 会加载所有的不带 databaseId 或匹配当前 databaseId 的语句;如果带或者不带的语句都有,则不带的会被忽略。

sql元素

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

它可以被静态地(在加载参数) 参数化. 不同的属性值通过包含的实例变化。

把上面的实例中UserMainMapper.xml修改,来个简单实例:

  <!-- sql语句块 -->
  <sql id="queryConditionSql">
   	f_id = #{id}
  </sql>	
  <!-- 查询用户对象,返回User对象 -->
  <select id="queryUserMainById" 
    parameterType="int" 
    flushCache="true" 
  	resultType="com.lanhuigu.mybatis.entity.User">
    select 
    	f_id id,
    	f_username username,
    	f_age age
    from t_user_main 
    <where>
    	<include refid="queryConditionSql"/>
    </where>
  </select>
将查询语句的条件由where f_id=#{id}修改成sql语句块替代。

这样整个xml中条件部分共同的地方都提出来,避免重复啰嗦。

当然,sql语句块除了可以用于条件部分,还可以用于其它任地方,

比如:

  <!-- sql语句块 -->
  <sql id="queryConditionSql">
   	f_id = #{id}
  </sql>	
  <sql id="att">
  	f_username username,
  	f_age age
  </sql>
  <!-- 查询用户对象,返回User对象 -->
  <select id="queryUserMainById" 
    parameterType="int" 
    flushCache="true" 
  	resultType="com.lanhuigu.mybatis.entity.User">
    select 
    	f_id id,
    	<include refid="att"/>
    from t_user_main 
    <where>
    	<include refid="queryConditionSql"/>
    </where>
  </select>
查询时,效果一样。

总结:

(1)sql语句块用于提出xml共同sql

(2)sql语句块可以置于xml文件中查询语句前后,位置无关系,都能调用。

参数(parameters)

但是

MyBatis的参数功能是非常强大的,前面用到的sql中,如果parameterType="int"
只是进行一个简单的整数传入,但是,在插入语句中,我们传入的是类型User对象:

<insert id="insertUser" 
  	parameterType="com.lanhuigu.mybatis.entity.User"
  	useGeneratedKeys="false">
  	insert into t_user_main (f_id,f_username,f_age) 
  	values(#{id},#{username},#{age})
  </insert>

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

这点对于向语句中传参是比较好的而且又简单,不过参数映射的功能远不止于此。

首先,像 MyBatis 的其他部分一样,参数也可以指定一个特殊的数据类型。

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

像 MyBatis 的剩余部分一样,javaType 通常可以从参数对象中来去确定,前提是只要对象不是一个 HashMap。那么 javaType 应该被确定来保证使用正确类型处理器。

NOTE 如果 null 被当作值来传递,对于所有可能为空的列,JDBC Type 是需要的。你可以自己通过阅读预处理语句的 setNull() 方法的 JavaDocs 文档来研究这种情况。

为了以后定制类型处理方式,你也可以指定一个特殊的类型处理器类(或别名),比如:

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

尽管看起来配置变得越来越繁琐,但实际上是很少去设置它们。

对于数值类型,还有一个小数保留位数的设置,来确定小数点后保留的位数。

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

最后,mode 属性允许你指定 IN,OUT 或 INOUT 参数。如果参数为 OUT 或 INOUT,参数对象属性的真实值将会被改变,就像你在获取输出参数时所期望的那样。如果 mode 为 OUT(或 INOUT),而且 jdbcType 为 CURSOR(也就是 Oracle 的 REFCURSOR),你必须指定一个 resultMap 来映射结果集到参数类型。要注意这里的 javaType 属性是可选的,如果左边的空白是 jdbcType 的 CURSOR 类型,它会自动地被设置为结果集。

#{department, mode=OUT, jdbcType=CURSOR, javaType=ResultSet, resultMap=departmentResultMap}

MyBatis 也支持很多高级的数据类型,比如结构体,但是当注册 out 参数时你必须告诉它语句类型名称。比如(再次提示,在实际中要像这样不能换行):

#{middleInitial, mode=OUT, jdbcType=STRUCT, jdbcTypeName=MY_TYPE, resultMap=departmentResultMap}

尽管所有这些强大的选项很多时候你只简单指定属性名,其他的事情 MyBatis 会自己去推断,最多你需要为可能为空的列名指定 jdbcType

#{firstName}
#{middleInitial,jdbcType=VARCHAR}
#{lastName}
一个完整的配置,这个直接考用工作的xml:

<insert id="addUser" parameterType="com.lanhuigu.core.dao.model.user.User" 
        useGeneratedKeys="true" keyColumn="f_userId" flushCache="true">
		insert into t_user_main (
		f_userId ,   
	        f_userName ,    
	        f_email ,   
	        f_password ,   
	        f_isPayPassword ,   
	        f_mobile ,   
	        f_registerTime ,   
	        f_role ,   
	        f_status ,   
	        f_realAuth ,   
	        f_redInviteCode,
	        f_redBeInviteCode,
	        f_version  )
		values(
			#{userId,jdbcType=VARCHAR},
			#{userName,jdbcType=VARCHAR},
			#{email,jdbcType=VARCHAR},
 			#{password,jdbcType=VARCHAR}		, 
			#{isPayPassword,jdbcType=VARCHAR},
			#{mobile,jdbcType=VARCHAR},
			#{registerTime,jdbcType=VARCHAR},
			#{roles,jdbcType=VARCHAR},
			#{status,jdbcType=VARCHAR},
			#{realAuth,jdbcType=VARCHAR},
			#{redInviteCode,jdbcType=VARCHAR},
			#{redBeInviteCode,jdbcType=VARCHAR},
			#{version,jdbcType=VARCHAR}
		)
</insert>

字符串替换

在上面中,很多地方用到#{},默认情况下,使用#{}格式的语法会导致 MyBatis 创建预处理语句属性并安全地设置值(比如?)。

这样做更安全,更迅速,通常也是首选做法,不过有时你只是想直接在 SQL 语句中插入一个不改变的字符串,

或者在条件放一个字符串。比如:

f_id = ${id}

以这种方式接受从用户输出的内容并提供给语句中不变的字符串是不安全的,

会导致潜在的 SQL 注入攻击,因此要么不允许用户输入这些字段,要么自行转义并检验。

本页内容版权归属为原作者,如有侵犯您的权益,请通知我们删除。
1、Maven构建Spring Boot 创建Maven Web工程,引入spring-boot-starter-parent依赖 project xmlns = "http://maven.apache.org/POM/4.0.0" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/m

平衡搜索树之AVLTree - 2016-07-24 14:07:56

今天我想要在这里写下个人觉得比较难的数据结构---AVL树的一些些心得。 一。了解一种新的数据结构,首先要搞懂它的定义 : AVL树又称为高度平衡的二叉搜索树,是1962年有俄罗斯的数学家G.M.Adel'son-Vel'skii和E.M.Landis提出来的。它能保持二叉树的高度 平衡,尽量降低二叉树的高度,减少树的平均搜索长度。所以严格点来说,对于一棵搜索二叉树,能达到O(logn)的只是AVL树,因为他对于二叉树的深度控制的最为严格 ,那么这是为什么呢?让我们来看看 AVL树的性质 : 左子树和右子

linux基础知识 - 2016-07-24 14:07:48

1:基本知识 微内核:是一种提供必要服务的操作系统内核,大部分内核都作为单独的进程在特权模式先运行,他们通过消息传递进行通讯 单内核:单内核是个很大的进程,他的内部又悲愤为若干个模块,是个单独的二进制但印象,其模块间的通讯是通过直接调用其他模块中的函数实现的,而不是消息传递。 linux分几种应用程序级别 Ring 0 特权模式 一般是系统底层运行级别 Ring3 应用程序级别 一般的级别 有时候应用进程为了调用系统底层的模块,可能会在用户空间和内核空间之间进行来回的切换,这是很耗时间的,平时工作中应注意
1. 概述 嵌入式系统由硬件环境、嵌入式操作系统和应用程序组成,硬件环境是操作系统和应用程序运行的硬件平台,它随应用的不同而有不同的要求。硬件平台的多样性是嵌入式系统的主要特点,如何使嵌入式操作系统在不同的硬件平台上有效地运行,是嵌入式系统开发中需要解决的关键问题。解决的方法是在硬件平台和操作系统之间提供硬件相关层来屏蔽这些硬件的差异,给操作系统提供统一的运行环境,这种硬件相关层就是嵌入式系统中的板级支持包BSP(Board Support Package,简称BSP)。 2. BSP及其作用 BSP是嵌
一.什么是装箱?什么是拆箱? 在前面的文章中提到,Java为每种基本数据类型都提供了对应的包装器类型,至于为什么会为每种基本数据类型提供包装器类型在此不进行阐述,有兴趣的朋友可以查阅相关资料。在Java SE5之前,如果要生成一个数值为10的Integer对象,必须这样进行:   1 Integer i = new   Integer( 10 ); 而在从Java SE5开始就提供了自动装箱的特性,如果要生成一个数值为10的Integer对象,只需要这样就可以了:   1 Integer i = 10 ;

Redis与Java - 数据结构 - 2016-07-24 14:07:41

Redis与Java 标签 : Java与NoSQL Redis( REmote DIctionary Server ) is an open source (BSD licensed), in-memory data structure store, used as database , cache and message broker . It supports data structures such as strings , hashes , lists , sets , sorted sets
0x00 实验背景 Server:选用腾讯云的云主机  Ubuntu Server 14.04.1 LTS 64位 Client-1:Acer笔记本 Win7 x64系统 Client-2:安卓机小米4  Android 6.0系统(MIUI8)   0x01  OpenVPN的背景知识 **** **** 以下内容摘自维基百科**** **** OpenVPN是一个用于创建虚拟专用网络加密通道的软件包,最早由James Yonan编写。OpenVPN允许创建的VPN使用公开密钥、电子证书、或者用户名/密

逐步深入TCP/IP协议栈 - 2016-07-24 14:07:36

一、关于应用层用户数据的历程,见下图:                                                                             TCP/IP数据包的封装 过程: 应用层将数据通过协议栈逐层向下传递,其下的每层接到来自上层的数据时,根据每层的协议都要在其数据 的前端添加首部信息进行封装。不同的协议层对数据包有不同 的称谓,在传输层叫做数据段,在网络层叫做数据报, 在链路层叫做数据帧。在经过链路层时,数据已经封装成帧并递交给物理层的传输介质上,到

Java事务--JTA原理 - 2016-07-23 19:07:54

        上一篇文章介绍了JDBC事务,JDBC可以处理单数据源的事务,满足大部分事务处理的需求,但是JDBC事务不能解决多数据源和分布式事务问题,Java平台给我们提供了解决方案--JTA。本文将探讨JTA的一些细节。          一 分布式事务          通常把一个数据库内部的事务处理,如对多个表的操作,作为本地事务看待。数据库和JDBC的事务处理对象是本地事务,而分布式事务处理的对象是全局事务。          所谓全局事务,是指分布式事务处理环境中,多个数据库可能需要共同完成
LINUX下SVN安装,配置,web目录同步 注: 各服务器运行环境可能有所不同,操作过程中可能出现其他问题,自行查阅资料解决 SVN的具体使用方法很多,本文档只是使用了SVN最简单的用法,感兴趣的同学可以查阅相关资料。 一、 安装subversion 首先输入rpm -qa | grep subversion 查看SVN是否已经安装过 如果输出类似如下结果,则说明已经安装:subversion-1.6.11-7.el6.x86_64 执行 yum -y install subversion 安装SVN