MyBatis笔记(一)————PersistenceException产生与解决(考考你CRUD基础扎不扎实~)
(使用Eclipse,JDK1.7,MySQL数据库)
CRUD【VC/C++、HTML、Java、SQL、JSP、SSH、SSM等等的英语单词(看了很多遍都会忘记意思或读音,只知道大概用来干嘛的)】
为了方便“着急找答案”的同胞们,我将总结放置Top,若想看问题分析,可点击CSDN文章右侧“目录”找相应位置:
1.DAO配置(MyBatis)文件中:#{参数名}与DAO文件的@Param(参数名)的参数名字必须一致(区分大小写)
2.DAO配置文件中:在DAO中定义时要注意重名问题,因为id名不可重复,且DAO文件中定义的函数名就是配置文件的id名
3.两种解决方式:
一是:在emp数据表,empId必须有条数据,
二是:右击emp表,点击"设计表",接着点击"empId",下面会出现"自动递增",进行勾选即可4.设置了empId为主键,
若emp数据表里empId有为5记录,手动添加主键时赋值不可再赋值5(体现主键的唯一性)5.
(1)DAO配置文件中:若使用了foreach,参数名就要这样#{item值.Javabean属性}
(2)若用list批量删除,使用foreach时,参数名是#{item值.empId};
若用array批量删除,使用foreach时,参数名可以是#{item值}6.update语句注意:修改多个字段时,字段之间用","逗号相隔
7.resultMap的type名可以是全限定名"qiu.vo.Emp_TaskVo" 也可以是用typeAlias标签定义的alias别名值"ETaskVo"
PS:主要要看懂异常表示哪处出问题,才能对症下药
①
org.apache.ibatis.exceptions.PersistenceException:
### Error querying database. Cause: org.apache.ibatis.binding.BindingException: Parameter 'id' not found. Available parameters are [empName, 0, param1, param2]
### Cause: org.apache.ibatis.binding.BindingException: Parameter 'id' not found. Available parameters are [empName, 0, param1, param2]
at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:150)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:141)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:77)
at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:82)
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:59)
at com.sun.proxy.$Proxy0.empByIdAndName(Unknown Source)
at qiu.action.MyBatisXmlQ.main(MyBatisXmlQ.java:38)
Caused by: org.apache.ibatis.binding.BindingException: Parameter 'id' not found. Available parameters are [empName, 0, param1, param2]
at org.apache.ibatis.binding.MapperMethod$ParamMap.get(MapperMethod.java:202)
at org.apache.ibatis.reflection.wrapper.MapWrapper.get(MapWrapper.java:45)
at org.apache.ibatis.reflection.MetaObject.getValue(MetaObject.java:122)
at org.apache.ibatis.executor.BaseExecutor.createCacheKey(BaseExecutor.java:219)
at org.apache.ibatis.executor.CachingExecutor.createCacheKey(CachingExecutor.java:146)
at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:82)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:148)
... 6 more
我的代码:
————EmpVo类文件
private Integer empId;
private String empName;
private String password;
private int age;
private String sex;
....setter and getter....
————EmpDAO接口文件
List<EmpVo> listemp();//接口,要定义方法,而不是变量,也不能static final,只能public和abstract
EmpVo empById(int id);//按id查询返回一条记录
//带注解的参数,若查不了记录,要么xml配置文件有问题,要么properties文件的URL没有加上"转码代码"
EmpVo empByName(@Param("name") String empname);
EmpVo empByIdAndName(int id,@Param("empName") String empname);
————EmpDAO.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<!-- mybatis的dtd文件 -->
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace属性: 用于指定指向那个接口 -->
<mapper namespace="qiu.mapper.EmpDAO">
<!--select标签都对应接口中的一个方法,
id属性:指定接口中具体的方法名 , 其值必须唯一
resultType:执行sql返回的结果类型,也就是指定接口中对应方法的List的尖括号里的Javabean
xml的文件名称必须与接口名称相同,并且必须在同一个包中
-->
<select id="listemp" resultType="qiu.vo.EmpVo">
<!--
格式化sql语句的标签;
处理>,<等特殊符号时必须加上CDATA标记。
-->
<![CDATA[
select * from Emp;
]]>
</select>
<select id="empById" parameterType="int" resultType="empVo">
<!--
当方法的参数是String时,调用该方法之后,若jdbc的driverUrl
没有加useUnicode=true&characterEncoding=UTF-8,
则查找不到对应记录,因为传于数据库时没有转码。
按主键查找指定的员工资料,如果查询结果只有一条记录返回Javabean,否则返回List集合。
-->
<![CDATA[
select * from Emp where empid=#{id};
]]>
</select>
<select id="empByName" parameterType="string" resultType="eMpVo">
<!--
查询语句,表名和字段名都不区分大小写,
#加{ }的大括号里的名字
可以是对应 id=" empByName " 的empByName方法的参数名
也可以是对应 id=" empByName " 的empByName方法的参数注解
-->
<![CDATA[
select * from Emp where empname=#{name};
]]>
</select>
<select id="empByIdAndName" resultType="eMpVo">
<![CDATA[
select * from Emp where empid=#{id} and EMPName=#{EmpnamE};
]]>
</select>
</mapper>
————jdbc.properties文件:
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.driverUrl=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8
jdbc.user=root
jdbc.password=123
————mybatisQ.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<!-- mybatis核心配置文件的dtd -->
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 引用jdbc配置文件 -->
<properties resource="jdbc.properties"/>
<settings>
<setting name="cacheEnabled" value="true" />
<setting name="useColumnLabel" value="true" />
<setting name="useGeneratedKeys" value="true" />
<setting name="mapUnderscoreToCamelCase" value="true" />
<!-- 打印SQL语句 -->
<setting name="logImpl" value="STDOUT_LOGGING" />
</settings>
<typeAliases>
<!-- 配置JAVABEAN的短名称,使用时,首字母(其实别名都)不区分大小写
alias=别名
type=类的全路径(包含了包名)
-->
<typeAlias alias="EmpVo" type="qiu.vo.EmpVo"></typeAlias>
</typeAliases>
<!--环境配置,配置的是开发者模式(development),工作模式(work) -->
<environments default="development">
<environment id="development">
<!-- 声明jdbc事务处理,type=[JDBC、MANAGED] -->
<transactionManager type="JDBC"></transactionManager>
<!-- 数据源:数据库连接池 ,type=[UNPOOLED、POOLED、JDNI]-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.driverUrl}"/>
<property name="username" value="${jdbc.user}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="qiu/mapper/EmpDAO.xml"/>
</mappers>
</configuration>
————某个测试类文件:
public static void main(String[] args) {
try{
// 读取mybatis.xml配置文件
InputStream configuration=Resources.getResourceAsStream("mybatisQ.xml");
// 由SqlSessionFactoryBuilder和mybatis.xml配置文件获取SqlSessionFactory工厂
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(configuration);
// 由sqlSessionFactory打开连接获取SqlSession
SqlSession sqlSession=sqlSessionFactory.openSession();
// 由SqlSession获取映射器接口EmpDAO
EmpDAO empDAO=sqlSession.getMapper(EmpDAO.class);
// EmpVo empVo=empDAO.empById(2);
EmpVo empVo=empDAO.empByIdAndName(2, "王昭君");
// EmpVo empVo=empDAO.empByName("西施");
System.out.println(empVo);
}catch(Exception e){
e.printStackTrace();
}
}
错就是由这产生的(异常前,将“#{}的id、EmpnamE”看作“注解”【要是有注解,程序自动setter和getter方法】,因为没有"id、EmpnamE"这样的注解且程序找不到,才会报异常):
复习:
其中还要注意的是 "有注解empId就一定要用,若用参数名empid,会被程序看作注解,而非参数名;#{}"里的名字必须与注解@Param("")的名字一致(区分大小写),所以解决:
②
org.apache.ibatis.exceptions.PersistenceException:
### Error building SqlSession.
### The error may exist in qiu/mapper/EmpDAO.xml
### Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: org.apache.ibatis.builder.BuilderException: Error parsing Mapper XML. Cause: java.lang.IllegalArgumentException: Mapped Statements collection already contains value for qiu.mapper.EmpDAO.empVoById
at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:80)
at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:64)
at qiu.base.DBConnQ.getSession(DBConnQ.java:16)
at qiu.action.EmpTestQ.main(EmpTestQ.java:14)
Caused by: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: org.apache.ibatis.builder.BuilderException: Error parsing Mapper XML. Cause: java.lang.IllegalArgumentException: Mapped Statements collection already contains value for qiu.mapper.EmpDAO.empVoById
at org.apache.ibatis.builder.xml.XMLConfigBuilder.parseConfiguration(XMLConfigBuilder.java:121)
at org.apache.ibatis.builder.xml.XMLConfigBuilder.parse(XMLConfigBuilder.java:99)
at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:78)
... 3 more
Caused by: org.apache.ibatis.builder.BuilderException: Error parsing Mapper XML. Cause: java.lang.IllegalArgumentException: Mapped Statements collection already contains value for qiu.mapper.EmpDAO.empVoById
at org.apache.ibatis.builder.xml.XMLMapperBuilder.configurationElement(XMLMapperBuilder.java:120)
at org.apache.ibatis.builder.xml.XMLMapperBuilder.parse(XMLMapperBuilder.java:92)
at org.apache.ibatis.builder.annotation.MapperAnnotationBuilder.loadXmlResource(MapperAnnotationBuilder.java:173)
at org.apache.ibatis.builder.annotation.MapperAnnotationBuilder.parse(MapperAnnotationBuilder.java:124)
at org.apache.ibatis.binding.MapperRegistry.addMapper(MapperRegistry.java:72)
at org.apache.ibatis.binding.MapperRegistry.addMappers(MapperRegistry.java:97)
at org.apache.ibatis.binding.MapperRegistry.addMappers(MapperRegistry.java:105)
at org.apache.ibatis.session.Configuration.addMappers(Configuration.java:737)
at org.apache.ibatis.builder.xml.XMLConfigBuilder.mapperElement(XMLConfigBuilder.java:364)
at org.apache.ibatis.builder.xml.XMLConfigBuilder.parseConfiguration(XMLConfigBuilder.java:119)
... 5 more
Caused by: java.lang.IllegalArgumentException: Mapped Statements collection already contains value for qiu.mapper.EmpDAO.empVoById
at org.apache.ibatis.session.Configuration$StrictMap.put(Configuration.java:872)
at org.apache.ibatis.session.Configuration$StrictMap.put(Configuration.java:844)
at org.apache.ibatis.session.Configuration.addMappedStatement(Configuration.java:668)
at org.apache.ibatis.builder.MapperBuilderAssistant.addMappedStatement(MapperBuilderAssistant.java:302)
at org.apache.ibatis.builder.xml.XMLStatementBuilder.parseStatementNode(XMLStatementBuilder.java:109)
at org.apache.ibatis.builder.xml.XMLMapperBuilder.buildStatementFromContext(XMLMapperBuilder.java:135)
at org.apache.ibatis.builder.xml.XMLMapperBuilder.buildStatementFromContext(XMLMapperBuilder.java:128)
at org.apache.ibatis.builder.xml.XMLMapperBuilder.configurationElement(XMLMapperBuilder.java:118)
... 14 more
由这导致:( , 下两张图分别是:EmpDAO.xml 和 EmpDAO.java)
所以解决(没有注解时,xml里的#{age或sex},会让程序自动找empVoById方法的参数这Javabean对象里的age或sex属性或变量;若有注解,通过#{empVo.xxx},找注解对应的参数这Javabean对象里的xxx属性或变量;错误纠正,只要将第二个"empVoById"改为"empVoParamById",即可):
③
Exception in thread "main" org.apache.ibatis.exceptions.PersistenceException:
### Error updating database. Cause: java.sql.SQLException: Field 'empId' doesn't have a default value
### The error may involve qiu.mapper.EmpDAO.addEmp-Inline
### The error occurred while setting parameters
### SQL: insert into emp(empName,password,age,sex,job,remark) values(?,?,?,?,?,?);
### Cause: java.sql.SQLException: Field 'empId' doesn't have a default value
at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:200)
at org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession.java:185)
at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:57)
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:59)
at com.sun.proxy.$Proxy0.addEmp(Unknown Source)
at qiu.action.EmpTestQ.main(EmpTestQ.java:31)
Caused by: java.sql.SQLException: Field 'empId' doesn't have a default value
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:964)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3973)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3909)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2527)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2680)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2490)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1858)
at com.mysql.jdbc.PreparedStatement.execute(PreparedStatement.java:1197)
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.apache.ibatis.logging.jdbc.PreparedStatementLogger.invoke(PreparedStatementLogger.java:59)
at com.sun.proxy.$Proxy2.execute(Unknown Source)
at org.apache.ibatis.executor.statement.PreparedStatementHandler.update(PreparedStatementHandler.java:46)
at org.apache.ibatis.executor.statement.RoutingStatementHandler.update(RoutingStatementHandler.java:74)
at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:50)
at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:117)
at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:76)
at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:198)
... 5 more
前提:empId是主键但不是"自动递增"。在我的代码中,除了empId字段都新增了值,运行之后报了这异常,所以解决:【若联系“主键回填”并同样的前提,也会报这样的异常,所以解决:MyBatis笔记(二)————PersistenceException产生与解决 和 MyBatis的高级使用(主键回填)——②自定义回填】
一是:给empId也赋值,二是:(右击emp表,点击"设计表",接着点击"empId",下面会出现"自动递增",进行勾选即可)
④
Exception in thread "main" org.apache.ibatis.exceptions.PersistenceException:
### Error updating database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '5' for key 'PRIMARY'
### The error may involve qiu.mapper.EmpDAO.addEmp-Inline
### The error occurred while setting parameters
### SQL: insert into emp(empId,empName,password,age,sex,job,remark) values(?,?,?,?,?,?,?);
### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '5' for key 'PRIMARY'
at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:200)
at org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession.java:185)
at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:57)
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:59)
at com.sun.proxy.$Proxy0.addEmp(Unknown Source)
at qiu.action.EmpTestQ.main(EmpTestQ.java:32)
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '5' for key 'PRIMARY'
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:425)
at com.mysql.jdbc.Util.getInstance(Util.java:408)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:935)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3973)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3909)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2527)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2680)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2490)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1858)
at com.mysql.jdbc.PreparedStatement.execute(PreparedStatement.java:1197)
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.apache.ibatis.logging.jdbc.PreparedStatementLogger.invoke(PreparedStatementLogger.java:59)
at com.sun.proxy.$Proxy2.execute(Unknown Source)
at org.apache.ibatis.executor.statement.PreparedStatementHandler.update(PreparedStatementHandler.java:46)
at org.apache.ibatis.executor.statement.RoutingStatementHandler.update(RoutingStatementHandler.java:74)
at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:50)
at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:117)
at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:76)
at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:198)
... 5 more
由这导致(我的emp表的empId是能“自动递增”的主键,前提:已经有了empId为5的记录):
EmpDAO配置文件:
<insert id="addEmp" parameterType="qiu.vo.EmpVo" >
<![CDATA[
insert into emp(empId,empName,password,age,sex,job,remark) values(#{empId},#{empName},#{password},#{age},#{sex},#{job},#{remark});
]]>
</insert>
EmpDAO接口 : void addEmp(EmpVo empvo);
EmpTest类 : EmpDAO empBase=session.getMapper(EmpDAO.class); 以及下图
====改一下就好了====》
---------------------
再次出现相同异常,发现:
光看异常报错,就知道是"empId是主键,传empId的值"12"重复了",所以解决:将值改了!!!(有些异常,只看异常警告就可以找到错误,我在这超容易的就不一一列举了)
⑤
⑴
Exception in thread "main" org.apache.ibatis.exceptions.PersistenceException:
### Error updating database. Cause: org.apache.ibatis.binding.BindingException: Parameter 'empName' not found. Available parameters are [list, collection]
### The error may involve qiu.mapper.EmpDAO.batchAddEmp-Inline
### The error occurred while setting parameters
### SQL: insert into emp(empName,password,age,sex,job,status,remark) values (?,?,?,?,?,?,?) , (?,?,?,?,?,?,?)
### Cause: org.apache.ibatis.binding.BindingException: Parameter 'empName' not found. Available parameters are [list, collection]
at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:200)
at org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession.java:185)
at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:57)
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:59)
at com.sun.proxy.$Proxy0.batchAddEmp(Unknown Source)
at qiu.action.EmpTestQ.main(EmpTestQ.java:50)
Caused by: org.apache.ibatis.binding.BindingException: Parameter 'empName' not found. Available parameters are [list, collection]
at org.apache.ibatis.session.defaults.DefaultSqlSession$StrictMap.get(DefaultSqlSession.java:343)
at org.apache.ibatis.reflection.wrapper.MapWrapper.get(MapWrapper.java:45)
at org.apache.ibatis.reflection.MetaObject.getValue(MetaObject.java:122)
at org.apache.ibatis.scripting.defaults.DefaultParameterHandler.setParameters(DefaultParameterHandler.java:79)
at org.apache.ibatis.executor.statement.PreparedStatementHandler.parameterize(PreparedStatementHandler.java:93)
at org.apache.ibatis.executor.statement.RoutingStatementHandler.parameterize(RoutingStatementHandler.java:64)
at org.apache.ibatis.executor.SimpleExecutor.prepareStatement(SimpleExecutor.java:86)
at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:49)
at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:117)
at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:76)
at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:198)
... 5 more
你以为这个错和①的差不多???可不是哦!!!!差很多呐~~【情况:批量新增】,智慧的你发现了没,在EmpDAO配置文件中,用的foreach参数,局部变量为item,但是我的empName、password等属性没有加上“item”前缀
————EmpDAO接口中
//因为是传多个Javabean对象的批量新增,传值的是List类型的
void batchAddEmp(List<EmpVo> empvo);
————EmpTestQ类中main方法里:
SqlSession session=DBConnQ.getSession();
EmpDAO empBase=session.getMapper(EmpDAO.class);
EmpVo empVo=new EmpVo();
//3.批量新增(有自动递增,所以可以给empId自动赋值)
EmpVo empVo2=new EmpVo();
empVo.setEmpName("戴作拉");
empVo.setPassword("11");
empVo.setRemark("Why~嗯额");
empVo.setJob("后勤人员");
empVo.setAge(23);
empVo.setSex("男");
empVo2.setEmpName("李明远");
empVo2.setPassword("11");
empVo2.setRemark("How~嗯额");
empVo2.setJob("副经理");
empVo2.setAge(23);
empVo2.setSex("男");
List<EmpVo> eList=new ArrayList<EmpVo>();
eList.add(empVo);
eList.add(empVo2);
empBase.batchAddEmp(eList);
session.commit();//更新数据必须手动提交事务
所以解决(在MySQL里,可以批量新增):
<!-- 批量新增,parameterType为list -->
<insert id="batchAddEmp" parameterType="list" >
<![CDATA[
insert into emp(empName,password,age,sex,job,status,remark) values
]]>
<!-- foreach collection集合返回的是list类型 separator以逗号为分隔符 -->
<foreach item="item" collection="list" separator=",">
(#{item.empName},#{item.password},#{item.age},#{item.sex},#{item.job},#{item.status},#{item.remark})
</foreach>
</insert>
⑵
Exception in thread "main" org.apache.ibatis.exceptions.PersistenceException:
### Error updating database. Cause: java.lang.IllegalStateException: Type handler was null on parameter mapping for property '__frch_e_0'. It was either not specified and/or could not be found for the javaType (qiu.vo.EmpVo) : jdbcType (null) combination.
### Cause: java.lang.IllegalStateException: Type handler was null on parameter mapping for property '__frch_e_0'. It was either not specified and/or could not be found for the javaType (qiu.vo.EmpVo) : jdbcType (null) combination.
at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:200)
at org.apache.ibatis.session.defaults.DefaultSqlSession.delete(DefaultSqlSession.java:213)
at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:67)
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:59)
at com.sun.proxy.$Proxy0.delEmp_foreachList(Unknown Source)
at qiu.action.EmpTestQ.main(EmpTestQ.java:129)
Caused by: java.lang.IllegalStateException: Type handler was null on parameter mapping for property '__frch_e_0'. It was either not specified and/or could not be found for the javaType (qiu.vo.EmpVo) : jdbcType (null) combination.
at org.apache.ibatis.mapping.ParameterMapping$Builder.validate(ParameterMapping.java:119)
at org.apache.ibatis.mapping.ParameterMapping$Builder.build(ParameterMapping.java:104)
at org.apache.ibatis.builder.SqlSourceBuilder$ParameterMappingTokenHandler.buildParameterMapping(SqlSourceBuilder.java:123)
at org.apache.ibatis.builder.SqlSourceBuilder$ParameterMappingTokenHandler.handleToken(SqlSourceBuilder.java:67)
at org.apache.ibatis.parsing.GenericTokenParser.parse(GenericTokenParser.java:78)
at org.apache.ibatis.builder.SqlSourceBuilder.parse(SqlSourceBuilder.java:45)
at org.apache.ibatis.scripting.xmltags.DynamicSqlSource.getBoundSql(DynamicSqlSource.java:44)
at org.apache.ibatis.mapping.MappedStatement.getBoundSql(MappedStatement.java:292)
at org.apache.ibatis.executor.statement.BaseStatementHandler.<init>(BaseStatementHandler.java:64)
at org.apache.ibatis.executor.statement.PreparedStatementHandler.<init>(PreparedStatementHandler.java:40)
at org.apache.ibatis.executor.statement.RoutingStatementHandler.<init>(RoutingStatementHandler.java:46)
at org.apache.ibatis.session.Configuration.newStatementHandler(Configuration.java:558)
at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:48)
at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:117)
at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:76)
at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:198)
... 5 more
这个和(1)错在同一处【foreach标签】,以下为对应代码:
————interface EmpDAO
void delEmp_foreachList(List<EmpVo> empvo);//批量删除
————EmpDAO.xml
<delete id="delEmp_foreachList">
<![CDATA[
delete from emp where empid in
]]>
<foreach collection="list" open="(" close=")" item="e" separator=",">
#{e}
</foreach>
</delete>
————EmpTestQ测试类
SqlSession session=DBConnQ.getSession();
EmpDAO empBase=session.getMapper(EmpDAO.class);
EmpVo empVo=new EmpVo();
//批量删除
empVo.setEmpId(23);
EmpVo empVo2=new EmpVo();
EmpVo empVo3=new EmpVo();
List<EmpVo> empList=new ArrayList();//使用List批量删除
empVo2.setEmpId(24);
empVo3.setEmpId(25);
empList.add(empVo);
empList.add(empVo2);
empList.add(empVo3);
empBase.delEmp_foreachList(empList);
session.commit();//更新
错在==改==》...#{e.empId}...
————DAO.xml中
**************批量删除,除了collection为list,还可以collection为array*******************
<delete id="delEmp_foreachArray">
<![CDATA[
delete from emp where empid in
]]>
<!-- 使用Integer(不是Javabean),所以直接使用item这个别名 -->
<foreach collection="array" open="(" close=")" item="e" separator=",">
#{e}
</foreach>
</delete>
————DAO接口类
void delEmp_foreachArray(Integer[] empvo);//批量删除
————测试类
SqlSession session=DBConnQ.getSession();
EmpDAO empBase=session.getMapper(EmpDAO.class);
EmpVo empVo=new EmpVo();
Integer[] arr={23,24,25};//使用array批量删除
empBase.delEmp_foreachArray(arr);
session.commit();
⑥
打印结果:
==> Preparing: update emp set age=? and status=? where empid=?;
==> Parameters: 26(Integer), 1(Integer), 5(Integer)
<== Updates: 1
Committing JDBC Connection [com.mysql.jdbc.JDBC4Connection@2e2167]
==> Preparing: select * from Emp where empid=?;
==> Parameters: 5(Integer)
<== Columns: empId, empName, password, age, sex, job, status, remark
<== Row: 5, 周东阳, 1, null, 男, 开发人员, null, 无奈~嗯额
<== Total: 1
empId=5,empName=周东阳,password=1,age=0,sex=男,status=0,job=开发人员,remark=无奈~嗯额
由这导致:
经过上面新增查询的报错折腾,这么简单的修改也会犯错,这破心理呐!!
————EmpDAO接口
void undateEmp(EmpVo empvo);
————EmpDAO配置文件
<update id="undateEmp" parameterType="qiu.vo.EmpVo">
<![CDATA[
update emp set age=#{age} and status=#{status} where empid=#{empId};
]]>
</update>
————EmpTestQ类
//4.修改记录
empVo.setEmpId(5);
empVo.setAge(26);
empVo.setStatus(1);
empBase.undateEmp(empVo);
session.commit();//更新数据必须手动提交事务
empVo=empBase.empById(5);
System.out.println(empVo);
所以解决(Update修改多个字段,之间用","相隔,逻辑要正确,别定向思维,一上来就set值于Javabean对象) [/笑哭]:
补充:MyBatis“显示SQL语句”
⑦
Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
Class not found: org.jboss.vfs.VFS
JBoss 6 VFS API is not available in this environment.
Class not found: org.jboss.vfs.VirtualFile
VFS implementation org.apache.ibatis.io.JBoss6VFS is not valid in this environment.
Using VFS adapter org.apache.ibatis.io.DefaultVFS
Find JAR URL: file:/F:/ALL_Course/10Activiti/Ecli/MyBatisQ/build/classes/qiu/mapper
Not a JAR: file:/F:/ALL_Course/10Activiti/Ecli/MyBatisQ/build/classes/qiu/mapper
Reader entry: Emp_TaskDAO.class
Reader entry: Emp_TaskDAO.xml
Reader entry: EmpDAO.class
Reader entry: EmpDAO.xml
Listing file:/F:/ALL_Course/10Activiti/Ecli/MyBatisQ/build/classes/qiu/mapper
Find JAR URL: file:/F:/ALL_Course/10Activiti/Ecli/MyBatisQ/build/classes/qiu/mapper/Emp_TaskDAO.class
Not a JAR: file:/F:/ALL_Course/10Activiti/Ecli/MyBatisQ/build/classes/qiu/mapper/Emp_TaskDAO.class
Reader entry: 。。。qiu/mapper/Emp_TaskDAO。。java/lang/ObjectSignature'()Ljava/util/List<Lqiu/vo/Emp_TaskVo;>;listEmpTask
Find JAR URL: file:/F:/ALL_Course/10Activiti/Ecli/MyBatisQ/build/classes/qiu/mapper/Emp_TaskDAO.xml
Not a JAR: file:/F:/ALL_Course/10Activiti/Ecli/MyBatisQ/build/classes/qiu/mapper/Emp_TaskDAO.xml
Reader entry: <?xml version="1.0" encoding="UTF-8"?>
Find JAR URL: file:/F:/ALL_Course/10Activiti/Ecli/MyBatisQ/build/classes/qiu/mapper/EmpDAO.class
Not a JAR: file:/F:/ALL_Course/10Activiti/Ecli/MyBatisQ/build/classes/qiu/mapper/EmpDAO.class
Reader entry: <?xml version="1.0" encoding="UTF-8"?>
Checking to see if class qiu.mapper.Emp_TaskDAO matches criteria [is assignable to Object]
Checking to see if class qiu.mapper.EmpDAO matches criteria [is assignable to Object]
org.apache.ibatis.exceptions.PersistenceException:
### Error building SqlSession.
### The error may exist in qiu/mapper/Emp_TaskDAO.xml
### The error occurred while processing mapper_resultMap[ETMap]
### Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: org.apache.ibatis.builder.BuilderException: Error parsing Mapper XML. Cause: org.apache.ibatis.builder.BuilderException: Error resolving class. Cause: org.apache.ibatis.type.TypeException: Could not resolve type alias 'Emp_TaskVo'. Cause: java.lang.ClassNotFoundException: Cannot find class: Emp_TaskVo
at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:80)
at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:64)
at qiu.base.DBConnQ.getSession(DBConnQ.java:16)
at qiu.action.Emp_TaskTestQ.main(Emp_TaskTestQ.java:14)
Caused by: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: org.apache.ibatis.builder.BuilderException: Error parsing Mapper XML. Cause: org.apache.ibatis.builder.BuilderException: Error resolving class. Cause: org.apache.ibatis.type.TypeException: Could not resolve type alias 'Emp_TaskVo'. Cause: java.lang.ClassNotFoundException: Cannot find class: Emp_TaskVo
at org.apache.ibatis.builder.xml.XMLConfigBuilder.parseConfiguration(XMLConfigBuilder.java:121)
at org.apache.ibatis.builder.xml.XMLConfigBuilder.parse(XMLConfigBuilder.java:99)
at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:78)
... 3 more
Caused by: org.apache.ibatis.builder.BuilderException: Error parsing Mapper XML. Cause: org.apache.ibatis.builder.BuilderException: Error resolving class. Cause: org.apache.ibatis.type.TypeException: Could not resolve type alias 'Emp_TaskVo'. Cause: java.lang.ClassNotFoundException: Cannot find class: Emp_TaskVo
at org.apache.ibatis.builder.xml.XMLMapperBuilder.configurationElement(XMLMapperBuilder.java:120)
at org.apache.ibatis.builder.xml.XMLMapperBuilder.parse(XMLMapperBuilder.java:92)
at org.apache.ibatis.builder.annotation.MapperAnnotationBuilder.loadXmlResource(MapperAnnotationBuilder.java:173)
at org.apache.ibatis.builder.annotation.MapperAnnotationBuilder.parse(MapperAnnotationBuilder.java:124)
at org.apache.ibatis.binding.MapperRegistry.addMapper(MapperRegistry.java:72)
at org.apache.ibatis.binding.MapperRegistry.addMappers(MapperRegistry.java:97)
at org.apache.ibatis.binding.MapperRegistry.addMappers(MapperRegistry.java:105)
at org.apache.ibatis.session.Configuration.addMappers(Configuration.java:737)
at org.apache.ibatis.builder.xml.XMLConfigBuilder.mapperElement(XMLConfigBuilder.java:364)
at org.apache.ibatis.builder.xml.XMLConfigBuilder.parseConfiguration(XMLConfigBuilder.java:119)
... 5 more
Caused by: org.apache.ibatis.builder.BuilderException: Error resolving class. Cause: org.apache.ibatis.type.TypeException: Could not resolve type alias 'Emp_TaskVo'. Cause: java.lang.ClassNotFoundException: Cannot find class: Emp_TaskVo
at org.apache.ibatis.builder.BaseBuilder.resolveClass(BaseBuilder.java:118)
at org.apache.ibatis.builder.xml.XMLMapperBuilder.resultMapElement(XMLMapperBuilder.java:265)
at org.apache.ibatis.builder.xml.XMLMapperBuilder.resultMapElement(XMLMapperBuilder.java:252)
at org.apache.ibatis.builder.xml.XMLMapperBuilder.resultMapElements(XMLMapperBuilder.java:244)
at org.apache.ibatis.builder.xml.XMLMapperBuilder.configurationElement(XMLMapperBuilder.java:116)
... 14 more
Caused by: org.apache.ibatis.type.TypeException: Could not resolve type alias 'Emp_TaskVo'. Cause: java.lang.ClassNotFoundException: Cannot find class: Emp_TaskVo
at org.apache.ibatis.type.TypeAliasRegistry.resolveAlias(TypeAliasRegistry.java:120)
at org.apache.ibatis.builder.BaseBuilder.resolveAlias(BaseBuilder.java:149)
at org.apache.ibatis.builder.BaseBuilder.resolveClass(BaseBuilder.java:116)
... 18 more
Caused by: java.lang.ClassNotFoundException: Cannot find class: Emp_TaskVo
at org.apache.ibatis.io.ClassLoaderWrapper.classForName(ClassLoaderWrapper.java:200)
at org.apache.ibatis.io.ClassLoaderWrapper.classForName(ClassLoaderWrapper.java:89)
at org.apache.ibatis.io.Resources.classForName(Resources.java:261)
at org.apache.ibatis.type.TypeAliasRegistry.resolveAlias(TypeAliasRegistry.java:116)
... 20 more
Exception in thread "main" java.lang.NullPointerException
at qiu.action.Emp_TaskTestQ.main(Emp_TaskTestQ.java:15)
我的代码:
————Emp_TaskVo 类
private Integer empId;
private String taskName;
private String taskRemark;
@Override
public String toString() {
String msg="empId="+empId+",taskName="+taskName+",taskRemark="+taskRemark;
return msg;
}
public Integer getEmpId() {
return empId;
}
。。。。。setter与getter。。。。。
————MyBatis配置文件
<typeAliases>
<typeAlias alias="ETaskVo" type="qiu.vo.Emp_TaskVo"></typeAlias>
</typeAliases>
————Emp_TaskDAO接口 类
List<Emp_TaskVo> listetask();//查询全部(没有使用resultMap)
Emp_TaskVo etaskById(int id);//带id条件查询记录
void undateEtask(Emp_TaskVo etaskvo);//修改员工的年龄和状态
List<Emp_TaskVo> listEmpTask();//查询全部task(利用了resultMap)
List<Emp_EmpTaskVo> listE_EmpTask();//内连接查询员工和对应的task
————Emp_TaskDAO配置文件
<select id="listetask" resultType="qiu.vo.Emp_TaskVo">
<include refid="select_all"/>
</select>
<select id="etaskById" parameterType="integer" resultType="ETaskVo">
<include refid="select_all"/>
where empid=#{id};
</select>
<sql id="select_all">
select * from emp_task
</sql>
<update id="undateEtask" parameterType="qiu.vo.Emp_TaskVo">
<![CDATA[
update emp_task set taskName=#{taskName} , taskRemark=#{taskRemark} where empid=#{empId};
]]>
</update>
<!-- column,property都不能省略,名称相同也不能省略 -->
<resultMap type="Emp_TaskVo" id="ETMap">
<id column="empId" property="empId"/>
<result column="taskName" property="taskName"/>
<result column="taskRemark" property="taskRemark"/>
</resultMap>
<!-- 同时查询员工表和账号表的数据,使用resultMap保存数据 可以用于inner join或left join等情况-->
<select id="listEmpTask" resultMap="ETMap">
select * from emp_task;
</select>
<select id="listE_EmpTask" resultMap="E_ETMap">
select e.*,taskName,taskRemark from emp e right join emp_task t on e.empId= t.empId;
</select>
————DBConnQ 类
public class DBConnQ {
static SqlSession session=null;
public static SqlSession getSession(){
try {
InputStream configuration=Resources.getResourceAsStream("mybatisQ.xml");
SqlSessionFactory sessionFactory= new SqlSessionFactoryBuilder().build(configuration);
session=sessionFactory.openSession();
} catch (Exception e) {
e.printStackTrace();
}
return session;
}
}
————Emp_TaskTestQ 类
public static void main(String[] args) {
SqlSession session=DBConnQ.getSession();
Emp_TaskDAO etaskBase=session.getMapper(Emp_TaskDAO.class);
Emp_TaskVo etaskVo=new Emp_TaskVo();
//修改
etaskVo=etaskBase.etaskById(9);
etaskVo.setTaskName("清理整洁");
etaskBase.undateEtask(etaskVo);
session.commit();//更新数据必须手动提交事务
// List<Emp_TaskVo> etaskList=etaskBase.listEmpTask();//利用resultMap查询全部task
List<Emp_TaskVo> etaskList=etaskBase.listetask();//查询全部task
for (Emp_TaskVo etaskVo3 : etaskList) {
System.out.println(etaskVo3);
}
//利用resultMap和内或左、右外连接查询
// List<Emp_EmpTaskVo> e_etaskList=etaskBase.listE_EmpTask();
// for (Emp_EmpTaskVo etaskVo3 : e_etaskList) {
// System.out.println(etaskVo3);
// }
}
从异常上看,"错发生在alias别名上,没有'Emp_TaskVo'这样的别名,发生连锁反应,导致找不到Emp_TaskVo类",我回看我的代码,检查了MyBatis配置文件的typeAlias标签和Emp_TaskDAO配置文件的type或resultType或javaType或ofType属性,发现了错误:'resultMap标签的type属性的值'
所以解决(用别名ETaskVo或者全限定名【即qiu.vo.Emp_TaskVo】):
===改===》
问题已经解决了,但接着我疑惑了:“在Emp_TaskTestQ类中,并没有执行‘listEmpTask()’方法,所以应该不会执行"listEmpTask有关的代码"的啊~” ,可 MyBatis框架里就是会执行"listEmpTask有关代码",原因在这:
我去设断点Debug,发现在创建SqlSession对象过程中的“”报了异常,推荐看看——【原理分析之二:框架整体设计、《深入理解mybatis原理》 MyBatis的架构设计以及实例分析、mybatis学习之查询缓存】,
从那三个文章里可知:运行“测试类”,要先创建SqlSession对象——》要先加载配置并初始化——》到数据处理层阶段,为了'生成缓存',就必须将Mapper(XXXDAO).xml文件里的<mapper>标识的所有内容/SQL语句执行——》先参数映射,接着SQL语句处理,再接着结果映射(StatementHandle)——》(Executor)之后都给Configuration实例维护——》创建了SqlSession对象,若调用'查询'的方法,就会从'缓存'中读取、写入、清空;
此时,我疑惑的问题发生在"创建SqlSession对象时到达的StatementHandler";
因为我使用的是resultMap,所以当'查询emp_task表全部记录,要返回值'时,MyBatis会自动找到select标签的resultMap属性——》找到id为ETMap——》找到同resultMap标签的type属性(值为bean别名或全限定名)——》找到对应Javabean类这个映射的POJO对象,即为Emp_TaskVo——》将记录都放在缓存中;
但是发现"我的错误"中"type的值是错误的'对应别名'或者'全限定名' ",导致'找不到对应类',这时立即停止向下执行,并且报对应的异常到后台!!!简单地说,"ParameterHandler能正常转到TypeHandler,而TypeHandler却出了异常,去不到ResultSetHandler",即TypeHandler至ResultSetHandler中发生异常!!!
这就可以解释为什么" 在报错前,有这两行【译为:检查 类是否为qiu.mapper.Emp_TaskDAO匹配条件[可分配给Object]】"
'分享文章'(MyBatis基础实现):
Mybatis-mapper-xml-基础、Mybatis(二)Mapper的开发规范、【ORM系列】- mybatis一般规范、Mybatis二级缓存
更多推荐
所有评论(0)