Mybatis的若干问题总结

标签: Java 分类: Java 创建时间:2019-12-23 06:59:50 更新时间:2025-01-17 10:39:22

1.配置文件

2.传入变量

1
2
3
4
SELECT * FROM realtime where RecordTime BETWEEN ${startdate} AND ${enddate} 

## or
SELECT * FROM realtime where RecordTime BETWEEN #{startdate} AND #{enddate}

#和$的区别
1.#是把传入的数据当作字符串,如#field#传入的是id,则sql语句生成是这样,order by “id”,这当然会报错..
2.$传入的数据直接生成在sql里,如$field$传入的是id,则sql语句生成是这样,order by id, 这就对了.
3.#方式能够很大程度防止sql注入.
4.$方式无法防止sql注入.
5.$方式一般用于传入数据库对象.例如传入表名.
6.一般能用#的就别用$.

3.动态生成sql语句

需求来源于在一张表中查找id号符合多个值的记录,id可能是一个也可能是两个,我能想到的就是使用in操作符,id in (1,2,3,4)。那么如何传入这个(1,2,3,4)呢?官网给的例子如下:

1
2
3
4
5
6
7
8
9
<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为我们需要传入的List,List等类型的变量,item为其中的内容。open为开始符合,close为结束分割符,separator为分隔符。比如我这里的list为List类型,最后生成的sql语句即为

1
2
3
4
5
6
/*
* list.add<>
*/
SELECT *
FROM POST P
WHERE ID in (1,2,3)

java端mapper代码:

1
2
// 根据开始时间和结束时间以及站点列表查询历史记录
List<POST> selectPostIn(List<Integer> list);

4.打印输出日志

只需要在application.yml中添加,其中com.bibichuan.bigdata.mapper是我mapper的包路径

1
2
3
4
5
6
logging:
level:
com:
bibichuan:
bigdata:
mapper: debug

5.返回值

(1) 如下语句,我只返回了max(InsFlux),min(InsFlux),这两个字段。

1
2
3
4
5
6
7
8
9
10
11
12
  <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace 指定映射对应的mapper接口类-->
<mapper namespace="com.bibichuan.bigdata.mapper.RealTimeMapper">
<!--查询最近一个月内最大和最小瞬时流量-->
<select id="getMaxMinInsFlux" resultType="List">
SELECT max(InsFlux),min(InsFlux) FROM lsmfhx.realtime WHERE parseDateTimeBestEffortOrNull(RecordTime) BETWEEN
toDateTime(#{startdate}) AND toDateTime(#{enddate})
</select>

</mapper>

如果使用List返回值,我觉得是不是大材小用了。

1
List<Object[]> getMaxMinInsFlux(String startdate,String enddate);

注意

resultType="返回结果类型",一般把结果映射到对应的JAVAbean,select 返回的每一条记录的类型,而不是所有记录组成的类型。

也就是说,resultType的类型,是把sql语句返回的每一行映射成什么类型。比如:

1
resultType="com.bibichuan.bigdata.Entity.RealTime"

即把select 返回的每一行都映射为一个RealTime类型。

(2) 参考文章1中,我们还可以找到两种方式将返回值包装成map,第一种就是直接返回的结果是[key1=value1,key2=value2...]这种形式,另一种是把结果封装成{key=object [id=1, name=Bob, age=15.0]},也就是关键字可以指定,而值是一个对象,类似于Map<String,Object>这种形式。
第一种直接指定resultType=”Map”,第二种指定resultType=”你自己定义的JavaBean”,然后在mapper的interface接口中,通过@MapKey(“关键字”),例如参考文章中,指定了name作为返回的Map中的key:

1
2
3
4
5
public interface UserDao {
/*用MapKey注解指定字段name作为map中的key*/
@MapKey("name")
public Map<String, User> getUserMap(String name);
}

(3) 其他类型的返回值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public interface AuthorMapper {
// (Author) selectOne("selectAuthor",5);
Author selectAuthor(int id);
// (List) selectList("selectAuthors")
List selectAuthors();
// (Map) selectMap("selectAuthors", "id")
@MapKey("id")
Map selectAuthors();
// insert("insertAuthor", author)
int insertAuthor(Author author);
// updateAuthor("updateAuthor", author)
int updateAuthor(Author author);
// delete("deleteAuthor",5)
int deleteAuthor(int id);
}

6.java.lang.UnsupportedOperationException

主要是返回值的问题。

1
2
3
4
5
6
7
8
9
10
11
<!--出现错误-->
<select id="getMaxMinInsFlux" resultType="List">
SELECT max(InsFlux),min(InsFlux) FROM lsmfhx.realtime WHERE parseDateTimeBestEffortOrNull(RecordTime) BETWEEN
parseDateTimeBestEffortOrNull(#{startdate}) AND parseDateTimeBestEffortOrNull(#{enddate})
</select>

<!--正确返回值-->
<select id="getMaxMinInsFlux" resultType="Map">
SELECT max(InsFlux),min(InsFlux) FROM lsmfhx.realtime WHERE parseDateTimeBestEffortOrNull(RecordTime) BETWEEN
parseDateTimeBestEffortOrNull(#{startdate}) AND parseDateTimeBestEffortOrNull(#{enddate})
</select>

使用map类型,即可返回正确的内容。

7.无法获取数据类型为text的值

数据库中的一个字段是text类型,但是使用java总是获取不到其中的值。参考资料中,大部分是说,有WithBLOBs方法等,自动生成等。
解决方法是编写一个resultMap,比如我的实体类是SiteInfo,我将数据库中属性为extra_settings的字段映射为VARCHAR类型就可以了。

1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace 指定映射对应的mapper接口类-->
<mapper namespace="com.bibichuan.bigdata.mapper.SiteInfoMapper">
<resultMap id="ResultMapWithBLOBs" type="com.bibichuan.bigdata.Entity.SiteInfo">
<result column="extra_settings" jdbcType="VARCHAR" property="extra_settings" />
</resultMap>

<select id="selectAll" resultType="com.bibichuan.bigdata.Entity.SiteInfo" resultMap="ResultMapWithBLOBs">
SELECT * FROM siteinfo
</select>
</mapper>

8.返回list

需求就是使用sql返回多条数据,但是我不想再增加一个实体类,可以分为如下几步:
1.xml中使用 HashMap 作为返回值

1
2
3
4
5
6
7
8
9
<select id="getSiteInfo" resultType="java.util.HashMap">
SELECT s.SiteNo ,SiteName ,GroupId ,SiteLevel FROM siteinfo s
INNER JOIN (
<foreach collection="site_list" item="item" index="index" separator="UNION ALL" >
SELECT #{item} AS SiteNo
</foreach>
) AS t2
ON s.SiteNo = t2.SiteNo
</select>

2.mapper中的代码,使用list进行返回

1
List<Map<String,Object>> getSiteInfo(@Param("site_list") List<Integer> site_list);

3.可以将返回的值进行遍历,也可以通过键获取数据内容

1
2
3
4
5
6
7
8
9
List<Map<String,Object>> siteinfos=vRealTimeService.getSiteInfo(sitelist);
JSONObject siteinfResult=new JSONObject();
siteinfos.stream().forEach(siteinfo->{
String sitenoStr=siteinfo.get("SiteNo").toString();
JSONObject siteContent=new JSONObject();
siteContent.putAll(siteinfo);
// 保存对象
siteinfResult.put(sitenoStr,siteContent);
});
参考文章:
1.Mybatis返回Map,List
小额赞助
本人提供免费与付费咨询服务,感谢您的支持!赞助请发邮件通知,方便公布您的善意!
**光 3.01 元
Sun 3.00 元
bibichuan 3.00 元
微信公众号
广告位
诚心邀请广大金主爸爸洽谈合作
每日一省
isNaN 和 Number.isNaN 函数的区别?

1.函数 isNaN 接收参数后,会尝试将这个参数转换为数值,任何不能被转换为数值的的值都会返回 true,因此非数字值传入也会返回 true ,会影响 NaN 的判断。

2.函数 Number.isNaN 会首先判断传入参数是否为数字,如果是数字再继续判断是否为 NaN ,不会进行数据类型的转换,这种方法对于 NaN 的判断更为准确。

每日二省
为什么0.1+0.2 ! == 0.3,如何让其相等?

一个直接的解决方法就是设置一个误差范围,通常称为“机器精度”。对JavaScript来说,这个值通常为2-52,在ES6中,提供了Number.EPSILON属性,而它的值就是2-52,只要判断0.1+0.2-0.3是否小于Number.EPSILON,如果小于,就可以判断为0.1+0.2 ===0.3。

每日三省
== 操作符的强制类型转换规则?

1.首先会判断两者类型是否**相同,**相同的话就比较两者的大小。

2.类型不相同的话,就会进行类型转换。

3.会先判断是否在对比 null 和 undefined,是的话就会返回 true。

4.判断两者类型是否为 string 和 number,是的话就会将字符串转换为 number。

5.判断其中一方是否为 boolean,是的话就会把 boolean 转为 number 再进行判断。

6.判断其中一方是否为 object 且另一方为 string、number 或者 symbol,是的话就会把 object 转为原始类型再进行判断。

每日英语
Happiness is time precipitation, smile is the lonely sad.
幸福是年华的沉淀,微笑是寂寞的悲伤。