mybatis foreach批量insert时遇到异常,如何彻底解决这个长尾问题?

2026-04-19 16:051阅读0评论SEO资讯
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1465个文字,预计阅读时间需要6分钟。

mybatis foreach批量insert时遇到异常,如何彻底解决这个长尾问题?

系统出现异常:org.springframework.jdbc.BadSqlGrammarException异常。

异常

org.springframework.jdbc.BadSqlGrammarException: ### Error updating database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'INSERT INTO t_user_role(userid,roleid)VALUES(1,3) ; INSERT INTO t_user_ro' at line 3 ### The error may involve defaultParameterMap ### The error occurred while setting parameters ### SQL: INSERT INTO t_user_role(userid,roleid)VALUES(?,?) ; INSERT INTO t_user_role(userid,roleid)VALUES(?,?) ; INSERT INTO t_user_role(userid,roleid)VALUES(?,?) ### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'INSERT INTO t_user_role(userid,roleid)VALUES(1,3) ; INSERT INTO t_user_ro' at line 3 ; bad SQL grammar []; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'INSERT INTO t_user_role(userid,roleid)VALUES(1,3) ; INSERT INTO t_user_ro' at line 3 at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:231) at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:73) at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:73) at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:371) at com.sun.proxy.$Proxy13.insert(Unknown Source) at org.mybatis.spring.SqlSessionTemplate.insert(SqlSessionTemplate.java:240) at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:51) at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:52) at com.sun.proxy.$Proxy14.addRoles(Unknown Source) at com.atguigu.atcrowdfunding.manager.service.impl.UserServiceImpl.addRoles(UserServiceImpl.java:139) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) at com.sun.proxy.$Proxy17.addRoles(Unknown Source) at com.atguigu.atcrowdfunding.manager.controller.UserController.doAddRoles(UserController.java:271) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:175) at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:446) at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:434) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:945) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:876) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:931) at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:833) at javax.servlet.localhost:3306/atcrowdfunding?allowMultiQueries=true&rewriteBatchedStatements=true&useUnicode=true&characterEncoding=utf8

补充:Mybatis foreach嵌套 批量insert map list数据

方式一:

以Teacher和Students为例 ,两者为一对多关系:**

Teacher 实体类

private String tid; private String tName; private List<Student> studentList; public String getTid() { return tid; } public void setTid(String tid) { this.tid = tid; } public String gettName() { return tName; } public void settName(String tName) { this.tName = tName; } public List<Student> getStudentList() { return studentList; } public void setStudentList(List<Student> studentList) { this.studentList = studentList; }

Student实体类

private String sid; private String sName; public String getSid() { return sid; } public void setSid(String sid) { this.sid = sid; } public String getsName() { return sName; } public void setsName(String sName) { this.sName = sName; }

应用场景 :在老师的service层批量插入老师数据

int nums=1000; //定义teacher list List<Teacher> teaList=new ArrayList<Teacher>(); //数据是通过excel读取的 此处模拟循环读取excel row数据 for(int rowi=0;rowi<nums;rowi++){ Teacher teacher=new Teacher(); teacher.settName("xxx"); List<Student> stuList=new ArrayList<Student>(); Student student=new Student(); //此处获取Students集合 for(xxx){ stuList.add(student); } //把student集合和teacher绑定 teacher.setStudentList(stuList); //把teacher放入list teaList.add(teacher); } // 批量插入老师数据 teacherMapper.batchInsertTeacher(teaList); //此时每个teacher对象都有返回的主键id值 //老师主键 对应一个list(学生信息) map Map<String,List<Student>> stuMap=new HashMap<>(); //填入数据 老师主键一对多学生信息 for(Teacher tea:teaList){ //非空判断 避免老师没有对应学生的情况(此处只进行逻辑处理 不考虑现实中老师没有学生) if(tea.getStudentList()!=null&&tea.getStudentList().size()>0){ stuMap.put(tea.getTid(),tea.getStudentList()); } } //调用学生service的批量保存学生方法 studentService.batchInsertStudent(stuMap);

student Mapper接口文件

int batchInsertStudent(@Param("stuMap") Map<String,List<Student>> stuMap);

student mapper.xml文件(写法一:)

<insert id="batchInsertStudent" parameterType="java.util.Map"> INSERT INTO bs_student (sid,sName,tid) values <foreach collection="stuMap.keys" index="key" item="itemKey" separator=","> <foreach collection="stuMap[itemKey]" index="index_list" item="list" separator="," > ( (select REPLACE(UUID(),'-','') AS sid) ,#{list.sName},#{itemKey} ) </foreach> </foreach> </insert>

student mapper.xml文件(写法二:)

<insert id="batchInsertStudent" >   INSERT INTO bs_student (sid,sName,tid)   <foreach collection="stuMap.keys" index="index" item="itemKey" separator="UNION ALL">   <foreach collection="stuMap[itemKey]" index="index_list" item="list" separator="UNION ALL">       (       SELECT       (select REPLACE(UUID(),'-','') AS sid)       ,#{list.sName}       ,#{itemKey}       FROM DUAL       )   </foreach>   </foreach> </insert>

stuMap:就是在接口中使用@Param(“stuMap”)标注了变量;

使用stuMap.keys可以取到所有的key,遍历。

内层循环中使用stuMap[itemKey]类似stuMap.get(“key”)取当前key对应的value值。由于value是list所以还需要遍历。

结果保存成功。再次膜拜强大的Mybatis。

mybatis foreach批量insert时遇到异常,如何彻底解决这个长尾问题?

至此 成功插入student数据。

方式二(推荐):

自定义类

class EnclosingType{ private String uuid; private List<ElementType> elements; }

class ElementType{ String a; String b; (...) }

Mapper.xml(方法一)

<mapper namespace="my.example.ElementType"> <insert id="insertElements" parameterType="EnclosingType"> INSERT INTO table1(enclosingTypeId,column_a,column_b) VALUES <foreach collection="elements" index="index" item="list" separator=","> ( #{uuid,jdbcType=VARCHAR} ,#{list.a,jdbcType=VARCHAR} ,#{list.b,jdbcType=VARCHAR} ) </foreach> </insert> </mapper>

Mapper.xml(方法二)

<mapper namespace="my.example.ElementType"> <insert id="insertElements" parameterType="EnclosingType"> INSERT INTO table1(enclosingTypeId,column_a,column_b) <foreach collection="elements" index="index" item="list" separator="union all"> ( select #{uuid,jdbcType=VARCHAR} ,#{list.a,jdbcType=VARCHAR} ,#{list.b,jdbcType=VARCHAR} from dual ) </foreach> </insert> </mapper>

以上为个人经验,希望能给大家一个参考,也希望大家多多支持易盾网络。如有错误或未考虑完全的地方,望不吝赐教。

本文共计1465个文字,预计阅读时间需要6分钟。

mybatis foreach批量insert时遇到异常,如何彻底解决这个长尾问题?

系统出现异常:org.springframework.jdbc.BadSqlGrammarException异常。

异常

org.springframework.jdbc.BadSqlGrammarException: ### Error updating database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'INSERT INTO t_user_role(userid,roleid)VALUES(1,3) ; INSERT INTO t_user_ro' at line 3 ### The error may involve defaultParameterMap ### The error occurred while setting parameters ### SQL: INSERT INTO t_user_role(userid,roleid)VALUES(?,?) ; INSERT INTO t_user_role(userid,roleid)VALUES(?,?) ; INSERT INTO t_user_role(userid,roleid)VALUES(?,?) ### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'INSERT INTO t_user_role(userid,roleid)VALUES(1,3) ; INSERT INTO t_user_ro' at line 3 ; bad SQL grammar []; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'INSERT INTO t_user_role(userid,roleid)VALUES(1,3) ; INSERT INTO t_user_ro' at line 3 at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:231) at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:73) at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:73) at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:371) at com.sun.proxy.$Proxy13.insert(Unknown Source) at org.mybatis.spring.SqlSessionTemplate.insert(SqlSessionTemplate.java:240) at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:51) at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:52) at com.sun.proxy.$Proxy14.addRoles(Unknown Source) at com.atguigu.atcrowdfunding.manager.service.impl.UserServiceImpl.addRoles(UserServiceImpl.java:139) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) at com.sun.proxy.$Proxy17.addRoles(Unknown Source) at com.atguigu.atcrowdfunding.manager.controller.UserController.doAddRoles(UserController.java:271) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:175) at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:446) at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:434) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:945) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:876) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:931) at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:833) at javax.servlet.localhost:3306/atcrowdfunding?allowMultiQueries=true&rewriteBatchedStatements=true&useUnicode=true&characterEncoding=utf8

补充:Mybatis foreach嵌套 批量insert map list数据

方式一:

以Teacher和Students为例 ,两者为一对多关系:**

Teacher 实体类

private String tid; private String tName; private List<Student> studentList; public String getTid() { return tid; } public void setTid(String tid) { this.tid = tid; } public String gettName() { return tName; } public void settName(String tName) { this.tName = tName; } public List<Student> getStudentList() { return studentList; } public void setStudentList(List<Student> studentList) { this.studentList = studentList; }

Student实体类

private String sid; private String sName; public String getSid() { return sid; } public void setSid(String sid) { this.sid = sid; } public String getsName() { return sName; } public void setsName(String sName) { this.sName = sName; }

应用场景 :在老师的service层批量插入老师数据

int nums=1000; //定义teacher list List<Teacher> teaList=new ArrayList<Teacher>(); //数据是通过excel读取的 此处模拟循环读取excel row数据 for(int rowi=0;rowi<nums;rowi++){ Teacher teacher=new Teacher(); teacher.settName("xxx"); List<Student> stuList=new ArrayList<Student>(); Student student=new Student(); //此处获取Students集合 for(xxx){ stuList.add(student); } //把student集合和teacher绑定 teacher.setStudentList(stuList); //把teacher放入list teaList.add(teacher); } // 批量插入老师数据 teacherMapper.batchInsertTeacher(teaList); //此时每个teacher对象都有返回的主键id值 //老师主键 对应一个list(学生信息) map Map<String,List<Student>> stuMap=new HashMap<>(); //填入数据 老师主键一对多学生信息 for(Teacher tea:teaList){ //非空判断 避免老师没有对应学生的情况(此处只进行逻辑处理 不考虑现实中老师没有学生) if(tea.getStudentList()!=null&&tea.getStudentList().size()>0){ stuMap.put(tea.getTid(),tea.getStudentList()); } } //调用学生service的批量保存学生方法 studentService.batchInsertStudent(stuMap);

student Mapper接口文件

int batchInsertStudent(@Param("stuMap") Map<String,List<Student>> stuMap);

student mapper.xml文件(写法一:)

<insert id="batchInsertStudent" parameterType="java.util.Map"> INSERT INTO bs_student (sid,sName,tid) values <foreach collection="stuMap.keys" index="key" item="itemKey" separator=","> <foreach collection="stuMap[itemKey]" index="index_list" item="list" separator="," > ( (select REPLACE(UUID(),'-','') AS sid) ,#{list.sName},#{itemKey} ) </foreach> </foreach> </insert>

student mapper.xml文件(写法二:)

<insert id="batchInsertStudent" >   INSERT INTO bs_student (sid,sName,tid)   <foreach collection="stuMap.keys" index="index" item="itemKey" separator="UNION ALL">   <foreach collection="stuMap[itemKey]" index="index_list" item="list" separator="UNION ALL">       (       SELECT       (select REPLACE(UUID(),'-','') AS sid)       ,#{list.sName}       ,#{itemKey}       FROM DUAL       )   </foreach>   </foreach> </insert>

stuMap:就是在接口中使用@Param(“stuMap”)标注了变量;

使用stuMap.keys可以取到所有的key,遍历。

内层循环中使用stuMap[itemKey]类似stuMap.get(“key”)取当前key对应的value值。由于value是list所以还需要遍历。

结果保存成功。再次膜拜强大的Mybatis。

mybatis foreach批量insert时遇到异常,如何彻底解决这个长尾问题?

至此 成功插入student数据。

方式二(推荐):

自定义类

class EnclosingType{ private String uuid; private List<ElementType> elements; }

class ElementType{ String a; String b; (...) }

Mapper.xml(方法一)

<mapper namespace="my.example.ElementType"> <insert id="insertElements" parameterType="EnclosingType"> INSERT INTO table1(enclosingTypeId,column_a,column_b) VALUES <foreach collection="elements" index="index" item="list" separator=","> ( #{uuid,jdbcType=VARCHAR} ,#{list.a,jdbcType=VARCHAR} ,#{list.b,jdbcType=VARCHAR} ) </foreach> </insert> </mapper>

Mapper.xml(方法二)

<mapper namespace="my.example.ElementType"> <insert id="insertElements" parameterType="EnclosingType"> INSERT INTO table1(enclosingTypeId,column_a,column_b) <foreach collection="elements" index="index" item="list" separator="union all"> ( select #{uuid,jdbcType=VARCHAR} ,#{list.a,jdbcType=VARCHAR} ,#{list.b,jdbcType=VARCHAR} from dual ) </foreach> </insert> </mapper>

以上为个人经验,希望能给大家一个参考,也希望大家多多支持易盾网络。如有错误或未考虑完全的地方,望不吝赐教。