1. 有关sql - select 书写细则:
https://www.cnblogs.com/EasonJim/p/7057575.html
2. mybatis 中大于等于和小于等于的写法
第一种写法(1): 原符号 < <= > >= & ' " 替换符号 < <= > >= & ' " 例如:sql如下: create_date_time >= #{startTime} and create_date_time <= #{endTime} 第二种写法(2): 大于等于 <![CDATA[ >= ]]> 小于等于 <![CDATA[ <= ]]> 例如:sql如下: create_date_time <![CDATA[ >= ]]> #{startTime} and create_date_time <![CDATA[ <= ]]> #{endTime}
3. 数据库连接配置如下 ,如果缺少?Unicode=true&characterEncoding=UTF-8 这些有关中文的查询会在执行的时候返回 0 条数据,但是实际上通过语句可以在navacit 中查询出来 :
url: jdbc:mysql://localhost:3306/test?Unicode=true&characterEncoding=UTF-8
4.写有关in 的语句的时候的报的错误
问题背景:
在Dao中使用MyBatis进行查询操作,参数是传的一个List:studentNameList,但是在执行查询的时候报错,具体日志如下:
- com.chenzhou.base.mybatis.IbatisSystemException: SqlSession operation; nested exception is org.apache.ibatis.exceptions.PersistenceException:
- ### Error querying database. Cause: org.apache.ibatis.binding.BindingException: Parameter 'studentNameList' not found. Available parameters are [list]
- ### Cause: org.apache.ibatis.binding.BindingException: Parameter 'studentNameList' not found. Available parameters are [list]
- at com.chenzhou.base.mybatis.SqlSessionTemplate.wrapException(SqlSessionTemplate.java:341)
- at com.chenzhou.base.mybatis.SqlSessionTemplate.execute(SqlSessionTemplate.java:127)
- at com.chenzhou.base.mybatis.SqlSessionTemplate.execute(SqlSessionTemplate.java:106)
- at com.chenzhou.base.mybatis.SqlSessionTemplate.selectOne(SqlSessionTemplate.java:138)
- at com.chenzhou.dao.GenericMybatisDao.count(GenericMybatisDao.java:306)
- at com.chenzhou.cds.ps.dao.impl.StudentDao.getStudentCount(StudentDao.java:42)
- at com.chenzhou.cds.ps.dao.impl.StudentDao$$FastClassByCGLIB$$8819e766.invoke(<generated>)
- at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:191)
- at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:689)
- at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
- at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:80)
- at com.chenzhou.util.LogUtil.doMethodInfo(LogUtil.java:85)
- at com.chenzhou.util.LogUtil.doDebugMethodLog(LogUtil.java:36)
- at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
- at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
- at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
- at java.lang.reflect.Method.invoke(Method.java:597)
- at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:621)
- at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:610)
- at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:65)
- at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
- at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:55)
- at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
- at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
- at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
- at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:90)
- at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
- at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:622)
- at com.chenzhou.cds.ps.dao.impl.StudentDao$$EnhancerByCGLIB$$d4fcf513.getStudentCount(<generated>)
- at com.chenzhou.ps.dao.StudentDaoTest.testgetStudentCount(StudentDaoTest.java:44)
- ……
- public void testgetStudentCount(){
- List<String> studentNameList = new ArrayList<String>();
- studentNameList.add("chenzhou");
- studentNameList.add("zhangsan");
- studentNameList.add("lisi");
- int count = studentDao.getStudentCount(studentNameList);
- System.out.println(count);
- }
studentDao中的getStudentCount方法代码如下:
- public int getStudentCount(List<String> studentNameList){
- return super.count("getStudentCount", studentNameList);
- }
MyBatis mapper.xml定义如下:
- <!-- 查询学生数量 -->
- <select id="Student.getStudentCount" parameterType="java.util.List" resultType="java.lang.Integer">
- <![CDATA[
- SELECT
- COUNT(*)
- FROM
- t_student WHERE 1=1
- ]]>
- <if test="studentNameList != null">
- AND student_name in
- <foreach collection="studentNameList" item="item" open="(" separator="," close=")">
- #{item}
- </foreach>
- </if>
- </select>
根据报错日志分析,是MyBatis在解析xml时找不到其中声明的studentNameList,但是在Dao中明明传的参数就是studentNameList,怎么会报错呢?
查询了一下MyBatis官方的说明文档,终于找到了原因,在里有一段说明:
写道
注意 你可以传递一个 List 实例或者数组作为参数对象传给 MyBatis。当你这么做的时 候,MyBatis 会自动将它包装在一个 Map 中,用名称在作为键。List 实例将会以“list” 作为键,而数组实例将会以“array”作为键。
因为我传的参数只有一个,而且传入的是一个List集合,所以mybatis会自动封装成Map<"list",studentNameList>。在解析的时候会通过“list”作为Map的key值去寻找。但是我在xml中却声明成studentNameList了,所以自然会报错找不到。
解决办法:
第一种就是修改mapper.xml中foreach标签内容,把studentNameList修改为list
- <if test="list != null">
- AND student_name in
- <foreach collection="list" item="item" open="(" separator="," close=")">
- #{item}
- </foreach>
- </if>
不过这种方式我个人不太建议,因为以后如果要扩展该方法,增加集合参数的时候,还得修改xml中的内容。
第二种方式,修改dao中的参数传入方式,手动封装成map,然后把map当参数传进去
Dao方法修改为:
- public int getStudentCount(List<String> studentNameList){
- //把参数手动封装在Map中
- Map<String, Object> map = new HashMap<String, Object>();
- map.put("studentNameList", studentNameList);
- return super.count("getStudentCount", map);
- }
然后修改mapper.xml中的parameterType类型为Map
- <!--注意下面的parameterType类型必须修改为Map类型,foreach中引用的List名称不用改变-->
- <select id="Student.getStudentCount" parameterType="java.util.Map" resultType="java.lang.Integer">
- <![CDATA[
- SELECT
- COUNT(*)
- FROM
- t_student WHERE 1=1
- ]]>
- <if test="studentNameList != null">
- AND student_name in
- <foreach collection="studentNameList" item="item" open="(" separator="," close=")">
- #{item}
- </foreach>
- </if>
- </select>
修改完后,重新执行了一下测试用例,测试通过。
5. 注解方式的根据传入参数动态插入数据库数据(@InsertProvider)
第二种写法:
public String insertTaskSellByParam(TaskSell tas){
SQL sql = new SQL(); sql.INSERT_INTO("t_task_sell"); if(StringUtils.isNotBlank(tas.getTaskNo())){ sql.VALUES("task_no", "#{taskNo,jdbcType=VARCHAR}"); } if(tas.getTaskTypeId() >0){ sql.VALUES("task_type_id", "#{taskTypeId,jdbcType=INTEGER}"); } if(StringUtils.isNotBlank(tas.getEndTime())){ sql.VALUES("end_time", "#{endTime,jdbcType=TIMESTAMP}"); } if(StringUtils.isNotBlank(tas.getUserPrompt())){ sql.VALUES("user_prompt", "#{userPrompt,jdbcType=VARCHAR}"); } if(StringUtils.isNotBlank(tas.getCreateTime())){ sql.VALUES("create_time", "#{createTime,jdbcType=VARCHAR}"); } if(tas.getState()>0){ sql.VALUES("state", "#{state,jdbcType=INTEGER}"); } return sql.toString(); }6.select 查询通过map.xml 实现的,不用定义<resultMap></resultMap>
<select id="SelectBySelective" resultMap="BaseResultMap"
parameterType="com.back.web.domain.SellCategory"> select id,name from t_sell_category where 1=1 <if test="status != null"> and status = #{status} </if> and is_del= 1 </select>8.mybatis 一对多,多对多等的使用
https://blog.csdn.net/desert568/article/details/79079151
自己实践列子:
实体类:
@JsonIgnoreProperties(value="{handler}")
public class WetBucketImg implements Serializable{ private static final long serialVersionUID = 1L;private int id;
private double longitude; // 经度 private double latitude; // 纬度 private String reNo; // 调研编号 private String url; // 图片位置地址}
@JsonIgnoreProperties(value={"handler"})
public class WetBucketResearch implements Serializable{/**
* serialVersionUID:TODO * @author 卫玉珍 */ private static final long serialVersionUID = 1L;private int id;
private String opertorPhone;// 操作人电话 private int villageId; // 小区Id private Set<WetBucketImg> imgSet; // 图片set 实列}
Mapper注注解:
@Select(" select * from t_wet_bucket_research where re_no = #{reNo} ")
@Results({ @Result(column="re_no",property="reNo"), @Result(column="re_no",property="imgSet", many=@Many( select="com.back.web.mapper.WetBucketResearchMapper.findbucketImgByReNo", fetchType=FetchType.LAZY )) }) public WetBucketResearch findBucketResearchByReNo(WetBucketResearch po); @Select("select * from t_wet_bucket_img where re_no = #{reNo}") public List<WetBucketImg> findbucketImgByReNo(WetBucketImg po);9. mybatis 包扫描,
ypeAliases
类型别名是为 Java 类型命名的一个短的名字。它只和 XML 配置有关,存在的意义仅在于用来减少类完全限定名的冗余。<typeAliases>
<typeAlias type="com.zpc.mybatis.pojo.User" alias="User"/> </typeAliases> 缺点:每个pojo类都要去配置。 解决方案:使用扫描包,扫描指定包下的所有类,扫描之后的别名就是类名(不区分大小写),建议使用的时候和类名一致。<typeAliases>
<!--type:实体类的全路径。alias:别名,通常首字母大写--> <!--<typeAlias type="com.zpc.mybatis.pojo.User" alias="User"/>--> <package name="com.zpc.mybatis.pojo"/> </typeAliases> 在yml 配置文件如下mybatis:
typeAliasesPackage: com.test.domain mapperLocations: classpath:mapper/*.xml configuration: map-underscore-to-camel-case: true