is this possible to do with iBatis + spring

2019-08-14 14:21发布

问题:

usual idiom of using ibatis with spring support is following. Or this is how I'm doing it. please let me know if it can be done a better way?

beans xml:

<bean id="DataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="jdbc/some/som1/my/mydb"/>
</bean>
<bean id="SqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
  <property name="configLocation" value="classpath:sql-map-config-oracle.xml"/>
  <property name="dataSource" ref="DataSource"/>
</bean>
 <bean id="myDAO" class="com.reports.MyUserAccessDAO">
    <property name="sqlMapClient" ref="SqlMapClient"/>
    <property name="dataSource" ref="DataSource"/>
 </bean>

interface:

public interface MyUserAccessIface {
    public SomeBean getUserReports (String org);
}

DAO:

public class MyUserAccessDAO extends SqlMapClientDaoSupport implements MyUserAccessDAO {
    public SomeBean getUserReports (String org)
    {
      SomeBean bean = new SomeBean();
      //code for parameters goes here 
      getSqlMapClientTemplate().queryForList("namesp.userreport", parm);
      //fetch the result from parm and put them in SomeBean
      return bean
    }
}

calling the DAO:

MyUserAccessIface iBatisDAO = 
(MyUserAccessIface) ApplicationInitializer.getApplicationContext().getBean("myDAO");

even though this works fine I dont understand the need for an interface.

Questions

  • Can the interface be taken out of the picture and still have this working?
  • can the design/settings be changed so the call to the DAO is simply (even if that requires a base abstract class)

    MyUserAccessDAO mydao = new MyUserAccessDAO(); mydao.getUserReports("blah");

I've asked question along these lines couple days back but after struggling for 2 days and finding more things out I asked this question again now. If possible please provide code snippets of what you'd change/add.

Unit testing with this design does not work because everything is residing inside the container. If I get that working, then I will be adding that to the question as well (for information purpose).

Also, I think for someone trying to make spring + ibatis work...this would end up being a good place to start.

Edit:

Like I mentioned above that I would like to call my DAO like this (or i'm fine with passing something along as constructor parameter):

MyUserAccessDAO mydao = new MyUserAccessDAO(); mydao.getUserReports("blah");

To achieve above I would have following line in my DAO

setSqlMapClient((SqlMapClient)ApplicationInitializer.getApplicationContext().getBean("SqlMapClient"));

Still need to know what all to overwrite to be able to write test case for this. Test case wont be able to access anything inside the container so it will depend on Driver Datasource...

Since I am going against the best practice here...i dont mind changing my DAO exclusively just for the test case...

回答1:

Can the interface be taken out of the picture and still have this working?

Don't take the interface out. It's there for a good reason (e.g., proxy generation for transactions, AOP, mocks for testing in services, etc.)

Why do you want to take it out? What angst is it causing for you?

Can the design/settings be changed so the call to the DAO is simply (even if that requires a base abstract class)

Why are you calling "new"? If you're using Spring, you should be injecting this using the App Context. If you call "new", it's not under Spring's control. That should be the whole point.



回答2:

The interface is there to decouple you from depending directly on the implementation, which is, in general, good practice. It should all work fine without the interface, but it is better to depend on abstractions rather than implementations.

As for testing, well by using the interface, it becomes much easier to test the code using the DAO as you can just create a "mock" implementation of this that just returns dummy data and "inject" this manually in your unit test - your client code can't tell the difference between this and the real DAO as all it knows about is the interface.



回答3:

I can think of 1 major principle taking out the interface would break... 'object orientation' and most importantly, the inability to change method signatures without disrupting clients calling your code. That alone would stop me on my tracks. GOOD QUESTION THOUGH!! During many engagements, I am usually asked this question. Or simply people want to program to abstract classes. =)