Mybatis常用操作 专题-阿里云开发者社区

开发者社区> 数据库> 正文
登录阅读全文

Mybatis常用操作 专题

简介: parameterType:即将传入的语句参数的完全限定类名和别名。这个属性是可选项的,因为MyBatis可以推断出传入语句的具体参数,因此不建议配置该属性flushCache:默认值为true,任何时候只要语句被调用,都会清空一级缓存和二级缓存useGeneratedKeys默认值为false。

parameterType:即将传入的语句参数的完全限定类名和别名。这个属性是可选项的,因为MyBatis可以推断出传入语句的具体参数,因此不建议配置该属性
flushCache:默认值为true,任何时候只要语句被调用,都会清空一级缓存和二级缓存
useGeneratedKeys默认值为false。如果设置为true,MyBatis会使用JDBC的getGeneratedKeys方法来取出由数据库内部生成的主键
keyProperty:MyBatis通过getGeneratedKeys获取主键值后将要赋值的属性名。如果希望得到多个数据库自动生成的列,属性值也可以是以逗号分隔的属性名称列表

此处<insert>中的SQL就是一个简单的INSERT语句,将所有的列都列举出来,在values中通过#{property}方式从参数中取出属性的值。

为了防止类型错误,对于一些特殊的数据类型,建议指定具体的jdbcType值。例如,icon字段指定BLOB类型,createTime指定TIMESTAMP类型

tips:
BLOB对应的类型是ByteArrayInputStream,就是二进制数据流
由于数据库区分date,time,dataTime类型,但是Java中一般都使用java.util.Date类型。因此为了保证数据类型的正确,需要手动指定日期类型,date,time,datetime对应的JDBC类型的DATE,TIME,TIMESTAMP

<insert 
id="insertSysUser"  
parameterType="user" 
useGeneratedKeys="true"  
keyProperty="id" >
  insert into sys_user
 (
user_name,
user_password,
user_email,
icon,
create_time
)
values (
#{userName},
#{userPassword},
#{userEmail},
#{icon,jdbcType=BLOB},
#{createTime,jdbcType=TIMESTAMP}
)

</insert>

 

 

<insert  id="insertSysUser"  >
  insert into sys_user
 (
user_name,
user_password,
user_email,
icon,
create_time
)
values (
#{userName},
#{userPassword},
#{userEmail},
#{icon,jdbcType=BLOB},
#{createTime,jdbcType=TIMESTAMP}
)

<selectKey keyColumn="id" resultType="long" keyProperty="id" order="AFTER" >
    select LAST_INSERT_ID()
</selectKey>

</insert>

selectKey标签的keyColumn、keyProperty和上面useGeneratedKeys的用法含义相同,这里的resultType用于设置返回值类型。order属性的设置和使用的数据库有关。

在MySQL数据库中,order属性设置的值是AFTER,因为当前记录的主键值在insert语句执行成功后才能获取到。
而Oracle数据库中,order的值要设置为BEFORE,这是因为Oracle中需要先从序列获取值,然后将值作为主键插入到数据库中

 

 

http://www.mybatis.org/mybatis-3/zh/configuration.html

 

What is the difference between #{...} and ${...}?

MyBatis interprets #{...} as a parameter marker in a JDBC prepared statement. MyBatis interprets ${...} as string substitution. It is important to know the difference because parameter markers cannot be used in certain places in SQL statements.
For example, you cannot use a parameter marker to specify a table name.
Given the following code:

Map<String, Object> parms = new HashMap<String, Object>();
parms.put("table", "foo");
parms.put("criteria", 37);
List<Object> rows = mapper.generalSelect(parms);
<select id="generalSelect" parameterType="map">
  select * from ${table} where col1 = #{criteria}
</select>

MyBatis will generate the following prepared statement:

select * from foo where col1 = ?

Important: note that use of ${...} (string substitution) presents a risk for SQL injection attacks. Also, string substitution can be problematical for complex types like dates. For these reasons, we recommend using the #{...} form whenever possible.

How do I code an SQL LIKE?

There are two methods. In the first (and preferred) method, you append the SQL wildcards in your Java code.
For example:

String wildcardName = "%Smi%";
List<Name> names = mapper.selectLike(wildcardName);
<select id="selectLike">
  select * from foo where bar like #{value}
</select>

Another method is to concatenate the wildcards in your SQL. This method is less safe than the method above because of possible SQL injection.
For example:

String wildcardName = "Smi";
List<Name> names = mapper.selectLike(wildcardName);
<select id="selectLike">
  select * from foo where bar like '%' || '${value}' || '%'
</select>

Important: Note the use of $ vs. # in the second example!

How do I code a batch insert?

First, code a simple insert statement like this:

<insert id="insertName">
  insert into names (name) values (#{value})
</insert>

Then execute a batch in Java code like this:

List<String> names = new ArrayList<String>();
names.add("Fred");
names.add("Barney");
names.add("Betty");
names.add("Wilma");

SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
try {
  NameMapper mapper = sqlSession.getMapper(NameMapper.class);
  for (String name : names) {
    mapper.insertName(name);
  }
  sqlSession.commit();
} finally {
  sqlSession.close();
}

How can I retrieve the value of an auto generated key? 

The insert method always returns an int - which is the number of rows inserted. Auto generated key values are placed into the parameter object and are available after the completion of the insert method.
For example:

<insert id="insertName" useGeneratedKeys="true" keyProperty="id">
  insert into names (name) values (#{name})
</insert>
Name name = new Name();
name.setName("Fred");
          
int rows = mapper.insertName(name);
System.out.println("rows inserted = " + rows);
System.out.println("generated key value = " + name.getId());

https://github.com/mybatis/mybatis-3/wiki/FAQ#how-do-i-code-a-batch-insert



userDao-mapping.xml相当于是UserDao的实现, 同时也将User实体类与数据表User成功关联起来。

再编写一个userDao-mapping.xml (可随便命名):

userDao-mapping.xml:

<?xml version="1.0" encoding="UTF-8" ?>   
<!DOCTYPE mapper   
PUBLIC "-//ibatis.apache.org//DTD Mapper 3.0//EN"  
"http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd"> 
<mapper namespace="com.dy.dao.UserDao">

   <select id="findUserById" resultType="com.dy.entity.User" > 
      select * from user where id = #{id}
   </select>

</mapper>

 

package com.dy.entity;

public class User {

    private int id;
    private String name;
    private String password;
    private int age;
    private int deleteFlag;
    
    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 String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public int getDeleteFlag() {
        return deleteFlag;
    }
    public void setDeleteFlag(int deleteFlag) {
        this.deleteFlag = deleteFlag;
    }
    
}

再编写一个UserDao 接口:

UserDao:

package com.dy.dao;

import java.util.List;

import com.dy.entity.User;

public interface UserDao {

    public void insert(User user);
    
    public User findUserById (int userId);
    
    public List<User> findAllUsers();
    
}

http://www.cnblogs.com/dongying/p/4031382.html

注意:#与$区别:
1.#是把传入的数据当作字符串,如#field#传入的是id,则sql语句生成是这样,order by "id",这当然会报错..
2.$传入的数据直接生成在sql里,如#field#传入的是id,则sql语句生成是这样,order by id, 这就对了. 
 $方式一般用于传入数据库对象.例如传入表名.
#方式一般用于传入插入/更新的值或查询/删除的where条件

http://aqxiebin.iteye.com/blog/1415578


<select>是iBatis已经映射的语句类型,就是查询了,为了配合说明,这里再介绍两个标记:<sql>和<include>,前者用来创建一个文本片段,这些片段可以组合起来创建完整的SQL语句;后者很显然就是包含的意思了。假设我们有如下代码段: 

<sql id="select-user">  
    select * from users  
</sql>  
<sql id="select-count">  
    select count(*) as value from users  
</sql>  
<sql id="where-age-over-value">  
    <![CDATA[ 
        where age > #value:INT# 
    ]]>  
</sql>  
<select id="getUserAgeOver" resultClass="hashmap">  
    <include refid="select-user" />  
    <include refid="where-age-over-value" />  
</select>  
<select id="getUserCountAgeOver" resultClass="int">  
    <include refid="select-count" />  
    <include refid="where-age-over-value" />  
</select>  

 

该部分代码展示了sql和include的使用,其中使用了CDATA段,这是因为XML标签本体中出现了于XML标签冲突的字符,这很好理解。后面两个查询就是我们执行的语句部分,程序代码可以这么来写: 

List users = sqlMap.queryForList("User.getUserAgeOver","23");  
System.out.println(users);  
int userCount = (Integer) sqlMap.queryForObject(  
    "User.getUserCountAgeOver", "22");  
System.out.println(userCount);  

 

如果可以查询到记录,那么就会打印出来了。上面的例子中我们是用了#来标识传递的参数#被成为占位符,这是内联参数的传递方式的一种。 

<select id="getUserById" resultClass="User">  
    select  
        userId,  
        userName,  
        password,  
        age,  
        mobile,  
        mail  
    from  
        users  
    where  
        userId = #value#  
</select>  

 在程序中,用下面这些代码就能达到查询效果了。

User user = (User) sqlMap.queryForObject("User.getUserById", new Integer(1));  
System.out.println(user);  

#value#是告诉iBatis传递一个简单的参数,iBatis处理该语句时,将会把#value#转换为预处理参数形式,然后将这个参数的值设置为1(就是queryForObject()方法的第二个参数),之后执行该预处理语句。最后iBatis接受返回的结果,然后把它映射到一个Java对象并返回该对象,这就是sqlMap的执行过程。 

下面来看另外一种内联参数形式,就是使用$作为占位符。它可以直接把参数插入到SQL语句中,这在该SQL语句被转变为参数化语句之前就执行了。如此就会留下安全隐患,它可能给SQL注入有机可乘,而且过度使用还会有性能问题,看下面这个语句: 

<select id="getUserByLikeEmail" resultClass="User">  
    select  
        userId,  
        userName,  
        password,  
        age,  
        mobile,  
        email  
    from  
        users  
    where  
        email like '%$value$%'  
</select>  

在程序中,我们可以使用如下代码来执行模糊查询: 

List<User> users = sqlMap.queryForList("User.getUserByLikeEmail", "gmail"); 
System.out.println(users); 
    若要使用#方式来当占位符,那么模糊查询时可能不是那么方便,需要如下进行:email like concat('%',#value#,'%'),这是MySQL的情况。所以模糊查询使用$比较方便。 
    以上的查询中我们使用了resultClass这种自动结果映射,这是iBatis的一种执行机制,而我们也可以进行自定义结果映射,就是使用resultMap。如果我们在查询中两者都没有使用的话,那么iBatis执行查询但是不能返回任何东西。 
    当我们使用bean作为结果映射时要注意如果结果列存在于数据库而不存在于bean中,那么我们不会得到任何数据,而且执行不会报错。自动映射使用起来很方便,但是更稳健的要数外部结果映射了

http://sarin.iteye.com/blog/731655

//外部调用此方法对mybatis配置文件进行解析
   public Configuration parse() {
     if (parsed) {
       throw new BuilderException("Each XMLConfigBuilder can only be used once.");
     }
     parsed = true;
     //从根节点configuration
     parseConfiguration(parser.evalNode("/configuration"));
     return configuration;
   }
 
   //此方法就是解析configuration节点下的子节点
   //由此也可看出,我们在configuration下面能配置的节点为以下10个节点
   private void parseConfiguration(XNode root) {
     try {
       propertiesElement(root.evalNode("properties")); //issue #117 read properties first
       typeAliasesElement(root.evalNode("typeAliases"));
       pluginElement(root.evalNode("plugins"));
       objectFactoryElement(root.evalNode("objectFactory"));
       objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
       settingsElement(root.evalNode("settings"));
       environmentsElement(root.evalNode("environments")); // read it after objectFactory and objectWrapperFactory issue #631
       databaseIdProviderElement(root.evalNode("databaseIdProvider"));
       typeHandlerElement(root.evalNode("typeHandlers"));
       mapperElement(root.evalNode("mappers"));
     } catch (Exception e) {
       throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
     }
   }
 }

通过以上源码,我们就能看出,在mybatis的配置文件中:

1. configuration节点为根节点。
2. 在configuration节点之下,我们可以配置10个子节点, 分别为:
properties、
typeAliases、
plugins、
objectFactory、
objectWrapperFactory、
settings、
environments、
databaseIdProvider、
typeHandlers、
mappers

http://www.cnblogs.com/dongying/p/4031613.html

 

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
数据库
使用钉钉扫一扫加入圈子
+ 订阅

分享数据库前沿,解构实战干货,推动数据库技术变革

其他文章