论坛首页 Java企业应用论坛

Ibatis动态查询例子(#和$以及iterate等的用法)

浏览 14814 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-05-21   最后修改:2009-08-11

最近做了很多动态的查询,尤其是排序,以及一些状态字段,所以就做了一个总的动态查询,以不变应万变,呵呵

 

ibatis 里面的sql代码:

	<select id="getTopics" resultClass="topic" parameterClass="map">
			<![CDATA[
			        select * from p_Topic 
			]]>
		<dynamic prepend=" WHERE ">
			<isPropertyAvailable property="authorId">
				<isNotNull property="authorId" prepend=" and ">
					authorId=#authorId# 
                </isNotNull>
			</isPropertyAvailable>
			<isPropertyAvailable property="marketId">
				<isNotNull property="marketId" prepend=" and ">
					marketId=#marketId# 
                </isNotNull>
			</isPropertyAvailable>

			<isPropertyAvailable property="isDelete">
				<isNotNull property="isDelete" prepend=" and ">
					isDelete=#isDelete# 
                </isNotNull>
			</isPropertyAvailable>

			<isPropertyAvailable property="isBest">
				<isNotNull property="isBest" prepend=" and ">
					isBest=#isBest#
				</isNotNull>
			</isPropertyAvailable>

			<isPropertyAvailable property="statusStr">
				<isNotNull property="statusStr" prepend=" and ">
					$statusStr$
				</isNotNull>
			</isPropertyAvailable>
			<isPropertyAvailable property="marketIdList">
				<isNotNull property="marketIdList" prepend=" and marketId in ">
					<iterate property="marketIdList" conjunction="," close=")" open="(">
						#marketIdList[]#
					</iterate>
				</isNotNull>
			</isPropertyAvailable>
		</dynamic>

		<dynamic prepend=" order by ">
			<isPropertyAvailable property="orderStr">
				<isNotNull property="orderStr">
					$orderStr$
                </isNotNull>
			</isPropertyAvailable>
		</dynamic>

		<dynamic>
			<isPropertyAvailable property="begin">
				<isNotNull property="begin">
					limit #begin# 
                </isNotNull>
			</isPropertyAvailable>
			<isPropertyAvailable property="max" prepend=" , ">
				<isNotNull property="max">
					#max#
                </isNotNull>
			</isPropertyAvailable>
		</dynamic>
	</select>



	<select id="getTopicCount" resultClass="java.lang.Long"
		parameterClass="map">
			<![CDATA[
			        select count(id) from p_Topic 
			]]>
		<dynamic prepend=" WHERE ">
			<isPropertyAvailable property="authorId">
				<isNotNull property="authorId" prepend=" and ">
					authorId=#authorId# 
                </isNotNull>
			</isPropertyAvailable>
			<isPropertyAvailable property="marketId">
				<isNotNull property="marketId" prepend=" and ">
					marketId=#marketId# 
                </isNotNull>
			</isPropertyAvailable>

			<isPropertyAvailable property="isDelete">
				<isNotNull property="isDelete" prepend=" and ">
					isDelete=#isDelete# 
                </isNotNull>
			</isPropertyAvailable>

			<isPropertyAvailable property="isBest">
				<isNotNull property="isBest" prepend=" and ">
					isBest=#isBest#
				</isNotNull>
			</isPropertyAvailable>

			<isPropertyAvailable property="statusStr">
				<isNotNull property="statusStr" prepend=" and ">
					$statusStr$
				</isNotNull>
			</isPropertyAvailable>
			<isPropertyAvailable property="marketIdList">
				<isNotNull property="marketIdList" prepend=" and ">
					<iterate property="marketIdList" conjunction="," close=")" open=" marketId in (">
						#marketIdList[]#
					</iterate>
				</isNotNull>
			</isPropertyAvailable>
		</dynamic>
	</select>

这里需要注意的是:

①#xxx#  代表xxx是属性值,map里面的key或者是你的pojo对象里面的属性,ibatis会自动在它的外面加上引号,表现在sql语句是这样的 where xxx = 'xxx' ;

   而$xxxx$ 则是把xxxx作为字符串拼接到你的sql语句中,比如 order by  topicId , 如果你不用$来拼接而用#的话,外面就会被加上引号的哦    比如你的语句这样写  ... order by #xxx# (xxx就是你传进来的字符串topicId),ibatis 就会把他翻译成  order by 'topicId' 这样就报错了 ,用$的结果就是这样  order by topicId

②这里的iterate

<isPropertyAvailable property="marketIdList">
	<isNotNull property="marketIdList" prepend=" and marketId in ">
		<iterate property="marketIdList" conjunction="," close=")" open="(">
			#marketIdList[]#
		</iterate>
	</isNotNull>
</isPropertyAvailable>

 注意 iterate 的property属性 ,虽然你上面的isNotNull什么的都有这句,但这里一定要写清楚,否则ibatis会找不到你的list的

 

 

数据访问层代码:

public List<Topic> getTopics(Map<String, Object> map) {

		return getSqlMapClientTemplate().queryForList("getTopics", map);
	}

 服务层代码:

	public List<Topic> getTopicsByMarketIdList(Long authorId,List<Long> marketIdList,
			Integer orderby, Integer status, Pagination pagination) {
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("authorId", authorId);
		map.put("isDelete", false);
		map.put("marketIdList", marketIdList);
		map.put("orderStr", "这里你组装你的order字符串");
		map.put("statusStr","这里你组装你的status字符串");
		map.put("begin", pagination.getOffset());
		map.put("max", pagination.getPageSize());
               //这个getTopicCount()方法和getTopics()大体是一致的,所以我的dao里面省略了它
		Long total = topicDao.getTopicCount(map);
		if (total == 0) {
			return new ArrayList<Topic>();
		} else {
			pagination.setTotal(total);
			List<Topic> res = topicDao.getTopics(map);
			return res;
		}
	}
 
public class Topic extends BaseObject implements Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = -851973667810710701L;

	private Long id;
	private Long authorId;
	private String authorName;
	private Long marketId;
	private String title;
	private String tags;
	private String content;
	private Date pubdate;
	private Integer isBest;
	private Integer status;
	private Integer isDelete;
	private Integer clickCount;
	private Integer replyCount;
	private Date lastReplyTime;
       //getter and setter 省略...
}

Pagination代码:

public class Pagination {

	/**
	 * 要查看的页码
	 */
	private int page;

	/**
	 * 每页显示数
	 */
	private int pageSize;

	/**
	 * 一共有多少页
	 */
	private int totalPage;

	/**
	 * 一共有多少条记录
	 */
	private long total;

	/**
	 * 当前页的记录数
	 */
	private int size;

	/**
	 * 只需要topxx,不需要页数信息了
	 */
	private boolean topOnly;

      /**
       *从第几条记录开始	
       */
  	private int offset;
	
	public void setOffset(int offset) {
		this.offset = offset;
	}

	public Pagination(int page, int pageSize) {
		this.page = page;
		this.pageSize = pageSize;
	}

	public Pagination() {
	}

	public boolean require() {
		return pageSize > 0 ? true : false;
	}

	public int from() {
		return page * pageSize;
	}

	public int to() {
		return from() + size;
	}

	public int getPage() {
		return page;
	}

	public void setPage(int page) {
		this.page = page;
	}

	public int getPageSize() {
		return pageSize;
	}

	public void setPageSize(int pageSize) {
		this.pageSize = pageSize;
	}

	public int getTotalPage() {
		return totalPage;
	}

	public void setTotalPage(int totalPage) {
		this.totalPage = totalPage;
	}

	public long getTotal() {
		return total;
	}

	public void setTotal(long total) {
		this.total = total;
		if (pageSize > 0) {
			this.totalPage = (int) Math.ceil(total / (double) pageSize);
		} else {
			this.totalPage = 1;
		}
		if (page >= totalPage) {
			page = totalPage - 1;
		}
		if (page < 0)
			page = 0;
		if (pageSize > 0) {
			if (page < totalPage - 1)
				this.size = pageSize;
			else
				this.size = (int) (total % pageSize);
		} else {
			this.size = (int) total;
		}
		offset=page * pageSize;
	}

	public int getOffset() {
		return offset;
	}

	public int getSize() {
		return size;
	}

	public void setSize(int size) {
		this.size = size;
	}

	public boolean isTopOnly() {
		return topOnly;
	}

	public void setTopOnly(boolean topOnly) {
		this.topOnly = topOnly;
	}

}
   发表时间:2009-08-04   最后修改:2009-08-04
动态语句里的分句给予服用都还是提出来比较好。


        <isPropertyAvailable property="marketIdList">  
            <isNotNull property="marketIdList" prepend=" and marketId in ">  
                <iterate property="marketIdList" conjunction="," close=")" open="(">  
                    #marketIdList[]#  
                </iterate>  
            </isNotNull>  
        </isPropertyAvailable>

如果子句前的属性在参数对象中都不存在。
那么你动态生成的sql不符合逻辑了,改成下面的好些
         <isPropertyAvailable property="marketIdList">  
            <isNotNull property="marketIdList" prepend="and">  
                <iterate property="marketIdList" conjunction="," close=")" open=" marketId in (">  
                    #marketIdList[]#  
                </iterate>  
            </isNotNull>  
        </isPropertyAvailable>


1 请登录后投票
   发表时间:2009-08-11  
谢谢 lemonweirui 的更正,帮我发现了一个bug,谢谢
0 请登录后投票
   发表时间:2009-11-05  
我觉得2楼提出的,只不过是看起来更漂亮而已,原写法也不会出现Bug
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics