MyBatis筆記(一)————PersistenceException產生與解決(考考你CRUD基礎扎不紮實~)
(使用Eclipse,JDK1.7,MySQL資料庫)
CRUD【VC/C++、HTML、Java、SQL、JSP、SSH、SSM等等的英語單詞(看了很多遍都會忘記意思或讀音,只知道大概用來幹嘛的)】
①
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); 以及下圖
====改一下就好了====》
⑤
⑴
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 [[email protected]]
==> 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物件) [/笑哭]:
⑦
Exception in thread "main" org.apache.ibatis.exceptions.PersistenceException:
### Error updating database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '12' for key 'PRIMARY'
### The error may involve qiu.mapper.Emp_TaskDAO.addEtask-Inline
### The error occurred while setting parameters
### SQL: insert into emp_task(empId,taskName,taskremark) values(?,?,?);
### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '12' 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.addEtask(Unknown Source)
at qiu.action.Emp_TaskTestQ.main(Emp_TaskTestQ.java:22)
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '12' 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
光看異常報錯,就知道是"empId是主鍵,傳empId的值"12"重複了",所以解決:將值改了!!!(有些異常,只看異常警告就可以找到錯誤,我在這超容易的就不一一列舉了)
⑦
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基礎實現):