问题描述
我有一个应用程序,它已经使用Spring Framework和Spring JDBC以及使用SimpleJdbcTemplate和RowMapper类的DAO层。这似乎与从数据库中读取的小类结构非常有效。但是,我们需要加载包含其他对象集合的对象,这些对象仍然保存其他对象的集合。
I have an application that is already using the Spring Framework and Spring JDBC with a DAO layer using the SimpleJdbcTemplate and RowMapper classes. This seems to work very well with small class structures being read from the database. However, we have the need to load objects that hold collections of other objects, which hold collections of other objects still.
此问题的明显解决方案是创建一个名为RowMapper的类或我们的对象,并将引用传递给构造函数中的正确DAO对象。例如:
The "obvious" solution to this problem is to create a named RowMapper class or our objects, and pass references to the proper DAO objects in the constructor. For example:
public class ProjectRowMapper implements ParameterizedRowMapper {
public ProjectRowMapper(AccountDAO accountDAO, ) {
this.accountDAO = accountDAO;
}
public Project mapRow(ResultSet rs, int rowNum) throws SQLException {
Project project= new Project ();
project.setProjecttId( rs.getString("project_id") );
project.setStartDate( rs.getDate("start_date") );
// project.setEtcetera(...);
// this is where the problems start
project.setAccounts( accountDAO.getAccountsOnProject(project.getProjectId()) );
}
}
问题是即使ProjectDAO和账户DAO共享相同的DataSource实例(在我们的示例中,这是一个连接池),任何数据库访问都是通过不同的连接完成的。
The problem is that even though the ProjectDAO and the Account DAO share the same DataSource instance (in our case this is a connection pool), any database accesses are done through a different connection.
如果对象层次结构甚至是三层深度,那么使用此实现会导致
(a)框架对datasource.getConnection()的多次调用,以及
(2)更糟糕的是,因为我们限制了连接池中允许的连接数,当多个线程试图从数据库加载项目时潜在的竞争条件。
If the object hierarchy is even three levels deep, using this implementation results in (a) many calls by the framework to datasource.getConnection(), and (2) even worse, since we cap the number of connections allowed in our connection pool, potential race conditions while multiple threads are trying to load a Project from the database.
在Spring中是否有更好的方法(没有另一个完整的ORM工具)来实现这种对象层次结构的加载?
Is there a better way in Spring (without another full-fledged ORM tool) to achieve the loading of such object hierarchies?
谢谢,
Paul
Thanks,Paul
推荐答案
我想你有理由不使用ORM,这是解决此类问题的理想工具。
I guess you have reasons for not using an ORM, which is the ideal tool for this kind of problem.
多个连接的问题是对另一个DAO的递归调用。为避免消耗其他连接,应在获取项目实例后稍后检索Account对象。在获取项目时,也会获取accountID,但不会实例化到帐户实例 - 它们仍然是ID列表,然后在项目DAO完成工作后填充这些ID。
The problem with multiple connections is the recursive call to another DAO. To avoid consuming additional connections, Account objects should be to be retrieved later, after the project instance has been fetched. When fetching the Project, the accountIDs are also fetched, but not "instantiated" to account instances - they remain as a list of IDs, which are then populated after the project DAO has done it's work.
例如,您可以构建一个自定义List类型,该类型包含ID列表和DAO实现。该列表仅使用ProjectRowMapper中的ID填充并分配给项目的accounts属性。这些ID是列表中的私有ID - 它们不是列表的内容,而是稍后生成实际内容的方法。
For example, you can build a custom List type that takes a list of IDs and a DAO implementation. The list is populated with just the IDs in the ProjectRowMapper and assigned to the project's accounts property. The IDs are private to the list - they are not the "contents" of the list, but a means to produce the real contents later.
项目DAO获取后来自RowMapper的项目,然后它可以指示列表然后获取列表中保存的ID的帐户。帐户被取为非嵌套操作,因此整个过程只使用一个连接。然而,fetch是在DAO方法的范围内完成的,所以fetch是热切地完成的 - 因此没有懒惰加载问题需要处理。
Once the Project DAO has fetched the projects from the RowMapper, it can then instruct the list to then fetch the accounts for the IDs that were saved in the list. The accounts are fetched as s non-nested operation and so the whole process only uses one connection at any time. Yet,the fetch is done within the scope of the DAO method, so the fetch is done eagerly - so there are no lazy-loading issues to deal with.
这篇关于Spring Framework JDBC DAO具有agrgegation / composition的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!