欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

mybatis 的一些用法

程序员文章站 2022-07-14 13:02:39
...
public class User {
	private int id;
	private String username;// 用户姓名
	private String sex;// 性别
	private String birthday;// 生日
	private String address;// 地址 }
	  
	
如果输入参数不是简单类型,那么#{}中的参数名称要和pojo中的属性名称一致,或者mapkey一致。取值方式是采用OGNL方式获取输入参数的值的
<!--注意:添加用户并返回主键 返回主键类型必须和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>


类似的用于动态更新语句的解决方案叫做 setset 元素可以用于动态包含需要更新的列,而舍去其它的。比如:

<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>
   这里,set 元素会动态前置 SET 关键字,同时也会删掉无关的逗号,因为用了条件语句之后很可能就会在生成的 SQL 语句的后面留下这些逗号。(译者注:因为用的是“if”元素,若最后一个“if”没有匹配上而前面的匹配上,SQL 语句的最后就会有一个逗号遗留

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>
     foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及在迭代结果之间放置分隔符。这个元素是很智能的,因此它不会偶然地附加多余的分隔符。
       注意 你可以将任何可迭代对象(如 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属性

mybatis 的一些用法

  <!-- 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类型对应关系:

mybatis 的一些用法