zoukankan      html  css  js  c++  java
  • Mybatis入门简版(补充)

    一、Mybatis 中$与#的区别

     

    #相当于对数据 加上 双引号,$相当于直接显示数据

    1. #将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。如:order by #user_id#,如果传入的值是111,那么解析成sql时的值为order by "111", 如果传入的值是id,则解析成的sql为order by "id".

    2. $将传入的数据直接显示生成在sql中。如:order by $user_id$,如果传入的值是111,那么解析成sql时的值为order by user_id,  如果传入的值是id,则解析成的sql为order by id.

    3. #方式能够很大程度防止sql注入。

    4.$方式无法防止Sql注入。

    5.$方式一般用于传入数据库对象,例如传入表名.

    6.一般能用#的就别用$.

    MyBatis排序时使用order by 动态参数时需要注意,用$而不是#

    二、Mybatis映射文件里的<selectkey>

    我们在数据库插入一条数据(主键是数据库生成)的时候,经常是需要返回插入这条数据的(数据库生成的)主键。

    比如插入用户信息JavaBean时,id不需要我们设置(自增),那么插入后,我们想马上得这个JavaBean的ID。


    可以下面这样改:

    <insert id="saveUser" parameterType="cn.itcast.mybatis.pojo.User">
    	<selectKey keyColumn="id" keyProperty="id" order="AFTER"
    		resultType="int">
    		SELECT LAST_INSERT_ID()
    	</selectKey>
    	INSERT INTO `user`
    	(username,birthday,sex,address) VALUES
    	(#{username},#{birthday},#{sex},#{address})
    </insert>

    其中:

    selectKey 标签实现主键返回 
    keyColumn:

    主键对应的表中的哪一列 

    keyProperty:

    主键对应的pojo中的哪一个属性 

    order:

    设置在执行insert语句前执行查询id的sql,还是在执行insert语句之后执行查询id的sql 

    MySQL填AFTER ,Oracle填BEFORE

    resultType:

    设置返回的id的类型 


    三、映射xml文件中的resultMap

    1.介绍

    resultType可以指定将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名一致方可映射成功

    如果sql查询字段名和pojo的属性名不一致,可以通过resultMap将字段名和属性名作一个对应关系 ,resultMap实质上还需要将查询结果映射到pojo对象中。

    比如对于数据库里user_id这种字段,逆向工程会生成userId属性的pojo


    2.使用(resultType改用resultMap

    <!-- resultMap最终还是要将结果映射到pojo上,type就是指定映射到哪一个pojo -->
    
    	<!-- id:设置ResultMap的id -->
    	<resultMap type="cn.ssm.pojo.order" id="orderResultMap">
    		<result property="userId" column="user_id" />//只要写那个不一样的就行了!
    	</resultMap>
    
    	<!-- 查询所有的订单数据 -->
    	<select id="queryOrderAll" resultMap="orderResultMap">
    		SELECT id, user_id,
    		number,
    		createtime, note FROM `order`
    	</select>
    其中:property:主键在pojo中的属性名,column:主键在数据库中的列名

    四、动态SQL(基于OGNL表达式)

    1.if标签

    <!-- 根据条件查询用户 -->
    <select id="queryUserByWhere" parameterType="user" resultType="user">
    	SELECT id, username, birthday, sex, address FROM `user`
    	WHERE 1=1
    	<if test="sex != null and sex != ''">
    		AND sex = #{sex}
    	</if>
    	<if test="username != null and username != ''">
    		AND username LIKE
    		'%${username}%'
    	</if>
    </select>
    

    2.where标签

    上面的例子里,还得写个1=1 防止出现 where and 这种错误情况。其实这种情况可以通过where标签解决

    <!-- 根据条件查询用户 -->
    <select id="queryUserByWhere" parameterType="user" resultType="user">
    	SELECT id, username, birthday, sex, address FROM `user`
    <!-- where标签可以自动添加where,同时处理sql语句中第一个and关键字 -->
    	<where>
    		<if test="sex != null">
    			AND sex = #{sex}
    		</if>
    		<if test="username != null and username != ''">
    			AND username LIKE
    			'%${username}%'
    		</if>
    	</where>
    </select>
    


    3.SQL片段

    Sql中可将重复的sql提取出来,使用时用include引用即可,最终达到sql重用的目的。

    把上面例子中的id, username, birthday, sex, address提取出来,作为sql片段,如下:

    <!-- 声明sql片段 -->
    <sql id="userFields">
    	id, username, birthday, sex, address
    </sql>
    
    <!-- 根据条件查询用户 -->
    <select id="queryUserByWhere" parameterType="user" resultType="user">
    
    	<!-- 使用include标签加载sql片段;refid是sql片段id -->
    	SELECT <include refid="userFields" /> FROM `user`
    
    	<where>
    		<if test="sex != null">
    			AND sex = #{sex}
    		</if>
    		<if test="username != null and username != ''">
    			AND username LIKE
    			'%${username}%'
    		</if>
    	</where>
    </select>

    如果要使用别的Mapper.xml配置的sql片段,可以在refid里面加上对应的Mapper.xml的namespace


    4.foreach标签

    向sql传递数组或List,mybatis使用foreach解析,比如:


    根据多个id查询用户信息
    查询sql:
    SELECT * FROM user WHERE id IN (1,10,24)

    <!-- 根据ids查询用户 -->
    <select id="queryUserByIds" parameterType="queryVo" resultType="user">
    	SELECT * FROM `user`
    	<where>
    		<!-- foreach标签,进行遍历 -->
    		<!-- collection:遍历的集合,这里是QueryVo的ids属性 -->
    		<!-- item:遍历的项目,可以随便写,,但是和后面的#{}里面要一致 -->
    		<!-- open:在前面添加的sql片段 -->
    		<!-- close:在结尾处添加的sql片段 -->
    		<!-- separator:指定遍历的元素之间使用的分隔符 -->
    		<foreach collection="ids" item="item" open="id IN (" close=")"
    			separator=",">
    			#{item}
    		</foreach>
    	</where>
    </select>
    




    五、多表查询


    多表查询的时候通常会要返回多个表的数据,即多个pojo的部分数据。


    5.1一对一查询(两张表)


    此时要么采取新建pojo(继承一个pojo再加上新需要的)去包裹查出来的数据,要么在原pojo里组合另外一个pojo(作为成员对象),即继承和组合 两种方法。


    5.1.1采用继承的方法(正常采用resultType即可)



    5.1.2采用组合的方式

    那么此时多个pojo会有相同属性,如何映射?采取resultMap



    pojo可能会要改成下面这样:


    那么此时查询结果对pojo的映射得改改了

    <resultMap type="order" id="orderUserResultMap">
    	<id property="id" column="id" />
    	<result property="userId" column="user_id" />
    	<result property="number" column="number" />
    	<result property="createtime" column="createtime" />
    	<result property="note" column="note" />
    
    	<!-- association :配置一对一属性 -->
    	<!-- property:order里面的User属性名 -->
    	<!-- javaType:属性类型 -->
    	<association property="user" javaType="user">
    		<!-- id:声明主键,表示user_id是关联查询对象的唯一标识-->
    		<id property="id" column="user_id" />
    		<result property="username" column="username" />
    		<result property="address" column="address" />
    	</association>
    
    </resultMap>
    
    <!-- 一对一关联,查询订单,订单内部包含用户属性 -->
    <select id="queryOrderUserResultMap" resultMap="orderUserResultMap">
    	SELECT
    	o.id,o.user_id,o.number,o.createtime,o.note,u.username,u.address
    	FROM
    	`order` o
    	LEFT JOIN `user` u ON o.user_id = u.id
    </select>
    


    5.2一对多查询

    如下:



    那么映射文件如下:

    <resultMap type="user" id="userOrderResultMap">
    	<!-- 配置主键,将主键相同的记录映射到一个集合里去-->
    	<id property="id" column="id" />
    	<result property="username" column="username" />
    	<result property="birthday" column="birthday" />
    	<result property="sex" column="sex" />
    	<result property="address" column="address" />
    
    	<!-- 配置一对多的关系 -->
    	<collection property="orders" javaType="list" ofType="order">
    		<!-- 配置主键,是关联Order的唯一标识 -->
    		<id property="id" column="oid" />
    		<result property="number" column="number" />
    		<result property="createtime" column="createtime" />
    		<result property="note" column="note" />
    	</collection>
    </resultMap>
    
    <!-- 一对多关联,查询订单同时查询该用户下的订单 -->
    <select id="queryUserOrder" resultMap="userOrderResultMap">
    	SELECT
    	u.id,u.username,u.birthday,u.sex,u.address,o.id oid,o.number,o.createtime,o.note
    	FROM
    	`user` u
    	LEFT JOIN `order` o ON u.id = o.user_id
    </select>
    


  • 相关阅读:
    【转载】大连商品交易所-套利交易相关问题
    LC 1340. Jump Game V
    1057 Stack
    1059 Prime Factors
    LC 1425. Constrained Subset Sum
    LCP 13. 寻宝
    P3381 【模板】最小费用最大流
    P3376 【模板】网络最大流
    LC 面试题51. 数组中的逆序对
    LC 466. Count The Repetitions
  • 原文地址:https://www.cnblogs.com/chz-blogs/p/9380946.html
Copyright © 2011-2022 走看看