Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Update (23-05-2007): I've totally reimplemented persistent identifiers in DSpace as well (see PersistentIdentifiers ). As well as removing the Handle System dependency, they also use DAOs. --JR

Update (20-06-2007): After a bit of a hiatus while I PersistentIdentifiers I've come back to DAOs, and I've now (mostly) got them in place for Bitstreams as well. The two major classes that still need doing are EPerson and Group_; once they're done, there are a few others (eg:_ SupervisedItem_,_ WorkspaceItem_, etc) but they should be relatively simple._ --JR

Just adding a comment that Handle/Pid management could be greatly improved by such an addition as well. currently with item caching, the DSpaceObject.getHandle method can become stale and using DAO's behind the scene for the HandleManagement might be beneficial -- Mark Diggory 13:56, 10 May 2007 (EDT)

Update (14-08-2007): Everything (apart from the code in org.dspace.checker_) has been pushed through the DAO layer. Non-DAO classes no longer_ import the DatabaseManager or throw SQLExceptions. There are interfaces for CRUD and link operations in org.dspace.storage.dao that I intend to write some tests to for throwing at all the implementing DAOs. - -JR

...

It has often struck me that DSpace would benefit from the use of Data Access Objects (DAO). If nothing else, it would make porting to alternative database platforms far easier; all we would need to do is provide alternative implementations for the DAO interfaces that worked for a given database. To this end, I have broken up some of the core classes in org.dspace.content to use DAOs.

...

This will be a fairly simple proxy implementation. Specifically, it will be closest to being a virtual proxy, in that it will appear to be a regular Item object, but will have a slightly smarter implementation (not loading metadata until requested, keeping track of what has changed to make updates more efficient etc). 

Panel
Wiki Markup
public class ItemProxy extends Item

...


{

...

 // Overrides relevant methods of Item.

...

 }

org.dspace.content.dao.ItemDAO

This isn't final, but it's a good start. 

Panel
Wiki Markup
public interface ItemDAO extends ContentDAO

...


implements CRUD<Item>, Link<Item, Bundle>

...


{

...

 public Item create(); throws AuthorizeException

...

 public Item retrieve(int id);

...

 public Item retrieve(UUID uuid);

...

 public void update(Item item); throws AuthorizeException

...

 public void delete(int id); throws AuthorizeException

...

 public List<Item> getItems();

...

 public List<Item> getItemsBySubmitter(EPerson eperson);

...

 public List<Item> getItemsByCollection(Collection collection);

...

 public List<Item> getParentItems(Bundle bundle);

...

 }

org.dspace.content.dao.ItemDAOFactory

public

class

ItemDAOFactory


{


public

static

ItemDAO

getInstance(Context

context)


{

//

Eventually,

the

implementation

that

is

returned

will

be

//

defined

in

the

configuration.

return

new

ItemDAOPostgres(context);

}

}


}

Panel
Wiki Markup

org.dspace.content.dao.postgres.ItemDAOPostgres

This is a fairly straightforward implementation of the above interface. As much as possible, code from the original Item class will be used. For instance, this is how getItems() is implemented:

Panel
Wiki Markup

...

public List<Item> getItems()
{

...

try

...

{

...

TableRowIterator tri = DatabaseManager.queryTable(context, "item",

...

"SELECT item_id FROM item WHERE in_archive = '1'");

...

List<Item> items = new ArrayList<Item>();

...

for (TableRow row : tri.toList())

...

{

...

 

...

int id = row.getIntColumn("item_id");

...

 items.add(retrieve(id));

...

 

...

}

...

return items;

...

}

...

; catch (SQLException sqle)

...

{

...

 

...

// Need to think more carefully about how we deal with SQLExceptions

...

 

...

throw new RuntimeException(sqle);

...

 

...

}

...

}
Some changes have been made to eliminate <code>ItemIterator</code>s, and to generally make things a little more consistent with the rest of the code (this looks almost identical to, eg, CollectionDAO.getCollections().

...

The idea behind this class came from the realisation that Item.withdraw() and Item.reinstate() don't really make sense. What I'd much rather do is call (eg) ArchiveManager.withdrawItem(Item item).
I've been thinking that the ArchiveManager could be used for certain maintenance operations as well, such as moving Items between Collections, and maybe acting as a wrapper for the CommunityFiliator.

Panel
Wiki Markup

&nbsp;public class ArchiveManager
&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp; public static void withdrawItem(Context context, Item item)
&nbsp;&nbsp;&nbsp;&nbsp; { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // ... &nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; public static void reinstateItem(Context context, Item item)
&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // ...&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; public static void moveItem(Context context,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Item item, Collection source, Collection dest)
&nbsp;&nbsp;&nbsp;&nbsp; { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // ... &nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;}

org.dspace.storage

...

As suggested by Richard Jones, there probably ought to be a top-level general-purpose DAO interface that has implementations for the various storage mechanisms GlobalDAOPostgres etc). The idea is to have this top-level object capture any implementation-specific details in a single top-level object, rather than in every Postgres DAO implementation. For example, with the current database "abstraction layer", the top-level implementation of GlobalDAO understands the Context object, whereas a Hibernate implementation would know what a SessionFactory is.

Panel
Wiki Markup

&nbsp;public interface GlobalDAO
&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp; // The following methods actually currently throw SQLExceptions to &nbsp;&nbsp;&nbsp;&nbsp; // keep things simple, but in future SQLExceptions should be &nbsp;&nbsp;&nbsp;&nbsp; // eliminated from any code that doesn't directly touch a database. &nbsp;&nbsp;&nbsp;&nbsp; public void startTransaction() throws GlobalDAOException; &nbsp;&nbsp;&nbsp;&nbsp; public void endTransaction() throws GlobalDAOException; &nbsp;&nbsp;&nbsp;&nbsp; public void saveTransaction() throws GlobalDAOException; &nbsp;&nbsp;&nbsp;&nbsp; public void abortTransaction(); &nbsp;&nbsp;&nbsp;&nbsp; public boolean transactionOpen(); &nbsp;&nbsp;&nbsp;&nbsp; @Deprecated Connection getConnection(); &nbsp;}

...

Implementation of the GlobalDAO interface for PostgreSQL.

Panel
Wiki Markup
&nbsp;public class GlobalDAOPostgres implements GlobalDAO
&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp; private Connection connection;
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; // ...
&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; public void startTransaction()
&nbsp;&nbsp;&nbsp;&nbsp;

...

     {
        connection = DatabaseManager.getConnection();

...


        connection.setAutoCommit(false);

...

&nbsp;

...


&nbsp;

...

&nbsp;&nbsp;&nbsp;

...

 // ...
&nbsp;}

...

Wiki Markup
\[\[Category:Refactoring\]\]