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二级缓存

  • 11
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Yvette_QIU

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值