How to Access the Persistence Layer

From SONIVIS:Wiki

Jump to: navigation, search

Contents

Introduction

We currently provide you with a persistence layer based on a MySQL 5.0 database. For accessing that database one may use the interfaces of data access objects (DAOs) in the package de.sonivis.tool.core.datamodel.dao or an implementation of these in the package de.sonivis.tool.core.datamodel.dao.spring.hibernate. There is also a package named de.sonivis.tool.core.datamodel.dao.spring.jpa, an implementation of the Spring framework's data access using the Java Persistence API (JPA). Since the latter is hardly tested we strongly recommend to use the Spring/Hibernate package.

Data Access Objects

As you can see from our data model we have several entities that represent different kinds of data. These entities are

  • InfoSpace
  • InfoSpaceItem
    • Actor
    • ContentElement
    • Context
    • Interaction
    • Knowledge
  • GraphItem
    • Edge
    • Graph
    • Node
  • Property
    • InfoSpaceItemProperty
    • GraphItemProperty
  • InfoSpaceItemType

For each of these entities there is a corresponding class in the package de.sonivis.tool.core.datamodel.hib, also referred to as plain old Java objects (POJOs). These are the data types you will get when you retrieve data from the database via the DAOs. The de.sonivis.tool.core.datamodel.dao.spring.hibernate package provides you with the necessary DAOs named according to the POJOs they retrieve, i.e. ActorDAO.java for Actor objects, EdgeDAO.java for Edge objects, and so on. Note, though, that InfoSpaceItem.java, GraphItem.java, and Property.java are abstract classes. Therefore, no corresponding DAOs are provided. Currently, there is no InfoSpaceItemTypeDAO in the de.sonivis.tool.core.datamodel.dao.spring.jpa package.


Retrieved POJOs

You will expect the POJOs you retrieve by accessing the DAOs to be complete and have all their methods work properly. This is currently not exactly the case. You might experience access problems with methods that are supposed to return another POJO, like, i.e. InfoSpaceItemType or the ContentElements of a Context. This is due to the default Hibernate strategy of lazy fetching, in other words, Hibernate tries to access the content of POJOs in fields of other POJOs in the moment they are requested.

But it also depends on the way the DAO methods are implemented: Each one starts, when called, its own session, accesses the persistence layer, and closes that session thereafter. Thus, in the moment of access to a POJO method no session is available to retrieve the expected object and an exception will be thrown. We decided on a non-lazy fetching method for most POJOs that are part of other POJOs. In case of InfoSpace we held on to lazy fetching since accessing the InfoSpace of a POJO would possibly lead to having the whole database extracted.


Basic Access Functionality

For the most common requests on the database the DAOs provide a basic set of access methods. Generally, all classes implement the following methods of the interface IGenericDAO. These represent more or less the equivalents in SQL noted at the end of each line.

Java SQL
Integer count() SELECT count(*) FROM T
EventList<T> findAll() SELECT * FROM T
T findBySerial(Long serial) SELECT * FROM T WHERE serialID = serial
void remove(T) DELETE FROM T ...
void removeAll(Collection<T>) DELETE FROM T ...
void save(T) INSERT INTO T VALUES ...
void saveAll(Collection<T>) INSERT INTO T VALUES ...
T update(T) UPDATE T ...


count

To get the amount of all currently persisted entities of a certain type the count() method will suffice. It returns an Integer of the amount which equals 0 if no entities are present. There is also a count() method with a different signature for InfoSpaceItem<code>s.

findAll

To get all entities of a certain type this method will help out. You receive an <code>EventList (visit Glazed Lists Homepage for details) containing all objects that the persistence layer holds. Since you cannot tell the data type of the objects held by the returned EventList you may use the helper method findAllType() which returns the type's class to find out.

findBySerial(Long)

This method allows to retrieve an entity by its database-generated unique identifier. The uniqueness relates to the class as well as to the class hierarchy the class belongs to (Note, not in case of Property). So, each InfoSpaceItem has a unique serial and you won't find, i.e. an Actor and a ContentElement with the same serial. Therefore, the setter for the serial is private. Thus, the usefulness of the serial outside the persistence layer is limited. You have to know it in advance to get precisely the entity you expect. On the other hand side, you can persist the same Java object several times leading to clones with different serials.

remove

To delete a persistent entity from the persistence layer use this method. It will not return any information on the state of success of operation but if you encounter exceptions during execution something might have went wrong.

removeAll

If there is need to delete several entities at once that functionality is provided with this method. Alike remove() it returns void.

save

To persist a certain transient object in the persistence layer the save(T) method provided by the correpsonding DAO class is to be used. Note, that this holds for objects that are new to the persistence layer, i.e. transient. Do not try to use this method on an object that was retrieved from the database before, modified then and should be persisted again since this will cause exceptions to be thrown. For this case use the update(T) method described below.

saveAll

To store several transient objects at once one can use this method instead of repeatedly calling save().

update

An object that was retrieved from the database, modified and is to be persisted then should be passed to the update(T) method of the corresponding DAO class. There are good reasons to return the object that was persisted after the operation. Since an ID generation strategy internal to the database is used, the object you receive is not exactly equal to the one you passed as the argument. The returned object will, i.e., provide the generated IDs (serial field) of newly added properties.


Specific Access Functionality

The implementations for DAOs of specific entity classes specify further access methods. In general, these methods provide search on a value of a field of the class. Note though, that there is no necessity to have any meaningful fields in any of the InfoSpaceItem or GraphItem classes since all these could be represented within the properties of the class. For reasons of better handling and faster access we decided to have real fields for certain properties of entities.

Note! All methods that return an EventList containing objects of a certain type
are accompanied by a no-argument helper method of the same name having Type appended to the method
name. The helper methods return the class of the type that is contained in the EventList.
I.e., EventList<ContentElement> findByName(String) and Class<ContentElement> findByNameType()

InfoSpaceItem

All child classes of InfoSpaceItem, i.e. #Actor, #ContentElement, #Context, #Interaction, and #Knowledge, can be searched for the InfoSpace they belong to by calling the method findByInfoSpace(Long) specifying an InfoSpace serial (see #Retrieved POJOs for some details on access to the InfoSpace of an InfoSpaceItem).

Also one can get a collection of entities that share the same InfoSpaceItemType by calling findByInfoSpaceItemType(int) with the appropriate identifier of the InfoSpaceItemType to be looked for.

There is also a special count() method for InfoSpaceItems as mentioned before. Call count(InfoSpaceItemType) to count all entities of the InfoSpaceItem that share the same InfoSpaceItemType. It will return an Integer value >= 0 of the amount of matching entities.

Actor

The Actor entity, as well as the #ContentElement entity, provide the special field:

  • externalId

It is of a Long data type and may (but is not required to) hold the ID the entity had within its source system. It could also contain an individually assigned ID. The method

  • EventList<Actor> findByExternalId(Long)

allows to search for entities matching the value on this field. Note, the return type of findByExternalId(Long) is an EventList. Why so when searching for an ID? Well, the field itself is not required to be unique (not even non-null). Only in conjunction with the InfoSpaceItemType field uniqueness should be taken care of, though it's not enforced yet. To find exactly the entity you are looking for the

  • Actor identifyExternally(Long, InfoSpaceItemType)

will help out and returns the requested object (or null if not existent) identified by its external ID and the InfoSpaceItemType. (Note, the first entity from the internally retrieved list will be picked. If ) Besides these, the DAO implementation provides three more methods for retrieving entities:

  • EventList<Actor> findByName(String)
  • EventList<Actor> findRegisteredAfter(Date)
  • EventList<Actor> findRegisteredBefore(Date)

The findByName(String) method currently only matches exact name strings. Providing Administrator as argument string will retrieve all currently stored Actor entities with the exactly matching string and will not find names like, i.e., Co-Administrator, administrator, or AdMiNiStRaToR. In SQL this would be something like SELECT * FROM actor WHERE name = 'Administrator'. This might be relaxed in future.

The methods for searching the registered field are inclusive according to the argument. So if you provide a date, i.e., 2007-01-08, 13:55:27, all Actors that registered at exactly 2007-01-08, 13:55:27 will be included.

ContentElement

The ContentElement entities also have the special field

  • externalId

Refer to the #Actor section above for an explanation of the methods connected to it. Further, the following methods are provided:

  • EventList<ContentElement> findByName(String)
  • EventList<ContentElement> findCreatedAfter(Date)
  • EventList<ContentElement> findCreatedBefore(Date)
  • EventList<ContentElement> findCreatedBetween(Date,Date)

As with Actors, the findByName(String) method only retrieves exact matches and the methods searching on the created field are including ContentElements matching the specified date exactly.

Context

The Context DAO implements the following methods:

  • EventList<Context> findSources(Long)
  • EventList<Context> findSources(Collection<ContentElement>)
  • EventList<Context> findTargets(Long)
  • EventList<Context> findTargets(Collection<ContentElement>)
  • EventList<Context> findAllRelationships(Long)
  • EventList<Context> findAllRelationships(Collection<ContentElement>)
  • EventList<Context> findAllUniqueRelationships(Long)
  • EventList<Context> findAllUniqueRelationships(Collection<ContentElement>)

The findSources() methods allow you to either specify a ContentElement serial or a collection of ContentElements to retrieve an EventList holding all Contexts with a matching target. The findTargets() do the same with matching sources while findAllRelationships() combine the former two to match the the specified ContentElement(s) against the source as well as the target field. Since two ContentElements may share several Contexts the findAllUniqueRelationships() retrieves only a single representative for multiple relationships.

Interaction

While a #Context entity represents a relationship between #ContentElements, Interactions represent relations between #Actors. The provided methods are, thus, equivalent:

  • EventList<Interaction> findSources(Long)
  • EventList<Interaction> findSources(Collection<Actor>)
  • EventList<Interaction> findTargets(Long)
  • EventList<Interaction> findTargets(Collection<Actor>)
  • EventList<Interaction> findAllRelationships(Long)
  • EventList<Interaction> findAllRelationships(Collection<Actor>)
  • EventList<Interaction> findAllUniqueRelationships(Long)
  • EventList<Interaction> findAllUniqueRelationships(Collection<Actor>)

See #Context for explanations.

Knowledge

The relations between an Actor and a ContentElement are described by Knowledges. The offered DAO methods let you search by either matching Actors or ContentElements:

  • EventList<Knowledge> findByContentElement(Long)
  • EventList<Knowledge> findByContentElement(Collection<ContentElement>)
  • EventList<Knowledge> findByActor(Long)
  • EventList<Knowledge> findByActor(Collection<Actor>)


GraphItem

There are no general methods for searching GraphItems.

Edge

Edges connect two Nodes and may directed or not. To retrieve all directed Edges use findDirected(), to get the undirected use findUndirected(). Uniting both sets leads to the same result as calling findAll().

To get all Edges where a certain Node is part of call findNeighbours(Long) with the Node's serial as argument. For a collection of Edges that point to a certain Node calling findPredecessors(Long) with Node's serial as argument is appropriate whereas findSuccessors(Long) works for Edges where the Node with the specified serial is the source of.

Graph

A GraphDAO implementation provides you with the methods

  • EventList<Graph> findByName(String)
  • EventList<Graph> findByInfoSpace(Long).

The argument of findByName(String) must be an exact match of the Graph's name. findByInfoSpace(Long) retrieves a collection of all Graphs that represent the InfoSpace given by the specified serial.

Node

There are no special methods to search for Nodes.


Property

There are two general search methods that apply to child classes of Property:

  • EventList<Property> findByName(String)
  • EventList<Property> findByTypeFQN(String)

Both retrieve as collection of items whose name (or fully qualified name, resp.) are exact matches.

GraphItemProperty

A collection of GraphItemPropertys a GraphItem has can be retrieved by calling findByGraphItem(Long) with GraphItem's serial as an argument.

InfoSpaceItemProperty

A collection of InfoSpacePropertys a InfoSpaceItem has can be retrieved by calling findByInfoSpaceItem(Long) with InfoSpaceItem's serial as an argument.

InfoSpaceItemType

You can search for an InfoSpaceItemType by the type's name:

  • EventList<InfoSpaceItemType> findByName(String)

Although that method returns a collection this should usually contain no more than one item.


Direct Access

We decided to use the Spring framework when implementing the access to the persistence layer. It provides a lot of useful functionality on the issues of data access. In the packages implementing the DAOs there is an abstract parent class for all DAO implementations that extends the Spring framework.

Hibernate

The Spring/Hibernate style access to the persistence layer is provided in the de.sonivis.tool.core.datamodel.dao.spring.hibernate package. The abstract parent class of the package is name AbstractGenericDAO.java and extends Spring's HibernateDaoSupport (refer to the API Doc). Using this strategy provides each caller to use the whole functionality therein. One may pose handcrafted SQL statements in standard SQL or the Hibernate Query Languag (HQL) to get the requested data. See the API Doc of HibernateTemplate to check the options.

JPA

The Spring/JPA style access to the persistence layer is provided in the de.sonivis.tool.core.datamodel.dao.spring.jpa package. The abstract parent class of the package is name AbstractGenericDAOImpl.java and extends Spring's JpaDaoSupport (refer to the API Doc). Using this strategy provides each caller to use the whole functionality therein. One may pose handcrafted SQL statements to get the requested data. See the API Doc of JpaTemplate to check the individual options provided within.


Links

Personal tools