mybatis 的一些用法
public class User {
private int id;
private String username;// 用户姓名
private String sex;// 性别
private String birthday;// 生日
private String address;// 地址 }
<!--注意:添加用户并返回主键 返回主键类型必须和po中的属性类型对应上 否则报错-->
<!-- selectKey:该标签表明返回的id由哪个sql查询出来,然后通过哪个对象的哪个属性(keyProperty 仅对insert和update有用)返回回去 -->
<!-- LAST_INSERT_ID函数:该函数会返回刚自增添加的ID,它需要和insert语句联合使用才有意义( order="BEFORE" 查询返回的是0)
由于数据库中id 是自增主键 所以id依然按照数据库的值插入 -->
<!-- order:表示selectkey标签中的sql和insert语句的执行顺序,order指定的顺序是相对于insert语句来说 -->
<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
<selectKey keyProperty="id" resultType="int" order="AFTER">
SELECTLAST_INSERT_ID()
</selectKey>
INSERT INTO USER(username,birthday,sex,address)VALUES(#{username},#{birthday},#{sex},#{address})
</insert>
接口: public int insertUser(User user); 返回的int值是插入的条数,获取主键必须是 user.getId()-------useGeneratedKeys(仅对insert和update有用) 取值
范围true|false 默认值是:false。 含义:设置是否使用JDBC的getGenereatedKeys方法获取主键并赋值到keyProperty设置的领域模型属性中
<!-- useGeneratedKeys="true"把新增加的主键赋值到自己定义的keyProperty(id)中 -->
<insert id="insertUser" parameterType="user" useGeneratedKeys="true" keyProperty="id">
INSERT INTO USER(username,birthday,sex,address)VALUES(#{username},#{birthday},#{sex},#{address})
</insert>
如果想用插入后有主键值 使用selectKey或者useGeneratedKeys插入更新一条数据时,可以使用selectKey获取id操作。
当做多条数据插入更新时,而selectKey只能使用一次,此时应该使用useGeneratedKeys操作如果想用插入后有主键值
使用selectKey或者useGeneratedKeys插入更新一条数据时,可以使用selectKey获取id操作。当做多条数据插入更新时,
而selectKey只能使用一次,此时应该使用useGeneratedKeys操作!-- 主键返回之UUID 如果id不是自增主键 那么id需要显示的赋值order="BEFORE" -->
<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
<selectKey keyProperty="id" resultType="string" order="BEFORE">
SELECT UUID()
</selectKey>
INSERT INTO USER(id,username,birthday,sex,address)VALUES(#{id},#{username},#{birthday},#{sex},#{address})
</insert>
resultMap的使用
<select id="findUserRstMap" parameterType="int" resultMap="UserRstMap">
Select id id_,username
username_,sex sex_ from user where id = #{id}
</select>
column是数据库对应的字段,property是po的属性
<resultMap id="UserRstMap" type="cn.itcast.mybatis.po.User" >
<id column="id_" property="id" jdbcType="BIGINT"/> //映射查询结果唯一列<result column="username_" property="username" jdbcType="VARCHAR"/> //映射查询结果中普通列
<result column="sex_" property="sex" jdbcType="VARCHAR"/>
</resultMap>
尽管所有这些选项很强大,但大多时候你只须简单地指定属性名,其他的事情 MyBatis 会自己去推断,顶多要为可能为空的列指定 jdbcType 只需要在可能执行插入、更新和删除的允许空值的列上指定 JDBC 类型。这是 JDBC 的要求而非 MyBatis 的要求。如果你直接面向 JDBC 编程,你需要对可能为 null 的值指定这个类型
#{middleInitial,jdbcType=VARCHAR}
SqlMapConfig.xml文件中
<configuration>
<!-- 批量别名定义 默认是类名小写可以写成 上面的 type="user/全限定名"-->
<typeAliases>
<package name="cn.itcast.ms.po" />
</typeAliases>
</configuration>
TypeAliasRegistry类初始化时注册了一些常用的别名,如果忘记了别名可以在这里面查看 map-->>java.util.Map
<!-- 定义sql片段 -->
<sql id="whereCaulse">
<!-- where标签:默认去掉后面的第一个AND,如果没有查询条件,则把自己干掉 -->
<where>
<if test="user != null">
<!-- if标签:可以进行判断,如为true,在原有的sql中拼接上if标签中的代码片段 -->
<!-- test:输入判断表达式 -->
<if test="user.username != null and user.username != ''">
AND username LIKE '%${user.username}%'
</if>
<if test="user.sex != null and user.sex != ''">
AND sex = #{user.sex}
</if>
</if>
<if test="idList != null and idList.size!=0">
<!-- collection:表示集合参数参数名称 -->
<!-- item:遍历出的项 -->
<!-- open:遍历开始时需要拼接的字符串 -->
<!-- close: 遍历结束时需要拼接的字符串 -->
<!-- separator:遍历过程中需要拼接的字符串 -->
AND id IN
<foreach collection="idList" item="id" open="(" close=")"
separator=",">
#{id}
</foreach>
</if>
</where>
</sql>
resultMap:适合使用返回值是自定义实体类的情况
resultType:适合使用返回值得数据类型是非自定义的,即jdk的提供的类型
两者不能同时用
choose, when, otherwise
有时我们不想应用到所有的条件语句,而只想从中择其一项。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句
<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>
trim标记是一个格式化的标记,可以完成set或者是where标记的功能,如下代码:
1、select * from user
<trim prefix="WHERE" prefixoverride="AND |OR">
<if test="name != null and name.length()>0"> AND name=#{name}</if>
<if test="gender != null and gender.length()>0"> AND gender=#{gender}</if>
</trim>
假如说name和gender的值都不为null的话打印的SQL为:select * from user where name = 'xx' and gender = 'xx'
在红色标记的地方是不存在第一个and的,上面两个属性的意思如下:
prefix:前缀
prefixoverride:去掉第一个and或者是or prefixOverrides 属性会忽略通过管道分隔的文本序列(注意此例中的空格也是必要的)。
它的作用是移除所有指定在 prefixOverrides 属性中的内容,并且插入 prefix 属性中指定的内容
2. update user
<trim prefix="set" suffixoverride="," suffix=" where id = #{id} ">
<if test="name != null and name.length()>0"> name=#{name} , </if>
<if test="gender != null and gender.length()>0"> gender=#{gender} , </if>
</trim>
假如说name和gender的值都不为null的话打印的SQL为:update user set name='xx' , gender='xx' where id='x'
在红色标记的地方不存在逗号,而且自动加了一个set前缀和where后缀,上面三个属性的意义如下,其中prefix意义如上:
suffixoverride:去掉最后一个逗号(也可以是其他的标记,就像是上面前缀中的and一样)
suffix:后缀
<insert id="save" parameterType="NoticeEntity">
INSERT INTO S_NOTICE
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="title != null">TITLE,</if>
<if test="content != null">CONTENT,</if>
<if test="noticeStatus != null">NOTICE_STATUS,</if>
<if test="createdBy != null">CREATED_BY,</if>
<if test="lastUpdBy != null">LAST_UPD_BY,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="title != null">#{title,jdbcType=VARCHAR},</if>
<if test="content != null">#{content,jdbcType=VARCHAR},</if>
<if test="noticeStatus != null">#{noticeStatus,jdbcType=VARCHAR},</if>
<if test="createdBy != null">#{createdBy,jdbcType=VARCHAR},</if>
<if test="lastUpdBy != null">#{lastUpdBy,jdbcType=VARCHAR},</if>
</trim>
</insert>
类似的用于动态更新语句的解决方案叫做 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>
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>
注意 你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象传递给 foreach 作为集合参数。当使用可迭代对象或者数组时,index 是当前迭代的次数,item 的值是本次迭代获取的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值
1> 方法返回值为Boolean,mybatis会自动的将数值转成对应的Boolean类型
接口: public Boolean exists(@Param("bukrs") String bukrs)
对应的xml:
<select id="exists" parameterType="String" resultType="java.lang.Boolean">
select 1 from dual
where exists
( select null from THM_FS12 where BUKRS =#{bukrs}
)
</select>
2> 参数是布尔类型
<select id="existsboolean" parameterType="java.lang.Boolean" resultType="String">
<if test="boolean!=null and boolean==true">
select 1 from dual where 1=1
</if>
<if test="boolean!=null and boolean==false">
select 2 from dual where 2=2
</if>
</select>
3> 使用java静态方法 使用格式为:@aaa@qq.com(传递参数名称)
<select id="javainmybatis" parameterType="String" resultType="String">
<if test="@aaa@qq.com(province)">
select 1 from dual where 1=1
</if>
<if test="@aaa@qq.com(province)">
select 2 from dual where 2=2
</if>
</select>
4> <!-- 使用java中的常量 格式 @qualifiedName@变量名-->
<select id="javaconstant" parameterType="String" resultType="String">
select 1 from dual
where {constant,jdbcType=VARCHAR}='${@aaa@qq.comCOMP_CODE}'
</select>
5> 使用枚举
<select id="javaEnum" parameterType="String" resultType="String">
select 1 from dual
where #{enumStr,jdbcType=VARCHAR}=
'${@aaa@qq.comACTIVITIES_ALL_TYPE.getDescription()}'
</select>
6>mybatis实现SaveOrUpdate,但是仍然建议在Service中实现,因为会影响事务的控制
注意: 若入参是实体类,那么实体类中须包含count属性(可以是别的名字)且有get/set方法。
<selectKey keyProperty="id" resultType="long" order="BEFORE">
select count(id) id from t_coupons_receive where coupon_id=#{couponId}
</selectKey>
<if test "id>0"> </if> -- 亦可使用类中的其他字段存储结果
否则selectKey的结果没法保存,如果入参是Map类型+使用注解+#{index},就没有这个限制. selectKey标签只能用于insert update语句中,否则报错: org.xml.sax.SAXParseException: 元素类型为 "select或者delete" 的内容必须匹配 "(include|trim|where|set|foreach|choose|if|bind)"。最外层标签<select/delete...>不能改动负责返回结果有影响
java接口 : public void saveOrUpdate(@Param("couponId")int couponId) throws DataAccessException;
xml文件中定义:
<insert id="saveOrUpdateData">
<selectKey keyProperty="count" resultType="int" order="BEFORE">
select count(*) from t_coupons_receive where coupon_id=#{couponId}
</selectKey>
<if test="count > 0">
update t_coupons_receive set coupon_id=#{0} ;
</if>
<if test="count == 0">
INSERT INTO t_coupons_receive(`coupon_id`, `create_time`) VALUES ( #{0}, now());
</if>
</insert>
1.1 设置延迟加载
在sqlmapConfig.xml中设置settings属性
<!-- type:resultMap最终需要映射成的java对象类型 属性名相同 都能赋值成功-->
<!-- id标签:映射查询结果唯一列 -->
<!-- result标签:映射查询结果中普通列 -->
<resultMap type="cn.itcast.mybatis.po.OrdersExt" id="OrdersAndUserRstMap">
<!-- 订单信息 -->
<id column="id" property="id" />
<result column="user_id" property="userId" />
<result column="username" property="username" />
<result column="number" property="number" />
<!-- 用户信息 (一对一) -->
<!-- association:用来关联映射一对一关系 -->
<!-- property:表示关联查询的结果要映射到输出结果中的哪个pojo属性上,一般是嵌套 -->
<!-- id标签:如果没有关联查询时,id标签不写影响不大,如果有嵌套查询时,建议id标签写上,不写会影响性能,但不会报错 -->
<association property="user" javaType="user">
<id column="user_id" property="id" />
<result column="username" property="username" />
<result column="sex" property="sex" />
</association>
</resultMap>
如果 <select id="findUserById" parameterType="int" resultType="hashmap"> 返回是map 有为null值得属性将不存在(不包括空值)
{sex=2, id=1, username=王五} 此时 birthday字段不存在于map中
java type中推荐使用包装类型
JDBC Type Java Type
//常用
CHAR String
VARCHAR String
LONGVARCHAR String
NUMERIC java.math.BigDecimal
DECIMAL java.math.BigDecimal
BIT boolean
BOOLEAN boolean
TINYINT byte
SMALLINT short
INTEGER int(INTEGER 参照mybatis****生成的xml)
BIGINT long
REAL float
FLOAT double
DOUBLE double
DATE java.sql.Date (java.util.Date)
TIME java.sql.Time (java.util.Date)
TIMESTAMP java.sql.Timestamp(java.util.Date)
//不常用
BINARY byte[]
VARBINARY byte[]
LONGVARBINARY byte[]
CLOB Clob
BLOB Blob
ARRAY Array
DISTINCT mapping of underlying type
STRUCT Struct
REF Ref
DATALINK java.net.URL[color=red][/color]
示例:
<resultMap type="java.util.Map" id="resultjcm">
<result property="FLD_NUMBER" column="FLD_NUMBER" javaType="double" jdbcType="NUMERIC"/>
<result property="FLD_VARCHAR" column="FLD_VARCHAR" javaType="string" jdbcType="VARCHAR"/>
<result property="FLD_DATE" column="FLD_DATE" javaType="java.sql.Date" jdbcType="DATE"/>
<result property="FLD_INTEGER" column="FLD_INTEGER" javaType="int" jdbcType="INTEGER"/>
<result property="FLD_DOUBLE" column="FLD_DOUBLE" javaType="double" jdbcType="DOUBLE"/>
<result property="FLD_LONG" column="FLD_LONG" javaType="long" jdbcType="INTEGER"/>
<result property="FLD_CHAR" column="FLD_CHAR" javaType="string" jdbcType="CHAR"/>
<result property="FLD_BLOB" column="FLD_BLOB" javaType="[B" jdbcType="BLOB" />
<result property="FLD_CLOB" column="FLD_CLOB" javaType="string" jdbcType="CLOB"/>
<result property="FLD_FLOAT" column="FLD_FLOAT" javaType="float" jdbcType="FLOAT"/>
<result property="FLD_TIMESTAMP" column="FLD_TIMESTAMP" javaType="java.sql.Timestamp" jdbcType="TIMESTAMP"/>
</resultMap>
#{orderStatus,jdbcType=VARCHAR} 没有 jdbcType =datetime
Mybatis中什么时候应该声明jdbcType?
当Mybatis不能自动识别你传入对象的类型时。
什么情况下,Mybatis不能自动识别我的传入类型?
例如:当你传入空值的时候。
1.如果jdbcType=DATE 则你bean就算有时分秒也不会被插入数据库(mybatis会根据jdbc的类型进行取值)
2.如果jdbcType =TIMESTAMP 则可以将年月日时分秒插入数据库
MyBatis 插入空值时,需要指定JdbcType
mybatis insert空值报空值异常,但是在pl/sql不会提示错误,主要原因是mybatis无法进行转换,
用mybatis generator生成代码后,执行查询语句时,oracle里的Date类型字段只精确到年月日,后面时分秒都为零。
jdbcType="DATE"时候,存入到数据库中的字段只有年月日!
后来发现是jdbcType问题,改成 jdbcType="TIMESTAMP" 就可以。(原先默认生成时是jdbcType="DATE")
当jdbcType = DATE 时, 只传入了 年月日
jdbcType = TIMESTAMP , 年月日+ 时分秒
sql中的数据类型和java类型对应关系:
上一篇: pyecharts的一些用法
下一篇: Java 将List平均分成若干个集合