DROP TABLE IF EXISTS `goods`;
CREATE TABLE `goods` (
`good_id` int(11) NOT NULL AUTO_INCREMENT,
`good_name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`good_id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
-- ----------------------------
-- Records of goods
-- ----------------------------
BEGIN;
INSERT INTO `goods` VALUES (1, '上衣');
INSERT INTO `goods` VALUES (2, '裤子');
INSERT INTO `goods` VALUES (3, '鞋子');
COMMIT;
-- ----------------------------
-- Table structure for shoopingcart
-- ----------------------------
DROP TABLE IF EXISTS `shoopingcart`;
CREATE TABLE `shoopingcart` (
`cart_id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) DEFAULT NULL,
`good_id` int(11) DEFAULT NULL,
PRIMARY KEY (`cart_id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
-- ----------------------------
-- Records of shoopingcart
-- ----------------------------
BEGIN;
INSERT INTO `shoopingcart` VALUES (1, 1, 1);
INSERT INTO `shoopingcart` VALUES (2, 1, 2);
INSERT INTO `shoopingcart` VALUES (3, 2, 1);
INSERT INTO `shoopingcart` VALUES (4, 3, 2);
INSERT INTO `shoopingcart` VALUES (5, 3, 3);
COMMIT;
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(30) DEFAULT NULL,
`pwd` varchar(30) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
-- ----------------------------
-- Records of user
-- ----------------------------
BEGIN;
INSERT INTO `user` VALUES (1, 'user1', 'pwd1');
INSERT INTO `user` VALUES (2, 'user2', 'pwd2');
INSERT INTO `user` VALUES (3, 'user3', 'pwd3');
COMMIT;
DROP TABLE IF EXISTS `wallet`;
CREATE TABLE `wallet` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) DEFAULT NULL,
`balance` decimal(10,2) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
-- ----------------------------
-- Records of wallet
-- ----------------------------
BEGIN;
INSERT INTO `wallet` VALUES (1, 1, 100.00);
INSERT INTO `wallet` VALUES (2, 2, 200.00);
INSERT INTO `wallet` VALUES (2, 3, 300.00);
COMMIT;
package com.szm.pojo;
@Data
public class Good {
private int goodId;
private String goodName;
}
package com.szm.pojo;
import lombok.Data;
@Data
public class ShoppingCart {
private int cartId;
private int userId;
private int goodId;
}
package com.szm.pojo;
import lombok.Data;
@Data
public class User {
private int userId;
private String userName;
private String userPwd;
}
package com.szm.pojo;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class Wallet {
private int id;
private BigDecimal balance;
}
package com.szm.mapper;
import com.szm.pojo.User;
import java.util.List;
public interface UserMapper {
List<User> selectUserByName(String name);
}
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.szm.mapper.UserMapper">
<select id="selectUserByName" resultType="user">
select id as userId,name as userName,pwd as userPwd from user where name =#{name};
select>
mapper>
属性 | 描述 |
---|---|
id |
在命名空间中唯一的标识符,可以被用来引用这条语句。 |
parameterType |
将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)。 |
parameterMap(废弃) |
用于引用外部 parameterMap 的属性,目前已被废弃。请使用行内参数映射和 parameterType 属性。 |
resultType |
期望从这条语句中返回结果的类全限定名或别名。 注意,如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身的类型。 resultType 和 resultMap 之间只能同时使用一个。 |
resultMap |
对外部 resultMap 的命名引用。结果映射是 MyBatis 最强大的特性,如果你对其理解透彻,许多复杂的映射问题都能迎刃而解。 resultType 和 resultMap 之间只能同时使用一个。 |
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 或 DEFAULT(等价于 unset) 中的一个,默认值为 unset (依赖数据库驱动)。 |
databaseId |
如果配置了数据库厂商标识(databaseIdProvider),MyBatis 会加载所有不带 databaseId 或匹配当前 databaseId 的语句;如果带和不带的语句都有,则不带的会被忽略。 |
resultOrdered |
这个设置仅针对嵌套结果 select 语句:如果为 true,将会假设包含了嵌套结果集或是分组,当返回一个主结果行时,就不会产生对前面结果集的引用。 这就使得在获取嵌套结果集的时候不至于内存不够用。默认值:false 。 |
parameterType用来声明这条语句所需要的入参,一般不需要在xml进行显式的定义,mybatis会自动进行处理,下面列举参数类型的几种情况
package com.szm.mapper;
import com.szm.pojo.User;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface UserMapper {
//传入两个参数
List<User> selectUser( String userName, String pwd);
}
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.szm.mapper.UserMapper">
<select id="selectUser" resultType="user" >
select id as userId,name as userName,pwd as userPwd from user where name =#{arg0} and pwd = #{arg1};
select>
mapper>
package com.szm.mapper;
import com.szm.pojo.User;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface UserMapper {
List<User> selectUser(@Param("name") String userName,@Param("p") String pwd);
}
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.szm.mapper.UserMapper">
<select id="selectUserByName" resultType="user" >
select id as userId,name as userName,pwd as userPwd from user where name =#{name} and pwd = #{p};
select>
mapper>
package com.szm.mapper;
import com.szm.pojo.User;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface UserMapper {
List<User> selectUserByName(@Param("queryUser")User user);
}
映射文件使用**#{名称.参数名称}**的方式进行占位
<?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.szm.mapper.UserMapper">
<select id="selectUserByName" resultType="user" >
select id as userId,name as userName,pwd as userPwd from user where name =#{queryUser.name} and pwd = #{queryUser.pwd};
</select>
</mapper>
期望从这条语句中返回结果的类全限定名或别名。 注意,如果返回的是集合,那应该设置为集合包含的类型,而不是集合本身的类型。 resultType 和 resultMap 之间只能同时使用一个
在使用select标签做查询时,使用resultType定义返回类型,如果查询返回的是mybatis内置的类型的话,直接使用java内置的类型别名或使用类型全限定路径(内置类型详见我的博客《mybatis(二)xml配置方式详细说明》)。
如果返回结果为javaBean对象,mybatis根据查询结果的列名和javaBean属性名称进行对应,所以javaBean对象的属性名称要和sql结果列名完全一致
需要注意的是如果返回的是集合对象,resultType只需定义集合的泛型类型就行了,
下面写几个例子来说明:
package com.szm.mapper;
import java.util.List;
import java.util.Map;
public interface UserMapper {
// 返回map类型
List<Map<String,Object>> selectUser(String userName,String pwd);
}
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.szm.mapper.UserMapper">
<select id="selectUser" resultType="map" >
select id as userId,name as userName,pwd as userPwd from user where name =#{arg0} and pwd = #{arg1};
select>
mapper>
如果返回的是mybatis非内置类型而是我们自定义的javaBean呢?
如果是普通的javabean对象,其中都是基础类型的话,在resultType中定义我们的自定义javaBean的类全限定路径或者定义一个typeAliases使用别名(别名配置详见《mybatis(二)xml配置方式详细说明》)这里就不在赘述了,那如果自定义javaBean对象又引用了另外一个javaBean或者定义了一个结构更复杂的属性呢,mybatis非自动处理吗?
我们定义一个dto对象,对象中包含user的两个字段和一个集合对象cartGoods(购物车里所有的货物集合):
package com.szm.dto;
import com.szm.pojo.Good;
import lombok.Data;
import java.util.List;
@Data
public class UserInfo {
private int userId;
private String userName;
List<Good> cartGoods;
}
package com.szm.mapper;
import com.szm.dto.UserInfo;
import java.util.List;
import java.util.Map;
public interface UserMapper {
UserInfo selectUserInfo(int userId);
}
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.szm.mapper.UserMapper">
<select id="selectUserInfo" resultType="com.szm.dto.UserInfo">
select
a.id as userId,
a.name as userName,
c.good_id as goodId,
c.good_name as goodName
from (select * from user where id = #{arg0}) a
left join shoopingcart b on a.id = b.user_id
left join goods c on b.good_id = c.good_id;
select>
mapper>
我们期待mybatis能够自动帮我们把结果映射,结果可见:mybatis并没有那么智能,运行结果:
org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 2
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:80)
at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:87)
at org.apache.ibatis.binding.MapperProxy$PlainMethodInvoker.invoke(MapperProxy.java:152)
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:85)
at com.sun.proxy.$Proxy6.selectUserInfo(Unknown Source)
at Test1.test2(Test1.java:48)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)
Process finished with exit code 255
MyBatis 会在幕后自动创建一个
ResultMap
,再根据属性名来映射列到 JavaBean 的属性上
所以,resultType其实在本质是是一个resultMap,那对于复杂的情况,我们移步看resultMap吧!
标签很多丰富好用的功能标签供我们使用
标签列表:
标签名称 | 用途 |
---|---|
constructor | 用于在实例化类时,注入结果到构造方法中 |
id | 一个 ID 结果;标记出作为 ID 的结果可以帮助提高整体性能 |
result | 注入到字段或 JavaBean 属性的普通结果 |
association | 一个复杂类型的关联;许多结果将包装成这种类型, 嵌套结果映射 – 关联可以是 resultMap 元素,或是对其它结果映射的引用 |
collection | 一个复杂类型的集合 |
discriminator | 使用结果值来决定使用哪个 resultMap |
resultMap定义可以理解为就是在定义一个对象来接收sql的一条查询结果,那这个对象在进行初始化和属性注入的时候mybatis约定了一些标签方便我们做一些处理
constructor允许我们定义在初始化返回对象的时候,将当前结果集中当前记录的某些字段注入到到我们的构造方法中,也就是说如果我们定义了这个标签,mybatis就会在初始化对象时调用我们的有参构造方法
discriminator ,定义了这个这个标签的话,mybatis在注入结果集时,会根据配置对当前记录行的某些字段进行判断来决定当前行使用那个resultMap
下面简单运用一下这两个标签:
新建一个UserInfo对象,新增一个有参构造,在构造方法中对extend属性进行赋值:
package com.szm.pojo;
import lombok.Data;
import java.util.UUID;
@Data
public class User {
public User(){
}
public User(String extend){
this.extend = extend+ UUID.randomUUID();
}
private int userId;
private String userName;
private String userPwd;
private String extend;
}
dao层接口
package com.szm.mapper;
import com.szm.dto.UserCart;
import com.szm.dto.UserInfo;
import com.szm.pojo.User;
import java.util.List;
public interface UserMapper {
List<User> select();
}
xml
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.szm.mapper.UserMapper">
<resultMap id="baseUserMap2" type="user">
<id property="userId" column="id"/>
<result property="userName" column="pwd"/>
<result property="userPwd" column="name"/>
resultMap>
<resultMap id="baseUserMap" type="user">
<constructor>
<idArg column="name" javaType="string"/>
constructor>
<id property="userId" column="id"/>
<result property="userName" column="name"/>
<result property="userPwd" column="pwd"/>
<discriminator javaType="int" column="id">
<case value="1" resultMap="baseUserMap2">case>
discriminator>
resultMap>
<select id="select" resultMap="baseUserMap">
select * from user;
select>
mapper>
User(userId=1, userName=pwd1, userPwd=user1, extend=null)
User(userId=2, userName=user2, userPwd=pwd2, extend=user2f1ae73cd-5ced-4778-8f97-ada7c690cdaf)
User(userId=3, userName=user3, userPwd=pwd3, extend=user3e012f90f-75aa-4294-9727-cf8abae884c3)
package com.szm.dto;
import com.szm.pojo.Wallet;
import lombok.Data;
@Data
public class UserInfo {
private int userId;
private String userName;
private String userPwd;
private Wallet wallet;
}
package com.szm.mapper;
import com.szm.dto.UserInfo;
import com.szm.pojo.User;
import java.util.List;
import java.util.Map;
public interface UserMapper {
List<UserInfo> selectUser();
}
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.szm.mapper.UserMapper">
<resultMap id="userMap" type="userInfo">
<id property="userId" column="id"/>
<result property="userName" column="name"/>
<result property="userPwd" column="pwd"/>
<association property="wallet" >
<result property="balance" column="balance">result>
association>
resultMap>
<select id="selectUser" resultMap="userMap">
select a.id,a.name,a.pwd,b.balance from user a
left join wallet b on a.id = b.user_id
select>
mapper>
UserInfo(userId=1, userName=user1, userPwd=pwd1, wallet=Wallet(id=0, balance=100.00))
UserInfo(userId=2, userName=user2, userPwd=pwd2, wallet=Wallet(id=0, balance=200.00))
UserInfo(userId=3, userName=user3, userPwd=pwd3, wallet=Wallet(id=0, balance=300.00))
Process finished with exit code 0
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.szm.mapper.UserMapper">
<resultMap id="wallet" type="com.szm.pojo.Wallet">
<result property="balance" column="balance">result>
resultMap>
<resultMap id="userMap" type="userInfo">
<id property="userId" column="id"/>
<result property="userName" column="name"/>
<result property="userPwd" column="pwd"/>
<association property="wallet" resultMap="wallet" />
resultMap>
<select id="selectUser" resultMap="userMap">
select a.id,a.name,a.pwd,b.balance from user a
left join wallet b on a.id = b.user_id
select>
mapper>
package com.szm.dto;
import com.szm.pojo.Good;
import java.util.List;
public class UserCart {
private int userId;
private String userName;
private List<Good> goods;
}
package com.szm.mapper;
import com.szm.dto.UserCart;
import com.szm.dto.UserInfo;
import java.util.List;
public interface UserMapper {
List<UserCart> selectUserCart();
}
此时配合result的collection就可以轻松解决:
<?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.szm.mapper.UserMapper">
<!-- 一对多-->
<resultMap id="cartGood" type="com.szm.pojo.Good">
<result property="goodName" column="good_name"/>
</resultMap>
<resultMap id="userCartMap" type="com.szm.dto.UserCart">
<id property="userId" column="id"></id>
<result property="userName" column="name"></result>
<collection property="goods" resultMap="cartGood"/>
</resultMap>
<select id="selectUserCart" resultMap="userCartMap">
select
a.id ,
a.name ,
c.good_id ,
c.good_name
from user a
left join shoopingcart b on a.id = b.user_id
left join goods c on b.good_id = c.good_id;
</select>
</mapper>
UserCart(userId=1, userName=user1, goods=[Good(goodId=0, goodName=上衣), Good(goodId=0, goodName=裤子)])
UserCart(userId=2, userName=user2, goods=[Good(goodId=0, goodName=上衣)])
UserCart(userId=3, userName=user3, goods=[Good(goodId=0, goodName=裤子), Good(goodId=0, goodName=鞋子)])
Process finished with exit code 0
<resultMap id="publicUserMap" type="user">
<id property="userId" column="id"/>
<result property="userName" column="name"/>
<result property="userPwd" column="pwd"/>
resultMap>
<resultMap id="baseUserMap" type="user" extends="publicUserMap">
<constructor>
<idArg column="name" javaType="string"/>
constructor>
<discriminator javaType="int" column="id">
<case value="1" resultMap="baseUserMap2">case>
discriminator>
resultMap>
sql标签可以定义一些可重用的 SQL 代码片段,以便在其它语句中使用,参数也可以在运行中确定下来,基于这个特性可以结合select做一些更灵活的配置
具体如下:
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.szm.mapper.UserMapper">
<sql id="userSql" >${userTable}.id,${userTable}.name,${userTable}.pwdsql>
<resultMap id="wallet" type="com.szm.pojo.Wallet">
<result property="balance" column="balance">result>
resultMap>
<resultMap id="userMap" type="userInfo">
<id property="userId" column="id"/>
<result property="userName" column="name"/>
<result property="userPwd" column="pwd"/>
<association property="wallet" resultMap="wallet" />
resultMap>
<select id="selectUser" resultMap="userMap">
select
<include refid="userSql"><property name="userTable" value="a"/>include>,
b.balance
from user a
left join wallet b on a.id = b.user_id
select>
<resultMap id="cartGood" type="com.szm.pojo.Good">
<id property="goodId" column="good_id" />
<result property="goodName" column="good_name"/>
resultMap>
<resultMap id="userCartMap" type="com.szm.dto.UserCart">
<id property="userId" column="id">id>
<result property="userName" column="name">result>
<result property="goodId" column="good_id">result>
<result property="goodName" column="good_name">result>
resultMap>
<select id="selectUserCart" resultType="com.szm.dto.UserInfo">
select
a.id ,
a.name ,
c.good_id ,
c.good_name
from (select * from user where id = #{arg0}) a
left join shoopingcart b on a.id = b.user_id
left join goods c on b.good_id = c.good_id;
select>
mapper>
数据变更语句 insert,update 和 delete 的实现非常接近:
属性 | 描述 |
---|---|
id |
在命名空间中唯一的标识符,可以被用来引用这条语句。 |
parameterType |
将会传入这条语句的参数的类全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过类型处理器(TypeHandler)推断出具体传入语句的参数,默认值为未设置(unset)。 |
parameterMap (废弃) |
用于引用外部 parameterMap 的属性,目前已被废弃。请使用行内参数映射和 parameterType 属性。 |
flushCache |
将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:(对 insert、update 和 delete 语句)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 的语句;如果带和不带的语句都有,则不带的会被忽略。 |
例子:
<insert id="insertUser">
insert into user(id,name,pwd)
values(#{id},#{name},#{pwd});
insert>
<update id="updateUser">
update user set name= #{name} where id = #{id}
update>
<delete id="deleteUser">
delete from user where id = #{id}
delete>
如果你的数据库支持自动生成主键的字段(比如 MySQL 和 SQL Server,那么你可以设置 useGeneratedKeys=”true”,然后再把 keyProperty 设置为目标属性就 OK 了,这样可以省略插入主键id,这里其实如果你设置了主键自动增长,是不用设置这两个属性也可以插入成功的,但是如果你要获得返回的主键id的话就必须要设置,keyProperty为传入的javaBean的属性名称,注意这里的返回其实是传入的对象本身,mybatis在底层对传入的对象做了一个setId的操作再返回了
<insert id="insertUser" useGeneratedKeys="true" keyProperty="userId">
insert into user(name,pwd)
values(#{user.name},#{user.pwd});
insert>
如果你的数据库还支持多行插入, 你也可以传入一个数组或集合,并返回自动生成的主键,注意这里的返回其实是传入的对象本身,mybatis在底层对传入的对象做了一个setId的操作再返回了
User新增一个构造方法
package com.szm.pojo;
import lombok.Data;
import java.util.UUID;
@Data
public class User {
public User() {
}
public User(String extend) {
this.extend = extend + UUID.randomUUID();
}
public User(String name, String pwd) {
this.userName = name;
this.userPwd = pwd;
}
private int userId;
private String userName;
private String userPwd;
private String extend;
}
dao:
package com.szm.mapper;
import com.szm.pojo.User;
import java.util.List;
public interface UserMapper {
// 注意这里返回的其实是传入的对象本身,mybatis在底层对传入的对象做了一个setId的操作再返回了
void batchInsertUser(@Param("users") List<User> users);
}
<insert id="batchInsertUser" useGeneratedKeys="true" keyProperty="userId" >
insert into user (name, pwd) values
<foreach item="user" collection="users" separator=",">
(#{user.userName}, #{user.userPwd})
foreach>
insert>
测试类
@Test
public void test4() throws IOException {
String resource = "mybatis.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> users = new ArrayList<>();
users.add(new User("user4","pwd4"));
users.add(new User("user4","pwd5"));
mapper.batchInsertUser(users);
users.stream().forEach((e)->{
System.out.println(e);
});
sqlSession.close();
}
运行结果:
User(userId=8, userName=user4, userPwd=pwd4, extend=null)
User(userId=9, userName=user4, userPwd=pwd5, extend=null)
在mybatis官方文档中,这个用来作为在数据库不支持自动生成主键的一种替代方案,本质上就是定义一段查询结果为一行一列的查询sql,mybatis将会根据你定义order在查询前/后执行这段sql,将查询结果注入到你传入的对象对应的属性中。
官方示例:
<insert id="insertAuthor">
<selectKey keyProperty="id" resultType="int" order="BEFORE">
select CAST(RANDOM()*1000000 as INTEGER) a from SYSIBM.SYSDUMMY1
selectKey>
insert into Author
(id, username, password, email,bio, favourite_section)
values
(#{id}, #{username}, #{password}, #{email}, #{bio}, #{favouriteSection,jdbcType=VARCHAR})
insert>