一个网站项目,网站有类别,类别是树状的,但目前只有两层;类别下可以有相应的产品。
下面两个是相应的VO:
public class CategoryModel implements Serializable
{
private int id;
private String name;
private int parentCategoryId;
private CategoryModel parentCategory;
//省略相应的setter/getter方法
......
}
public class SoftwareModel implements Serializable
{
private int id;
private String name;
private CategoryModel category;
//省略相应的setter/getter方法
......
}
下面是iBatis的XML文件:
<sqlmapconfig>
<settings cachemodelsenabled="true" enhancementenabled="true" lazyloadingenabled="true" usestatementnamespaces="true">
<sqlmap resource="com/demo/category/Category.xml">
<sqlmap resource="com/demo/software/Software.xml">
</sqlmapconfig>
Category.xml文件
<sqlmap namespace="Category">
<typealias alias="category" type="com.demo.category.model.CategoryModel">
<cachemodel type="OSCACHE" id="category-cache">
<flushinterval minutes="10">
<flushonexecute statement="Category.addCartory">
</cachemodel>
<resultmap class="category" id="categoryResult">
<result property="id" column="FID" javatype="int" jdbctype="int" nullvalue="0">
<result property="name" column="FName" javatype="String" jdbctype="nvarchar">
<result property="parentCategoryId" column="FParentID" javatype="int" jdbctype="int" nullvalue="0">
<!---->
<result property="parentCategory" column="FParentID" select="Category.getCategoryById">
</resultmap>
<!---->
<select id="getCategoryById">
SELECT * FROM t_categories
WHERE FID =#categoryId#
</select>
</sqlmap>
Software.xml文件:
<sqlmap namespace="Software">
<typealias alias="software" type="com.demo.software.model.SoftwareModel">
<cachemodel type="OSCACHE" id="software-cache">
<flushinterval minutes="10">
<flushonexecute statement="Software.addSoftware">
</cachemodel>
<resultmap class="software" id="softwareResult">
<result property="id" column="FID" javatype="int" jdbctype="int" nullvalue="0">
<result property="name" column="FName" javatype="String" jdbctype="nvarchar">
<result property="category" column="FCategoryID" select="Category.getCategoryById">
</resultmap>
<select id="getSoftwareById">
SELECT * FROM t_softwares
WHERE FID =#softwareId#
</select>
<select id="getSoftwareByName">
SELECT * FROM t_softwares
WHERE FName =#name#
</select>
</sqlmap>
通过Spring来调用iBatis,下面是Spring的配置文件:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemalocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<bean id="messageProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:properties/cms.properties</value>
</list>
</property>
</bean>
<bean id="cmsDbcpDataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName">
<value>${cms.datasource.driverClassName}</value>
</property>
<property name="url">
<value>${cms.datasource.url}</value>
</property>
<property name="username">
<value>${cms.datasource.username}</value>
</property>
<property name="password">
<value>${cms.datasource.password}</value>
</property>
</bean>
<bean id="cmsSqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="configLocation">
<value>classpath:cms-sql-map-config.xml</value>
</property>
<property name="dataSource">
<ref bean="cmsDbcpDataSource">
</property>
</bean>
<bean id="cmsSqlMapClientTemplete" class="org.springframework.orm.ibatis.SqlMapClientTemplate">
<property name="sqlMapClient">
<ref bean="cmsSqlMapClient">
</property>
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource">
<ref local="cmsDbcpDataSource">
</property>
</bean>
<bean id="baseTxProxy" lazy-init="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true">
<property name="transactionManager">
<ref local="transactionManager">
</property>
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
<prop key="create*">PROPAGATION_REQUIRED</prop>
<prop key="add*">PROPAGATION_REQUIRED</prop>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="get*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
<bean id="categoryDao" class="com.demo.category.dao.impl.ibatis.CategoryDaoImpl">
<property name="cmsSqlMapClientTemplete">
<ref bean="cmsSqlMapClientTemplete">
</property>
</bean>
<bean id="softwareDao" class="com.demo.software.dao.impl.ibatis.SoftwareDaoImpl">
<property name="cmsSqlMapClientTemplete">
<ref bean="cmsSqlMapClientTemplete">
</property>
</bean>
</beans>
下面是相应的DAO:
public abstract class BaseDaoImpl
{
private SqlMapClientTemplate cmsSqlMapClientTemplete;
public SqlMapClientTemplate getCmsSqlMapClientTemplete()
{
return cmsSqlMapClientTemplete;
}
public void setCmsSqlMapClientTemplete(
SqlMapClientTemplate cmsSqlMapClientTemplete)
{
this.cmsSqlMapClientTemplete = cmsSqlMapClientTemplete;
}
}
public class SoftwareDaoImpl extends BaseDaoImpl implements SoftwareDao
{
@Override
public SoftwareModel getSoftwareById(int softwareId)
{
return (SoftwareModel) getCmsSqlMapClientTemplete().queryForObject("Software.getSoftwareById", new Integer(softwareId));
}
@Override
public SoftwareModel getSoftwareByName(String name)
{
return (SoftwareModel) getCmsSqlMapClientTemplete().queryForObject("Software.getSoftwareByName", name);
}
}
public class CategoryDaoImpl extends BaseDaoImpl implements CategoryDao
{
@Override
public CategoryModel getCategoryById(int categoryId)
{
return (CategoryModel) getCmsSqlMapClientTemplete().queryForObject("Category.getCategoryById", new Integer(categoryId));
}
@Override
public CategoryModel getCategoryByName(String name)
{
return (CategoryModel) getCmsSqlMapClientTemplete().queryForObject("Category.getCategoryByName", name);
}
}
如果调用以下直接取得类别的代码不会有任何问题,证明这样子来取父类别是没有任何问题的
CategoryModel model = categoryDao.getCategoryById(273);
。
但是下面是取产品的代码就会抛出异常:
SoftwareModel model = softwareDao.getSoftwareById(111);//抛出异常
SoftwareModel model = softwareDao.getSoftwareByName("aaa");//抛出异常
当把Category.xml文件中“<result property="parentCategory" column="FParentID" select="Category.getCategoryById">”这一行注释掉后,上面代码就能正确运行。
下面是取产品代码的异常堆栈:
org.springframework.jdbc.UncategorizedSQLException: SqlMapClient operation; uncategorized SQLException for SQL []; SQL state [HY010]; error code [0];
--- The error occurred in com/demo/software/Software.xml.
--- The error occurred while applying a result map.
--- Check the Software.softwareResult.
--- Check the result mapping for the 'category' property.
--- Cause: com.ibatis.common.jdbc.exception.NestedSQLException:
--- The error occurred in com/demo/category/Category.xml.
--- The error occurred while applying a result map.
--- Check the Category.categoryResult.
--- The error happened while setting a property on the result object.
--- Cause: java.sql.SQLException: Invalid state, the ResultSet object is closed.; nested exception is com.ibatis.common.jdbc.exception.NestedSQLException:
--- The error occurred in com/demo/software/Software.xml.
--- The error occurred while applying a result map.
--- Check the Software.softwareResult.
--- Check the result mapping for the 'category' property.
--- Cause: com.ibatis.common.jdbc.exception.NestedSQLException:
--- The error occurred in com/demo/category/Category.xml.
--- The error occurred while applying a result map.
--- Check the Category.categoryResult.
--- The error happened while setting a property on the result object.
--- Cause: java.sql.SQLException: Invalid state, the ResultSet object is closed.
at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.translate(SQLStateSQLExceptionTranslator.java:124)
at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.translate(SQLErrorCodeSQLExceptionTranslator.java:322)
at org.springframework.orm.ibatis.SqlMapClientTemplate.execute(SqlMapClientTemplate.java:212)
at org.springframework.orm.ibatis.SqlMapClientTemplate.queryForObject(SqlMapClientTemplate.java:271)
at com.shareweb.cms.component.software.dao.impl.ibatis.SoftwareDaoImpl.getSoftwareById(SoftwareDaoImpl.java:23)
at com.shareweb.cms.importdata.AdvertExcelImportManagerImplTest.testImportData(AdvertExcelImportManagerImplTest.java:54)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at junit.framework.TestCase.runTest(TestCase.java:154)
at junit.framework.TestCase.runBare(TestCase.java:127)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:118)
at junit.framework.TestSuite.runTest(TestSuite.java:208)
at junit.framework.TestSuite.run(TestSuite.java:203)
at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
Caused by: com.ibatis.common.jdbc.exception.NestedSQLException:
--- The error occurred in com/demo/software/Software.xml.
--- The error occurred while applying a result map.
--- Check the Software.softwareResult.
--- Check the result mapping for the 'category' property.
--- Cause: com.ibatis.common.jdbc.exception.NestedSQLException:
--- The error occurred in com/demo/category/Category.xml.
--- The error occurred while applying a result map.
--- Check the Category.categoryResult.
--- The error happened while setting a property on the result object.
--- Cause: java.sql.SQLException: Invalid state, the ResultSet object is closed.
at com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.executeQueryWithCallback(MappedStatement.java:201)
at com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.executeQueryForObject(MappedStatement.java:120)
at com.ibatis.sqlmap.engine.mapping.statement.CachingStatement.executeQueryForObject(CachingStatement.java:79)
at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForObject(SqlMapExecutorDelegate.java:518)
at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForObject(SqlMapExecutorDelegate.java:493)
at com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.queryForObject(SqlMapSessionImpl.java:106)
at org.springframework.orm.ibatis.SqlMapClientTemplate$1.doInSqlMapClient(SqlMapClientTemplate.java:273)
at org.springframework.orm.ibatis.SqlMapClientTemplate.execute(SqlMapClientTemplate.java:209)
... 21 more
Caused by: com.ibatis.common.jdbc.exception.NestedSQLException:
--- The error occurred in com/demo/category/Category.xml.
--- The error occurred while applying a result map.
--- Check the Category.categoryResult.
--- The error happened while setting a property on the result object.
--- Cause: java.sql.SQLException: Invalid state, the ResultSet object is closed.
at com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.executeQueryWithCallback(MappedStatement.java:201)
at com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.executeQueryForObject(MappedStatement.java:120)
at com.ibatis.sqlmap.engine.mapping.statement.CachingStatement.executeQueryForObject(CachingStatement.java:79)
at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForObject(SqlMapExecutorDelegate.java:518)
at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForObject(SqlMapExecutorDelegate.java:493)
at com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.queryForObject(SqlMapSessionImpl.java:106)
at com.ibatis.sqlmap.engine.impl.SqlMapClientImpl.queryForObject(SqlMapClientImpl.java:82)
at com.ibatis.sqlmap.engine.mapping.result.loader.ResultLoader.getResult(ResultLoader.java:75)
at com.ibatis.sqlmap.engine.mapping.result.loader.LazyResultLoader.loadResult(LazyResultLoader.java:77)
at com.ibatis.sqlmap.engine.mapping.result.loader.ResultLoader.loadResult(ResultLoader.java:54)
at com.ibatis.sqlmap.engine.mapping.result.ResultMap.getNestedSelectMappingValue(ResultMap.java:501)
at com.ibatis.sqlmap.engine.mapping.result.ResultMap.getResults(ResultMap.java:341)
at com.ibatis.sqlmap.engine.execution.SqlExecutor.handleResults(SqlExecutor.java:384)
at com.ibatis.sqlmap.engine.execution.SqlExecutor.handleMultipleResults(SqlExecutor.java:300)
at com.ibatis.sqlmap.engine.execution.SqlExecutor.executeQuery(SqlExecutor.java:189)
at com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.sqlExecuteQuery(MappedStatement.java:221)
at com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.executeQueryWithCallback(MappedStatement.java:189)
... 28 more
Caused by: java.sql.SQLException: Invalid state, the ResultSet object is closed.
at net.sourceforge.jtds.jdbc.JtdsResultSet.checkOpen(JtdsResultSet.java:299)
at net.sourceforge.jtds.jdbc.JtdsResultSet.next(JtdsResultSet.java:569)
at org.apache.commons.dbcp.DelegatingResultSet.next(DelegatingResultSet.java:169)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.ibatis.common.jdbc.logging.ResultSetLogProxy.invoke(ResultSetLogProxy.java:47)
at $Proxy10.next(Unknown Source)
at com.ibatis.sqlmap.engine.execution.SqlExecutor.handleResults(SqlExecutor.java:383)
at com.ibatis.sqlmap.engine.execution.SqlExecutor.handleMultipleResults(SqlExecutor.java:300)
at com.ibatis.sqlmap.engine.execution.SqlExecutor.executeQuery(SqlExecutor.java:189)
at com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.sqlExecuteQuery(MappedStatement.java:221)
at com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.executeQueryWithCallback(MappedStatement.java:189)
... 44 more
问题补充去iBatis官方论坛上也没有找到解决方法。难道没有人遇到过这种问题吗?
问题补充首选,这个是lazyLoading的,所以如果没有调用getParentCategory()方法的话是不会真正去加载parent category的。
其次,当递归到根结点时就停了。
问题不在这个上面,如果是因为递归原因,为什么我直接CategoryModel model = categoryDao.getCategoryById(273); 就可以,而SoftwareModel model = softwareDao.getSoftwareById(111);却出错。
问题补充在www.nabble.com上问了,也没有什么实质性的回答。大部份人认为可能是DB设置的问题,比如链接数是不是设置成1了。但我试过了,不是这个问题。javaeye的大侠们,没有人遇到过这种问题吗?
问题补充如果用inner join的话,就不能通过po一级一级地得到父类别了。此外,即使通过别的方法解决了,但还是想从技术弄明白为什么不能这样做。
在www.nabble.com上有人说是配置问题,于是试了下面代码,代码运行没问题,证明DB配置是没有问题的。
Connection cn1 = null;
PreparedStatement pst1 = null;
PreparedStatement pst2 = null;
ResultSet rs1 = null;
ResultSet rs2 = null;
DataSource ds = (BasicDataSource)ctx.getBean("cmsDbcpDataSource");
try
{
// Class.forName("net.sourceforge.jtds.jdbc.Driver").newInstance();
// cn1 = DriverManager.getConnection("jdbc:jtds:sqlserver://localhost:1433/aa", "sa", "aa");
cn1 = ds.getConnection();
pst1 = cn1.prepareStatement("select fid, fname, fcategoryid from t_softwares");
rs1 = pst1.executeQuery();
while(rs1.next())
{
System.out.println("software:" + rs1.getString(2));
pst2 = cn1.prepareStatement("select fid, fname from t_categories where fid=?");
pst2.setInt(1, rs1.getInt(3));
rs2 = pst2.executeQuery();
if(rs2.next())
{
System.out.println("category:" + rs2.getString(2));
}
rs2.close();
pst2.close();
}
rs1.close();
pst1.close();
cn1.close();
}
catch(Exception e)
{
e.printStackTrace();
assertTrue(false);
}
问题补充两周过去了,还没解决问题
相关推荐
MySql,多表联合查询加AS语句,多余的就不说了,自己看,绝对简单!
access 联合查询 示例 将两个以上数据表中的相关数据通过联合查询筛选出来,显示在一个查询数据表中。
Access提供了多种查询方式,其中之一就是联合查询,这在处理多个表的数据整合时非常有用。"上传一个带合计的联合查询"这个标题揭示了我们要讨论的主题——如何在Access中进行复杂的联合查询,并且包含计算字段。 ...
多表联合查询,一个简单的实例。适合初学者参考!
总的来说,这个压缩包提供了一个实践性的学习资源,帮助用户理解并掌握SQL中的多表联合查询,同时通过VB项目示例展示了如何在实际开发中应用这些查询。用户不仅可以学习到SQL语法,还能了解到数据库应用程序的设计和...
dataset 多表联合查询 dataset 多表联合查询 dataset 多表联合查询 dataset 多表联合查询 dataset 多表联合查询 dataset 多表联合查询 dataset 多表联合查询
delphi针对 access表的多表联合查询实例
SQL同一个表不同条件两个SUM两个count查询结果一次查询并显示
sql 联合查询 子查询 综合查询 统计数据 case when then 用法
【联合查询】是SQL注入的一种技术,允许攻击者合并两个或更多的SELECT语句,以便在不直接访问数据库的情况下获取信息。在这个场景中,攻击者首先判断了注入点,通过对比两个不同的URL请求,发现系统对不同输入的响应...
使用库管实例,简单实用,高手细化一下,互相交流一下。
MySQL是一种广泛使用的开源关系型数据库管理系统,其联合查询(JOIN)功能是数据库操作中的核心部分,用于合并多个数据表中的相关记录,以便进行更复杂的分析和检索。在本实例讲解中,我们将深入探讨MySQL联合查询的...
MySQL数据库中的联合查询(UNION)是一种强大的操作,它允许将两个或更多SELECT语句的结果合并成一个结果集。在理解联合查询时,我们需要明确几个关键概念: 1. **UNION操作符**:UNION操作符用于合并两个或多个...
MySQL 联合查询案例,需要搭配博主【MySQL】联合查询这篇文章使用,用于初始化数据,搭配文章学习可以充分学会联合查询,建议先学习博主 MySQL 专栏前部分的基础知识,联合查询是在有一定基础后进行学习的,里面的...
- **联合查询定义**:数据库联合查询是一种能够在多个数据源或数据库之间执行查询的技术。通过整合来自不同来源的数据,联合查询可以帮助用户获得更全面的信息视图。 - **挑战**: - **数据异构性**:不同数据库的...
5. **联合查询**:联合查询是数据库操作中的一种,将两个或多个表的数据合并在一起,以满足特定的查询需求。在分页插件中,联合查询可能用于整合不同表中的信息,提供更全面的数据展示。 6. **模糊查询**:模糊查询...
然而,在实际项目中,当从Oracle切换到MySQL时,可能会遇到联合查询性能下降甚至引发内存溢出的问题。这主要是因为Oracle和MySQL在处理查询优化、内存管理和并行执行策略上的差异。 Oracle在处理联合查询时,通常会...
在实际项目中,遇到了表数据量大导致查询速度很慢的问题。通过记录和优化过程,总结出一些有价值的经验,希望能够帮助读者解决类似的问题。 知识点1:Group By 查询的索引设置 在优化 Group By 查询时,仅对 Group...
联合索引查询原理: 联合索引是由多个字段组成的索引结构,它的数据页内部按照联合索引的字段顺序进行排序。以本案例中的学生信息表为例,表中包含学生班级、学生姓名、科目名称和成绩分数四个字段,查询频率较高的...