文章目录
一、注解大全
注解 | 使用对象 | XML等价形式 | 描述 |
---|---|---|---|
@CacheNamespace | 类 | <cache> | 为给定的命名空间(比如类)配置缓存 |
@CacheNamespaceRef | 类 | <cacheRef> | 引用另外一个命名空间的缓存以供使用 |
@Property | N/A | 指定参数值或占位符(placeholder)(该占位符能被 mybatis-config.xml 内的配置属性替换)。属性:name、value。(仅在 MyBatis 3.4.2 以上可用) | |
@ConstructorArgs | 方法 | <constructor> | 收集一组结果以传递给一个结果对象的构造方法 |
@Arg | N/A | <arg><idArg> | ConstructorArgs 集合的一部分,代表一个构造方法参数。属性:id、column、javaType、jdbcType、typeHandler、select、resultMap。id 属性和 XML 元素 相似,它是一个布尔值,表示该属性是否用于唯一标识和比较对象。从版本 3.5.4 开始,该注解变为可重复注解。 |
@Case | N/A | <case> | 表示某个值的一个取值以及该取值对应的映射。属性:value、type、results,results 属性是一个 Results 的数组,因此这个注解实际上和 ResultMap 很相似,由下面的 Results 注解指定。 |
@Results | 方法 | <resultMap> | 一组结果映射,指定了对某个特定结果列,映射到某个属性或字段的方式。 |
@Result | N/A | <result><id> | 在列和属性或字段之间的单个结果映射。属性:id、column、javaType、jdbcType、typeHandler、one、many。id 属性和 XML 元素 相似,它是一个布尔值,表示该属性是否用于唯一标识和比较对象。one 属性是一个关联,和 类似,而 many 属性则是集合关联,和 类似。这样命名是为了避免产生名称冲突。 |
@One | N/A | <association> | 复杂类型的单个属性映射。属性: select,指定可加载合适类型实例的映射语句(也就是映射器方法)全限定名; fetchType,指定在该映射中覆盖全局配置参数 lazyLoadingEnabled; resultMap(available since 3.5.5), which is the fully qualified name of a result map that map to a single container object from select result; columnPrefix(available since 3.5.5), which is column prefix for grouping select columns at nested result map. 提示 注解 API 不支持联合映射。这是由于 Java 注解不允许产生循环引用。 |
@Many | N/A | <collection> | 复杂类型的集合属性映射。属性: select,指定可加载合适类型实例集合的映射语句(也就是映射器方法)全限定名; fetchType,指定在该映射中覆盖全局配置参数 lazyLoadingEnabled resultMap(available since 3.5.5), which is the fully qualified name of a result map that map to collection object from select result; columnPrefix(available since 3.5.5), which is column prefix for grouping select columns at nested result map. 提示 注解 API 不支持联合映射。这是由于 Java 注解不允许产生循环引用。 |
@MapKey | 方法 | 供返回值为 Map 的方法使用的注解。它使用对象的某个属性作为 key,将对象 List 转化为 Map | |
@Options | 方法 | 映射语句的属性 | 该注解允许你指定大部分开关和配置选项,它们通常在映射语句上作为属性出现。与在注解上提供大量的属性相比,Options 注解提供了一致、清晰的方式来指定选项。属性:useCache=true、flushCache=FlushCachePolicy.DEFAULT、resultSetType=DEFAULT、statementType=PREPARED、fetchSize=-1、timeout=-1、useGeneratedKeys=false、keyProperty=""、keyColumn=""、resultSets="", databaseId=""。注意,Java 注解无法指定 null 值。因此,一旦你使用了 Options 注解,你的语句就会被上述属性的默认值所影响。要注意避免默认值带来的非预期行为。 The databaseId(Available since 3.5.5), in case there is a configured DatabaseIdProvider, the MyBatis use the Options with no databaseId attribute or with a databaseId that matches the current one. If found with and without the databaseId the latter will be discarded. |
@Insert,@Update,@Delete,@Select | 方法 | <insert>,<update>,<delete>,<select> | 每个注解分别代表将会被执行的 SQL 语句 |
@Param | 参数 | 如果你的映射方法接受多个参数,就可以使用这个注解自定义每个参数的名字。否则在默认情况下,除 RowBounds 以外的参数会以 “param” 加参数位置被命名。例如 #{param1}, #{param2}。如果使用了 @Param(“person”),参数就会被命名为 #{person}。 | |
@SelectKey | 方法 | <selectKey> | 这个注解的功能与 标签完全一致。该注解只能在 @Insert 或 @InsertProvider 或 @Update 或 @UpdateProvider 标注的方法上使用,否则将会被忽略。如果标注了 @SelectKey 注解,MyBatis 将会忽略掉由 @Options 注解所设置的生成主键或设置(configuration)属性。属性:statement 以字符串数组形式指定将会被执行的 SQL 语句,keyProperty 指定作为参数传入的对象对应属性的名称,该属性将会更新成新的值,before 可以指定为 true 或 false 以指明 SQL 语句应被在插入语句的之前还是之后执行。resultType 则指定 keyProperty 的 Java 类型。statementType 则用于选择语句类型,可以选择 STATEMENT、PREPARED 或 CALLABLE 之一, |
@ResultMap | 方法 | 这个注解为 @Select 或者 @SelectProvider 注解指定 XML 映射中 元素的 id。这使得注解的 select 可以复用已在 XML 中定义的 ResultMap。如果标注的 select 注解中存在 @Results 或者 @ConstructorArgs 注解,这两个注解将被此注解覆盖。 | |
@ResultType | 方法 | 在使用了结果处理器的情况下,需要使用此注解。由于此时的返回类型为 void,所以 Mybatis 需要有一种方法来判断每一行返回的对象类型。如果在 XML 有对应的结果映射,请使用 @ResultMap 注解。如果结果类型在 XML 的 元素中指定了,就不需要使用其它注解了。否则就需要使用此注解。比如,如果一个标注了 @Select 的方法想要使用结果处理器,那么它的返回类型必须是 void,并且必须使用这个注解(或者 @ResultMap)。这个注解仅在方法返回类型是 void 的情况下生效。 |
二、项目准备
项目目录结构
maven的pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.tadpole.learn</groupId>
<artifactId>mybatis</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.30</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
</project>
create.sql
CREATE SCHEMA `mybatis_learn` ;
CREATE TABLE `item_order` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`order_id` varchar(45) DEFAULT NULL,
`name` varchar(45) DEFAULT NULL,
`price` bigint(20) DEFAULT NULL,
`item_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `order_id` (`order_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COMMENT='订单表';
INSERT INTO `mybatis_learn`.`item_order` (`order_id`, `name`, `price`,`item_id`) VALUES ('1', '123', '苹果', '20', '1');
INSERT INTO `mybatis_learn`.`item_order` (`order_id`, `name`, `price`,`item_id`) VALUES ('2', '456', '葡萄', '30', '2');
CREATE TABLE `mybatis_learn`.`item` (
`id` INT NOT NULL AUTO_INCREMENT,
`item_name` VARCHAR(45) NULL,
PRIMARY KEY (`id`))
COMMENT = '商品';
INSERT INTO `mybatis_learn`.`item` (`id`, `item_name`) VALUES ('1', '苹果');
INSERT INTO `mybatis_learn`.`item` (`id`, `item_name`) VALUES ('2', '香蕉');
mybatis.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>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis_learn?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<package name="com.tadpole.itemorder"/>
</mappers>
</configuration>
三、注解示例
1、@CacheNamespace,@CacheNamespaceRef
@CacheNamespace注解主要用于mybatis二级缓存,等同于属性
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface CacheNamespace {
//缓存实现类,默认是PerpetualCache.class
Class<? extends org.apache.ibatis.cache.Cache> implementation() default PerpetualCache.class;
//缓存回收策略,默认LruCache.class(最近最少使用)
Class<? extends org.apache.ibatis.cache.Cache> eviction() default LruCache.class;
//刷新间隔。可被设置为任意的正整数,单位毫秒。默认不设置。
long flushInterval() default 0;
// 引用数目。可被设置为任意正整数,缓存的对象数目等于运行环境的可用内存资源数目。默认是1024。
int size() default 1024;
//只读,true或false。只读的缓存会给所有的调用者返回缓存对象的相同实例。默认是false。
boolean readWrite() default true;
//是否使用BlockingCache,BlockingCache 是阻塞版本的缓存装饰器,它保证只有一个线程到数据库中查找指定key对应的数据。
boolean blocking() default false;
}
直接在对应的mapper接口中加上以上注释就好了
import org.apache.ibatis.annotations.CacheNamespace;
import org.apache.ibatis.cache.decorators.LruCache;
import org.apache.ibatis.cache.impl.PerpetualCache;
@CacheNamespace(implementation = PerpetualCache.class, eviction = LruCache.class)
@CacheNamespaceRef(value = ItemOrderMapper.class)//引用另一个命名空间的缓存
public interface ItemOrderMapper {
}
2、@ConstructorArgs,@Arg,@Results,@Select,@Insert,@Update,@Delete,@Param,@SelectKey,@ResultMap,@ResultType,@MapKey,@One,@Case
在注解上不能直接使用动态的SQL,需要在其前后加入 <script>
有以下bean
package com.tadpole.itemorder;
public class Item {
private int id;
private String itemName;
public int getId() {return id;}
public void setId(int id) {this.id = id; }
public String getItemName() {return itemName;}
public void setItemName(String itemName) {this.itemName = itemName;}
}
package com.tadpole.itemorder;
import java.util.List;
public class ItemOrder {
private int id;
private String orderId;
private String name;
private long price;
private int itemId;
private Item item;
private List<Item> items;
public int getItemId() {return itemId; }
public void setItemId(int itemId) {this.itemId = itemId; }
public Item getItem() {return item;}
public void setItem(Item item) {this.item = item;}
public List<Item> getItems() {return items;}
public void setItems(List<Item> items) {this.items = items;}
public int getId() {return id;}
public void setId(int id) {this.id = id;}
public String getOrderId() {return orderId;}
public void setOrderId(String orderId) {this.orderId = orderId; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public long getPrice() { return price; }
public void setPrice(long price) {this.price = price;}
}
package com.tadpole.itemorder;
public class ItemOrder2 {
private int id;
private String orderId;
private String name;
public ItemOrder2(Integer id, String orderId, String name) {this.id = id;this.orderId = orderId;this.name = name;}
public int getId() { return id;}
public void setId(int id) {this.id = id;}
public String getOrderId() {return orderId; }
public void setOrderId(String orderId) {this.orderId = orderId;}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
}
package com.tadpole.itemorder;
public class ItemOrderParam {
private int otherId;
private String orderId;
private String name;
private int price;
private int itemId;
public ItemOrderParam() {}
public ItemOrderParam(int id, String orderId, String name, int price, int itemId) {
this.otherId = id;
this.orderId = orderId;
this.name = name;
this.price = price;
this.itemId = itemId;
}
public int getOtherId() {return otherId;}
public void setOtherId(int otherId) { this.otherId = otherId;}
public String getOrderId() {return orderId; }
public void setOrderId(String orderId) {this.orderId = orderId;}
public String getName() { return name;}
public void setName(String name) {this.name = name; }
public int getPrice() {return price;}
public void setPrice(int price) {this.price = price;}
public int getItemId() {return itemId;}
public void setItemId(int itemId) { this.itemId = itemId; }
}
ItemMapper
package com.tadpole.itemorder;
import org.apache.ibatis.annotations.*;
import java.util.List;
@Mapper
public interface ItemMapper {
@Select(" select * from item where id = #{id}")
@Results( id = "item",value = {
@Result(column = "id",property = "id"),
@Result(column = "item_name",property = "itemName")
})
Item selectById(@Param(value = "id") int id);
@Select(" select * from item where id >= #{id}")
@ResultMap("item")
List<Item> selectBiggerIdById(@Param(value = "id") int id);
}
package com.tadpole.itemorder;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.cache.impl.PerpetualCache;
import org.apache.ibatis.mapping.FetchType;
@CacheNamespace(implementation = PerpetualCache.class)
@CacheNamespaceRef(value = ItemOrderMapper.class)
@Mapper
public interface ItemOrderMapper {
//定义查询的sql语句@Select,如果需要写动态sql则加上标签<script></script>
@Select({"<script>"," select * from item_order " +
"<if test=\"id != null\">where id = #{id}</if>" +
"","</script>"})
//定义结果映射器,这里定义的id可以提供给其他地方使用
@Results( id = "itemOrder",value = {
@Result(column = "id",property = "id"),//@Result定义了字段映射
@Result(column = "name",property = "name"),
@Result(column = "order_id",property = "orderId"),
@Result(column = "price",property = "price"),
@Result(column = "item_id",property = "itemId"),
//@One定义该item属性的填充使用com.tadpole.itemorder.ItemMapper.selectById这个查询语句查询回填,并且是懒加载,当方法被调用时才去查询数据库
@Result(column = "item_id",property = "item", one = @One(select = "com.tadpole.itemorder.ItemMapper.selectById", fetchType = FetchType.LAZY)),
//@Many定义该items属性的填充使用com.tadpole.itemorder.ItemMapper.selectBiggerIdById查询回填,也是懒加载,当使用get方法时才会加载执行查询语句
@Result(column = "item_id",property = "items", many = @Many(select = "com.tadpole.itemorder.ItemMapper.selectBiggerIdById", fetchType = FetchType.LAZY))
})
ItemOrder selectById(@Param(value = "id")/**这里给变量名声明名称,可在sql语句中使用#{id}引用*/ int id);
@Results(id = "itemOrder2")//定义结果映射器itemOrder2,使用以下的ConstructorArgs构造器映射
//按照构造函数的顺序
@ConstructorArgs({
@Arg(column = "id",javaType = Integer.class, id = true),
@Arg(column = "order_id",javaType = String.class),
@Arg(column = "name",javaType = String.class),
})
@Select(" select id,order_id,name from item_order where id = #{id}")
ItemOrder2 selectItemOrder2ById(@Param(value = "id") int id);
@Select(" select * from item_order where id = #{id}")
@ResultMap("itemOrder")//直接使用上面定义的itemOrder,
ItemOrder selectById1(int id);
@Insert("INSERT INTO`item_order` (`order_id`, `name`, `price`,`item_id`) VALUES ( #{orderId}, #{name}, #{price}, #{itemId}) ")
//options 选项返回id字段,回填到otherId属性中,Options还有其他的用法:使用缓存,超时时间等
@Options(useGeneratedKeys = true, keyColumn = "id", keyProperty = "otherId")
//返回影响的行数
int insert(ItemOrderParam itemOrderParam);
@Insert("INSERT INTO`item_order` (`order_id`, `name`, `price`,`item_id`) VALUES ( #{orderId}, #{name}, #{price}, #{itemId}) ")
//返回影响的行数
//SelectKey效果跟上面options一致
@SelectKey(statement = "SELECT LAST_INSERT_ID()", keyColumn = "id",keyProperty = "otherId", before = false, resultType = int.class)
int insertReturnKeyId(ItemOrderParam itemOrderParam);
@Delete("delete from item_order where id = #{id}")
//返回影响的行数
int deleteById(@Param("id")int id);
@Delete("update item_order set price = price + 1 where id >= #{id}")
//返回影响的行数
int updateAddBiggerIdById(@Param("id")int id);
@Select(" select * from item_order where id = #{id}")
@MapKey(value = "id")//使用id字段做为map的key,value则是resultMap的类型
@ResultMap("itemOrder")//直接使用上面定义的itemOrder,
Map<Integer, ItemOrder> selectMapById(int id);
}
MyBatisStart
package com.tadpole;
import com.tadpole.itemorder.Item;
import com.tadpole.itemorder.ItemOrder;
import com.tadpole.itemorder.ItemOrderMapper;
import com.tadpole.itemorder.ItemOrderParam;
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 java.io.IOException;
import java.io.InputStream;
public class MyBatisStart {
public static void main(String[] args) throws IOException {
InputStream is = Resources.getResourceAsStream("mybatis.xml");
//1、初始化sqlSession链接工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//2、获取SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//3、获取对应的Mapper执行sql
ItemOrderMapper abcMapper = sqlSession.getMapper(ItemOrderMapper.class);
ItemOrder itemOrder = abcMapper.selectById1(1);
System.out.println("id为1的商品订单:名字:" + itemOrder.getName() + ",支付金额:" + itemOrder.getPrice() + ",itemOrder,getOrderId" + itemOrder.getOrderId() + "itemOrder.itemid=" + itemOrder.getItemId());
System.out.println(itemOrder.getItem().getItemName());
System.out.println("id为1的商品订单关联商品id比该订单大的商品名");
for (Item item : itemOrder.getItems()) {
System.out.println(item.getItemName());
}
System.out.println("构造函数映射结果:abcMapper.selectItemOrder2ById(1).getName" + abcMapper.selectItemOrder2ById(1).getName());
System.out.println("删除abcMapper返回影响条数=" + abcMapper.deleteById(3));
ItemOrderParam itemOrderParam = new ItemOrderParam(3, "9999", "你好", 132, 465);
System.out.println("插入abcMapper,并且回填id字段。影响数量" + abcMapper.insert(itemOrderParam) + ",itemOrderParam.id=" + itemOrderParam.getOtherId());
ItemOrderParam insertReturnKeyIdParam = new ItemOrderParam(3, "789456", "你好", 132, 465);
int id = abcMapper.insertReturnKeyId(insertReturnKeyIdParam);
System.out.println("插入abcMapper。并且回填id字段,insertReturnKey影响数量" + id +",insertReturnKeyIdParam.id=" + insertReturnKeyIdParam.getOtherId());
System.out.println("删除abcMapper。delete影响数量=" + abcMapper.deleteById(itemOrderParam.getOtherId()));
System.out.println("删除abcMapper。delete影响数量=" + abcMapper.deleteById(insertReturnKeyIdParam.getOtherId()));
System.out.println("删除abcMapper。update影响数量=" + abcMapper.updateAddBiggerIdById(1));
Map<Integer, ItemOrder> integerItemOrderMap = abcMapper.selectMapById(1);
for (Map.Entry<Integer, ItemOrder> integerItemOrderEntry : integerItemOrderMap.entrySet()) {
System.out.println("查询。selectMapById,key=" + integerItemOrderEntry.getKey() + ",value=" + integerItemOrderEntry.getValue().getName());
}
}
}