Return-Path: Delivered-To: apmail-ibatis-user-java-archive@www.apache.org Received: (qmail 22296 invoked from network); 5 Jul 2006 18:06:09 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 5 Jul 2006 18:06:09 -0000 Received: (qmail 86488 invoked by uid 500); 5 Jul 2006 18:06:07 -0000 Delivered-To: apmail-ibatis-user-java-archive@ibatis.apache.org Received: (qmail 86468 invoked by uid 500); 5 Jul 2006 18:06:07 -0000 Mailing-List: contact user-java-help@ibatis.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: user-java@ibatis.apache.org Delivered-To: mailing list user-java@ibatis.apache.org Received: (qmail 86457 invoked by uid 99); 5 Jul 2006 18:06:07 -0000 Received: from asf.osuosl.org (HELO asf.osuosl.org) (140.211.166.49) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 05 Jul 2006 11:06:07 -0700 X-ASF-Spam-Status: No, hits=0.0 required=10.0 tests=HTML_MESSAGE X-Spam-Check-By: apache.org Received-SPF: neutral (asf.osuosl.org: local policy) Received: from [216.193.202.245] (HELO waseda.lunarpages.com) (216.193.202.245) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 05 Jul 2006 11:06:03 -0700 Received: from i-global254.qualcomm.com ([199.106.103.254] helo=RICK2) by waseda.lunarpages.com with esmtp (Exim 4.52) id 1FyBlb-0003s6-WC for user-java@ibatis.apache.org; Wed, 05 Jul 2006 11:06:31 -0700 From: "Rick" To: Subject: RE: One solution to self-join, new feature request.... RE: Employee self-join one to many relationship (iBatis) Date: Wed, 5 Jul 2006 11:05:30 -0700 MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="----=_NextPart_000_008A_01C6A022.F0A47600" X-Mailer: Microsoft Office Outlook, Build 11.0.5510 In-Reply-To: X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.2869 Thread-Index: AcagU9thYH0a9AzaRk+maGikAmDFNQABH3qA X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - waseda.lunarpages.com X-AntiAbuse: Original Domain - ibatis.apache.org X-AntiAbuse: Originator/Caller UID/GID - [0 0] / [47 12] X-AntiAbuse: Sender Address Domain - arc-mind.com X-Source: X-Source-Args: X-Source-Dir: X-Virus-Checked: Checked by ClamAV on apache.org Message-Id: <20060705180605.BAD7A10FB000@asf.osuosl.org> X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N This is a multi-part message in MIME format. ------=_NextPart_000_008A_01C6A022.F0A47600 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit I see. Hmmm. This is makes sense. My query is a "connect by" that gets all employees. All employees have a boss, but not all employees have directReports. Will this still work? I tried it as follows: The query is a rollup query that builds a tree. For some reason, I can't get the above query to run at all. It runs inside of SQL Navigator as follows: select employee.emplid as emplid, employee.name as name, employee.N_SUPERVISOR as bossId, boss.name as bossName from ps_employees employee join ps_employees boss on employee.N_SUPERVISOR = boss.emplid start with employee.emplid = '12345' connect by employee.n_supervisor = prior employee.emplid order by level, name Which results in: 12345 Tom Bridizzle 001 George Bush 30 Brad Bojangles 12345 Tom Bridizzle 1 David Efurdstein 12345 Tom Bridizzle 2 Rick Hightower 1 David Efurdstein 3 Scott Fauerbach 1 David Efurdstein When I run it inside of iBatis I get: (I tried with and without the ;) org.springframework.jdbc.BadSqlGrammarException: SqlMapClient operation; bad SQL grammar []; nested exception is com.ibatis.common.jdbc.exception.NestedSQLException: --- The error occurred in qcom/cas/mysourcej/poc/dao/Employee.xml. --- The error occurred while applying a parameter map. --- Check the getMyOrg-InlineParameterMap. --- Check the statement (query failed). --- Cause: java.sql.SQLException: ORA-00911: invalid character Caused by: java.sql.SQLException: ORA-00911: invalid character Caused by: com.ibatis.common.jdbc.exception.NestedSQLException: --- The error occurred in qcom/cas/mysourcej/poc/dao/Employee.xml. --- The error occurred while applying a parameter map. --- Check the getMyOrg-InlineParameterMap. --- Check the statement (query failed). --- Cause: java.sql.SQLException: ORA-00911: invalid character Caused by: java.sql.SQLException: ORA-00911: invalid character at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQueryWith Callback(GeneralStatement.java:185) at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQueryForL ist(GeneralStatement.java:123) at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForList(SqlMapExec utorDelegate.java:610) at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForList(SqlMapExec utorDelegate.java:584) at com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.queryForList(SqlMapSessionIm pl.java:101) at org.springframework.orm.ibatis.SqlMapClientTemplate$3.doInSqlMapClient(SqlMa pClientTemplate.java:228) at org.springframework.orm.ibatis.SqlMapClientTemplate.execute(SqlMapClientTemp late.java:165) at org.springframework.orm.ibatis.SqlMapClientTemplate.executeWithListResult(Sq lMapClientTemplate.java:187) at org.springframework.orm.ibatis.SqlMapClientTemplate.queryForList(SqlMapClien tTemplate.java:226) at qcom.cas.commons.dao.dataproducer.IBatisQueryDataProducer.executeNameParamsQ uery(IBatisQueryDataProducer.java:75) at qcom.cas.commons.dao.dataproducer.IBatisQueryDataProducer.list(IBatisQueryDa taProducer.java:66) 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:324) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopU tils.java:266) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint (ReflectiveMethodInvocation.java:181) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(Reflect iveMethodInvocation.java:148) at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed( DelegatingIntroductionInterceptor.java:124) at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(Del egatingIntroductionInterceptor.java:112) at qcom.cas.commons.faces.dataproducer.GetSelectItemsIntroduction.invoke(GetSel ectItemsIntroduction.java:69) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(Reflect iveMethodInvocation.java:170) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopPro xy.java:176) at $Proxy0.list(Unknown Source) at qcom.cas.mysourcej.poc.backingbean.EmergencyContactBackingBean.myOrgClicked( EmergencyContactBackingBean.java:93) at qcom.cas.mysourcej.poc.backingbean.EmergencyContactBackingBeanTest.testShowM yOrgTree(EmergencyContactBackingBeanTest.java:142) 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:324) 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 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRu nner.java:478) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner. java:344) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner .java:196) Caused by: java.sql.SQLException: ORA-00911: invalid character at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:111) at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:330) at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:287) at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:742) at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:21 2) at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatem ent.java:795) at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java :1030) at oracle.jdbc.driver.T4CPreparedStatement.executeMaybeDescribe(T4CPreparedStat ement.java:835) at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java :1123) at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedSta tement.java:3284) at oracle.jdbc.driver.OraclePreparedStatement.execute(OraclePreparedStatement.j ava:3389) at org.apache.commons.dbcp.DelegatingPreparedStatement.execute(DelegatingPrepar edStatement.java:168) at com.ibatis.sqlmap.engine.execution.SqlExecutor.executeQuery(SqlExecutor.java :180) at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.sqlExecuteQuery( GeneralStatement.java:205) at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQueryWith Callback(GeneralStatement.java:173) ... 38 more Caused by: java.sql.SQLException: ORA-00911: invalid character at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:111) at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:330) at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:287) at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:742) at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:21 2) at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatem ent.java:795) at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java :1030) at oracle.jdbc.driver.T4CPreparedStatement.executeMaybeDescribe(T4CPreparedStat ement.java:835) at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java :1123) at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedSta tement.java:3284) at oracle.jdbc.driver.OraclePreparedStatement.execute(OraclePreparedStatement.j ava:3389) at org.apache.commons.dbcp.DelegatingPreparedStatement.execute(DelegatingPrepar edStatement.java:168) at com.ibatis.sqlmap.engine.execution.SqlExecutor.executeQuery(SqlExecutor.java :180) at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.sqlExecuteQuery( GeneralStatement.java:205) at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQueryWith Callback(GeneralStatement.java:173) at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQueryForL ist(GeneralStatement.java:123) at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForList(SqlMapExec utorDelegate.java:610) at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForList(SqlMapExec utorDelegate.java:584) at com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.queryForList(SqlMapSessionIm pl.java:101) at org.springframework.orm.ibatis.SqlMapClientTemplate$3.doInSqlMapClient(SqlMa pClientTemplate.java:228) at org.springframework.orm.ibatis.SqlMapClientTemplate.execute(SqlMapClientTemp late.java:165) at org.springframework.orm.ibatis.SqlMapClientTemplate.executeWithListResult(Sq lMapClientTemplate.java:187) at org.springframework.orm.ibatis.SqlMapClientTemplate.queryForList(SqlMapClien tTemplate.java:226) at qcom.cas.commons.dao.dataproducer.IBatisQueryDataProducer.executeNameParamsQ uery(IBatisQueryDataProducer.java:75) at qcom.cas.commons.dao.dataproducer.IBatisQueryDataProducer.list(IBatisQueryDa taProducer.java:66) 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:324) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopU tils.java:266) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint (ReflectiveMethodInvocation.java:181) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(Reflect iveMethodInvocation.java:148) at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed( DelegatingIntroductionInterceptor.java:124) at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(Del egatingIntroductionInterceptor.java:112) at qcom.cas.commons.faces.dataproducer.GetSelectItemsIntroduction.invoke(GetSel ectItemsIntroduction.java:69) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(Reflect iveMethodInvocation.java:170) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopPro xy.java:176) at $Proxy0.list(Unknown Source) at qcom.cas.mysourcej.poc.backingbean.EmergencyContactBackingBean.myOrgClicked( EmergencyContactBackingBean.java:93) at qcom.cas.mysourcej.poc.backingbean.EmergencyContactBackingBeanTest.testShowM yOrgTree(EmergencyContactBackingBeanTest.java:142) 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:324) 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 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRu nner.java:478) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner. java:344) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner .java:196) _____ From: Jeff Butler [mailto:jeffgbutler@gmail.com] Sent: Wednesday, July 05, 2006 9:54 AM To: user-java@ibatis.apache.org Subject: Re: One solution to self-join, new feature request.... RE: Employee self-join one to many relationship (iBatis) Hi Rick, A self join can be accomplished through groupBy and column renaming. Here's a simple example I just coded up for a test: Table Definition: create table employees(id int not null, bossId int, name varchar(50)) Class Definition: public class Employee { private Integer id; private String name; private List employees; // getters/setters } iBATIS stuff: This returns all the data in one pass, so no N+1 problem. Jeff Butler On 7/5/06, Rick wrote: Someone sent me a solution to the self-join that I asked about earlier as follows: select * from Employee select * from Employee where employee_id=#value# This is very helpful in understanding how iBatis works. I think I will stick with the other approach b/c the code above would perform 1 query for each boss (N+1). The approach I used (with the helper method) only hits the db once. It gets all the data it needs in one swipe and then builds the hierarchy. Again, my former approach gets all of the employees in the tree (using connect-by) and then constructs the hierarchy. The above way is much cleaner in that it does not require custom Java code to build the list. Its runtime performance would be problematic especially since I am replacing code that does not have an N+1 issue (custom VB/ASP app). I'd like to have something like this (as a new feature in iBatis): select * from Employee e start with n_supervisor = #supervisorId# connect by n_supervisor = prior emplid See the: Basically the data for the hierarchy is already retrieved from the db. Why hit it a second time? Thoughts? -----Original Message----- From: Larry Meadors [mailto:lmeadors@apache.org] Sent: Monday, July 03, 2006 3:54 PM To: user-java@ibatis.apache.org Subject: Re: Employee self-join one to many relationship (iBatis) Hmm, I generally don't build my object model that way, so my experience with groupBy is sort of limited, sorry. ;-) If you can't make groupBy work, I'd look at doing this with a rowhandler. You'd get all the data in one hit to the database, and then step through the results building the object graph the way you want it. Larry On 7/3/06, Rick wrote: > Bingo! > > Yep. Employee has a directReports list which is a list of Employees. > > > > -----Original Message----- > From: Larry Meadors [mailto: lmeadors@apache.org] > Sent: Monday, July 03, 2006 3:19 PM > To: user-java@ibatis.apache.org > Subject: Re: Employee self-join one to many relationship (iBatis) > > Hey Rick, I am not 100% sure I understand what you are trying to do, > but let me try to restate it and see.. > > Do you want a list of employees, each one with another list of > employees (direct reports), and a list of contacts on each one - both > the main employee list and the child employees? > > Larry > > > On 7/3/06, Rick wrote: > > > > > > > > > > I just want to use iBatis in the cleanest way possible. I have a > workaround > > but wonder if iBatis support self-joined one to many relationships. > > > > > > > > Let me explain.. > > > > > > > > > > > > I have a query that returns employees. > > > > > > > > Employees have Boss's who are Employees. > > > > > > > > Currently I have Employees have Contacts who have Phone Numbers. > > > > > > > > (Where Employee, Contact and Phone number are objects.) > > > > > > > > I'd like to have Employees have Employees (directReports) and Employees > have > > Contacts who have Phone Numbers. > > > > > > > > Does iBatis support a self join? > > > > > > > > > > > > Here is my current mapping and how I get around this lack of support (or > is > > this support lacking)... > > > > > > > > , i.e., > > > > > > > > > class="qcom.cas.mysourcej.poc.model.Employee" > > groupBy="emplid"> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > class="qcom.cas.mysourcej.poc.model.Contact"> > > > > > > > > > > > > > typeHandler="qcom.cas.commons.ibatis.typehandler.StringBooleanTypeHandler" > > /> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >