ibatis返回HashMap结果类型与映射

本文详细解析了Java中高级映射技术在ORM框架中的应用,包括返回HashMap、JavaBean的实例化、一对一及一对多关联查询的实现,以及如何优化SQL语句避免N+1问题。通过具体代码示例展示了如何配置结果映射以实现高效的数据访问与处理。

<!-- 返回HashMap结果 类型--> <!-- 如果想返回JavaBean,只需将resultType设置为JavaBean的别名或全限定名 --> <!-- TypeAliasRegistry类初始化时注册了一些常用的别名,如果忘记了别名可以在这里面查看 --> <select id="selectBlogRetHashMap" parameterType="int" resultType="map"> SELECT id AS "id", title AS "title", content AS "content" FROM Blog WHERE id = #{id} </select> 测试代码:/** * 测试返回HashMap */ @SuppressWarnings("unchecked") @Test public void testSelectBlogRetHashMap() { SqlSession session = sqlSessionFactory.openSession(); HashMap<String,Object> blog = (HashMap<String,Object>) session.selectOne( "cn.enjoylife.BlogMapper.selectBlogRetHashMap", 15); session.close(); System.out.println(blog.get("title")); }

ibatis高级映射:

表结构:

create table BLOG ( ID NUMBER(20), TITLE VARCHAR2(50), CONTENT VARCHAR2(4000), BLOG_AUTHOR_ID NUMBER(20) ) create table AUTHOR ( ID NUMBER(20), AUTHOR_NAME VARCHAR2(50) ); create table POSTS ( ID NUMBER(20), SUBJECT VARCHAR2(50), BODY VARCHAR2(4000), BLOG_ID NUMBER(20) ) bean信息:package cn.enjoylife.domain; import java.util.List; public class Blog { private Integer id; private String title; private String content; private Author author; private List<Post> posts/*=new ArrayList<Post>()*/; public List<Post> getPosts() { return posts; } public void setPosts(List<Post> posts) { this.posts = posts; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public Author getAuthor() { return author; } public void setAuthor(Author author) { this.author = author; } @Override public String toString() { return "Blog [content=" + content + ", id=" + id + ", title=" + title + "]"; } }package cn.enjoylife.domain; public class Author { private Integer id; private String name; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { // System.out.println("Author[id="+id+",name="+name+"]"); return "Author[id="+id+",name="+name+"]"; } }package cn.enjoylife.domain; public class Post { private Integer id; private String subject; private String postContent; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getSubject() { return subject; } public void setSubject(String subject) { this.subject = subject; } public String getPostContent() { return postContent; } public void setPostContent(String postContent) { this.postContent = postContent; } @Override public String toString() { return "Post [postContent=" + postContent + ", id=" + id + ", subject=" + subject + "]"; } } Blog.xmll配置:<!-- 高级结果映射 --> <!-- 一对一关联 嵌套查询 应用select属性 1)id="selectBlogAndRelatedAuthor" 中的 blog_author_id 对应到 <association property="author" column="blog_author_id"/>中的column="blog_author_id" 2)我们执行selectBlogAndRelatedAuthor 1次之后,所产生的每条记录都要再进行一个查询来获取author信息(N), 这就是N+1问题,应该使用延迟加载的方式,否则这有可能产生致命的后果。 3)对于一对一关联,我设置了 <settings> <setting name="lazyLoadingEnabled" value="true"/> </settings> 却没有对Author进行延迟加载,不知为何。。。 --> <resultMap id="blogResult" type="Blog" > <association property="author" column="blog_author_id" javaType="Author" select="selectAuthor" /> </resultMap> <select id="selectBlogAndRelatedAuthor" parameterType="int" resultMap="blogResult" > SELECT id,title,content,blog_author_id FROM blog WHERE id = #{id} </select> <select id="selectAuthor" parameterType="int" resultType="Author"> SELECT id,author_name as "name" FROM author WHERE id = #{id} </select> <!-- 一对一关联 嵌套结果 --> <resultMap id="blogResult2" type="Blog"> <id property="id" column="id" /> <result property="title" column="title"/> <association property="author" column="blog_author_id" javaType="Author"> <id property="id" column="author_id"/> <result property="name" column="author_name"/> </association> </resultMap> <select id="selectBlogAndRelatedAuthor2" parameterType="int" resultMap="blogResult2" > SELECT t.ID, t.TITLE, t.CONTENT, a.id as "author_id", a.author_name FROM blog t INNER JOIN author a ON t.BLOG_AUTHOR_ID = a.ID AND t.ID = #{id} </select> <!-- 一对多关联 嵌套查询,应用select属性 <collection property="posts" column="id" javaType="ArrayList" ofType="Post" select="selectPosts"/>中的column指得是Post所对应表中的引用的主表中的主键id, 注意:这个column指的是主表(Blog)中的id,我在这犯了个错,写为Post所对应表中的外键id,这是不对的, 应为所引用主表的主键id。 property="posts" javaType="ArrayList" ofType="Post" 指属性posts为元素为Post的ArrayList类型 同样没有进行延迟加载,不知为何。。。 --> <resultMap type="Blog" id="blogResult3" > <id property="id" column="id"/> <result property="title" column="title"/> <result property="content" column="content"/> <collection property="posts" column="id" javaType="ArrayList" ofType="Post" select="selectPosts"/> </resultMap> <select id="selectBlogAndRelatedPosts" parameterType="int" resultMap="blogResult3" > SELECT id, title, content FROM blog WHERE id = #{id} </select> <select id="selectPosts" parameterType="int" resultType="Post" > SELECT p.id,p.subject,p.body as "postContent" FROM posts p WHERE p.blog_id =#{id} </select> <!-- 一对多关联 嵌套结果,在使用这种方式时,sql语句应该使用别名以保证不重复,如果不这样,可能 出现结果不正确的现象,比如以下的post_id别名 --> <resultMap type="Blog" id="blogResultVersion" > <id property="id" column="id" /> <result property="title" column="title"/> <result property="content" column="content"/> <collection property="posts" javaType="ArrayList" ofType="Post" column="id"> <id property="id" column="post_id"/> <result property="subject" column="subject"/> <result property="postContent" column="postContent"/> </collection> </resultMap> <select id="selectBlogAndRelatedPosts2" parameterType="int" resultMap="blogResultVersion"> SELECT t.id, t.title, t.content, p.id as "post_id", p.subject, p.BODY as "postContent" FROM blog t left outer JOIN posts p ON t.id = p.blog_id WHERE t.ID = #{id} </select> 测试代码:/** * 测试一对一关联 嵌套查询 */ @Test public void testSelectBlogAndRelatedAuthor() { SqlSession session = sqlSessionFactory.openSession(); Blog blog = (Blog) session.selectOne( "cn.enjoylife.BlogMapper.selectBlogAndRelatedAuthor", 15); System.out.println(blog.toString()); session.close(); System.out.println(blog.getAuthor()); } /** * 测试一对一关联 嵌套结果 */ @Test public void testSelectBlogAndRelatedAuthor2() { SqlSession session = sqlSessionFactory.openSession(); Blog blog = (Blog) session.selectOne( "cn.enjoylife.BlogMapper.selectBlogAndRelatedAuthor2", 15); session.close(); System.out.println(blog.toString()); System.out.println(blog.getAuthor()); } /** * 测试一对多关联 嵌套查询 */ @Test public void testSelectBlogAndRelatedPosts() throws Exception { SqlSession session = sqlSessionFactory.openSession(); Blog blog = (Blog) session.selectOne( "cn.enjoylife.BlogMapper.selectBlogAndRelatedPosts", 15); System.out.println(blog.toString()); session.close(); System.out.println(blog.getPosts()); } /** * 测试一对多关联 嵌套结果 */ @Test public void testSelectBlogAndRelatedPosts2() throws Exception { SqlSession session = sqlSessionFactory.openSession(); Blog blog = (Blog) session.selectOne( "cn.enjoylife.BlogMapper.selectBlogAndRelatedPosts2", 15); session.close(); System.out.println(blog.toString()); System.out.println(blog.getPosts()); }

### 如何在 iBatis 中将查询结果以 Map 形式返回iBatis(现称为 MyBatis)中,可以通过多种方式将查询结果以 `Map` 的形式返回。以下是几种常见的实现方法及其注意事项。 #### 方法一:使用 ResultHandler 实现自定义 Map 结果 如果需要灵活控制返回的 `Map` 数据结构,可以使用 `ResultHandler` 来手动处理每一行的数据。这种方式适用于复杂场景下的定制化需求。 ```java import org.apache.ibatis.session.SqlSession; import java.util.HashMap; import java.util.List; public class CustomMapper { public HashMap<String, String> getCommodityCategory(SqlSession sqlSession) { final HashMap<String, String> resultMap = new HashMap<>(); sqlSession.select("getCommodityByCode", null, (resultContext) -> { Object row = resultContext.getResultObject(); if (row instanceof List && !((List<?>) row).isEmpty()) { // 假设每行有两个字段 commodity_code 和 category_name resultMap.put(((HashMap<?, ?>) row).get("commodity_code").toString(), ((HashMap<?, ?>) row).get("category_name").toString()); } }); return resultMap; } } ``` 这种方法允许开发者完全掌控如何构建最终的 `Map`[^1]。 --- #### 方法二:利用 @MapKey 注解简化操作 对于简单场景,可以直接使用 `@MapKey` 注解来指定返回 `Map` 的键值来源。此方法适合于单条记录或多条记录均能映射成唯一键的情况。 ```java public interface CommodityMapper { @Select("SELECT commodity_code AS code, category_name AS name FROM commodities") @MapKey("code") // 将 'code' 列作为 Map 的 Key Map<String, String> getCategoryByName(); } ``` 在此示例中,`@MapKey("code")` 明确指定了 `Map` 的键为 SQL 查询结果中的 `code` 字段,而其对应的值则为整个对象实例或特定属性[^2]。 --- #### 方法三:通过 XML 配置文件设置返回类型 除了注解外,还可以借助 XML 文件完成同样的功能。例如: ```xml <select id="getCategories" parameterType="String" resultType="hashmap"> SELECT commodity_code AS code, category_name AS name FROM commodities WHERE status = #{status} </select> ``` 随后,在 Java 代码中调用该接口即可获得一个包含多个键值对的 `Map` 对象。需要注意的是,默认情况下不会自动启用驼峰命名转换规则;因此建议显式声明别名以匹配实际业务逻辑所需字段名称[^3]。 --- #### 示例程序演示 Spring JdbcTemplate 下的 queryForMap 方法 尽管题目提到的是 iBatis/MyBatis,但为了对比说明不同框架间差异性,下面给出基于 Spring JDBC Template 的另一种解决方案——即直接采用内置工具类快速获取单一记录对应关系表。 ```java import org.springframework.jdbc.core.JdbcTemplate; import javax.sql.DataSource; public class UserDao { private DataSource dataSource; public void setDataSource(DataSource ds){ this.dataSource = ds; } public Map<String,Object> getUserById(int userId){ String sqlStr = "SELECT * FROM user_tb WHERE USER_ID=?"; JdbcTemplate jt = new JdbcTemplate(dataSource); return jt.queryForMap(sqlStr,new Object[]{userId}); } } ``` 这段脚本展示了如何运用 spring-jdbc 提供的功能读取某张表格里符合条件的第一笔资料,并将其封装进标准库容器之中[^4]。 --- ### 注意事项 - 当前讨论仅限于基础层面的应用案例分析,请根据项目实际情况调整具体实施方案。 - 若涉及大量数据提取,则需考虑性能优化策略以及内存占用情况等问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值