这可以用 iBatis 来做吗?春天
使用带有 spring 支持的 ibatis 的常见习惯用法如下。或者这就是我正在做的事情。请让我知道是否可以有更好的方法?
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>
接口:
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
}
}
调用 DAO:
MyUserAccessIface iBatisDAO =
(MyUserAccessIface) ApplicationInitializer.getApplicationContext().getBean("myDAO");
尽管这工作正常,但我不明白需要一个接口。
问题
- 接口可以取出来吗 图片仍然有效吗?
设计/设置可以改变吗 对 DAO 的调用很简单(即使需要一个基本抽象类)
MyUserAccessDAO mydao = new MyUserAccessDAO(); mydao.getUserReports("blah");
几天前我已经问过这样的问题,但经过两天的努力并发现更多的事情后,我现在再次问了这个问题。如果可能,请提供您要更改/添加的内容的代码片段。
这种设计的单元测试不起作用,因为所有东西都驻留在容器内。如果我能做到这一点,那么我也会将其添加到问题中(出于信息目的)。
另外,我认为对于试图让 spring + ibatis 工作的人来说......这最终将是一个很好的起点。
编辑:
就像我上面提到的那样,我想像这样调用我的 DAO(或者我可以将某些内容作为构造函数参数传递):
MyUserAccessDAO mydao = new MyUserAccessDAO(); mydao.getUserReports("blah");
为了实现上述目标,我将在我的 DAO 中添加以下
setSqlMapClient((SqlMapClient)ApplicationInitializer.getApplicationContext().getBean("SqlMapClient"));
行需要知道要覆盖哪些内容才能为此编写测试用例。测试用例无法访问容器内的任何内容,因此它将取决于驱动程序数据源...
因为我在这里违背了最佳实践...我不介意仅针对测试用例更改我的 DAO...
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...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
接口不要拔出来。它的存在是有充分理由的(例如,事务的代理生成、AOP、服务中测试的模拟等)。
为什么要删除它?它给你带来了什么焦虑?
为什么要调用“new”?如果您使用 Spring,则应该使用 App Context 注入它。如果你调用“new”,它就不受Spring的控制。这应该就是重点。
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?
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.
该接口可以将您从直接依赖于实现的情况中分离出来,这通常是一个很好的实践。没有接口,它应该可以正常工作,但最好依赖抽象而不是实现。
至于测试,通过使用接口,使用 DAO 测试代码变得更加容易,因为您只需创建一个仅返回虚拟数据的“模拟”实现并“注入”它即可在单元测试中手动进行 - 您的客户端代码无法区分这与真正的 DAO 之间的区别,因为它只知道接口。
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.
我可以想到一个主要原则,去掉接口会破坏......“面向对象”,最重要的是,无法在不中断调用代码的客户端的情况下更改方法签名。仅此一点就会阻止我前进。不过,这是一个好问题!在许多约会中,我经常被问到这个问题。或者只是人们想要对抽象类进行编程。 =)
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. =)