com.h3c.util.dao

## Class AbstractBaseDao<I extends Serializable,P extends Storable<I>,T extends Transportable<? super T,I>,F,S>

- java.lang.Object
- - com.h3c.util.dao.AbstractBaseDao<I,P,T,F,S>

- Type Parameters:
    `I` - type of the persistent object and transport object id. This type should be immutable. It is critical this type implements equals() and hashCode() correctly.
    `P` - type of model persistent object
    `T` - type of the transport object
    `F` - type of the associated filter
    `S` - type of the associated sort specification type
  All Implemented Interfaces:
    BaseDao<I,P,T,F,S>
  Direct Known Subclasses:
    AbstractBidirectionalDependentDao, AbstractDao

      public abstract class AbstractBaseDao<I extends Serializable,P extends Storable<I>,T extends Transportable<? super T,I>,F,S>
      extends Object
      implements BaseDao<I,P,T,F,S>

  JPA Abstract Data Access Object.

  This class must remain state-less so it is thread safe.

  Some notes on primary keys:

  A candidate key is a column or a set of columns that could be used to identify a particular row in a table. To become a primary key, a candidate key must satisfy the following properties:

  - Required: Its value (for any column of the candidate key) is never null.
  - Unique: Each row has a unique value.
  - Constant: The value of a particular row never changes.
  If a table has only one identifying attribute, it's, by definition, the primary key. However, several columns or combinations of columns may satisfy the properties for a particular table; you choose between candidate keys to decide the best primary key for the table. Candidate keys not chosen as the primary key should be declared as unique keys in the table.

  A natural key is a key with business meaning: an attribute or combination of attributes that is unique by value of its business semantic (U.S. Social Security Number for example). If a candidate key attribute has meaning outside the database context, it is a natural key, whether or not it is automatically generated.

  Experience has shown that natural keys almost always cause problems in the long run. A good primary key must be unique, constant and required. Few entity attributes satisfy the requirements, and some that do can't be efficiently indexed by SQL databases (although this is an implementation detail and shouldn't be the primary motivation for or against a particular key). Natural keys can only be found only by combining several columns in a composite natural key. These composite keys, although certainly appropriate for some relations (like a link table in a many-to-many relationship), usually make maintenance, ad-hoc queries, and schema evolution much more difficult.

  For these reasons it is recommended to use synthetic identifiers, also called surrogate keys. Surrogate keys have not business meaning - they are unique values generated by the database or application. Application users ideally don't see or refer to these key values; they're part of the system internals. Introducing surrogate key column is also appropriate in a common situation: If there are no candidate keys, a table is by definition not a relation as defined by the relational model -it permits duplicated rows- and so you have to add a surrogate key column.

  Some notes on composite keys:

  If an entity defines a composite key, it is more elegant to define a separate composite identifier class that declares just the key properties, and this is actually forced in this class by the type-parameter I (The entity's id is typed with the generic type).

  Strategies for handling composite keys:

  1. Encapsulate the identifier properties in a separate class and mark it `@Embeddable`, like a regular component. Include a property of this component in your entity class, and map it with `@Id` for an application assigned strategy.
  2. Encapsulate the identifier properties in a separate class without any annotations on it. Include a property of this type in your entity class, and map it with `@EmbeddedId`.
  3. Encapsulate the identifier properties in a separate class. Now duplicate all the identifier properties in the entity class. Then, annotate the entity class with `@IdClass` and specify the name of your encapsulated identifier class.

  For example, suppose you have an `User` entity where the primary key consists of a USERNAME and DEPARTMENT_NUMBER. Then an `UserId` class could be created to keep the primary key attributes:

       public class UserId implements Serializable {
           private String username;
           private int departmentNumber;
           ...
           // Default constructor required by JPA.
           // Constructor expects primary key attributes and validates they are not null.
           // Just setters are exposed.
           // override equals and hasCode properly.
       }

  As for all component mappings, you can define extra mapping attributes on the fields of the entity's class. To map the composite key for `User` , set the generation strategy to application assigned by omitting the `@GeneratedValue` annotation.

  Strategy 1 (This requires to annotate `UserId` and it is not necessary to override properties, they are override in case we need to change the column name for example).

       @Id
       @AttributeOverrides
       (
           {
               @AttributeOverride(name="username", column = @Column(name="USERNAME")),
               @AttributeOverride(name="departmentNumber", column = @Column(name="DEPARTMENT_NUMBER"))
           }
       )
       private UserId userId;

  Strategy 2 (This does not require `UserId` to be annotated).

       @EmbeddedId
       @AttributeOverrides
       (
           {
               @AttributeOverride(name="username", column = @Column(name="USERNAME")),
               @AttributeOverride(name="departmentNumber", column = @Column(name="DEPARTMENT_NUMBER")),
           }
       )
       private UserId userId;

  Strategy 3 (This does not require `UserId` to be annotated).

       @Entity
       @Table(name="Users")
       @IdClass(UserId.class)
       public class User {
           @Id
           private String username;
           @Id
           private int departmentNumber;
           ...
       }

- - ### Constructor Summary

    Constructors
    Modifier | Constructor and Description
    --- | ---
    `protected` | `AbstractBaseDao(Class<P> entityClass)` Construct DAO and initialize query predicate generator.

  - ### Method Summary

    Methods
    Modifier and Type | Method and Description
    --- | ---
    `long` | `count(F filter, DataStoreContext context)` Gets the number of persist objects based on a filter criteria.
    `List<P>` | `find(F filter, SortSpecification<S> sortSpec, DataStoreContext context)` Get the set of persist objects based on the given filter criteria.
    `Page<P>` | `find(F filter, SortSpecification<S> sortSpec, PageRequest pageRequest, DataStoreContext context)` Get the set of persist objects based on the given filter criteria.
    `List<P>` | `findAll(SortSpecification<S> sortSpec, DataStoreContext context)` Gets all the persistent objects.
    `P` | `get(Id<T,I> id, DataStoreContext context)` Get the persistent object with the given id.
    `protected abstract javax.persistence.criteria.Predicate` | `getQueryPredicate(F filter, javax.persistence.criteria.CriteriaBuilder builder, javax.persistence.criteria.Root<P> root)` Augment the underlying database query with specifics to be included as part of the where clause
    `protected QueryPredicateGenerator<P>` | `getQueryPredicateGenerator()` Get the query predicate generator for this type of entity
    `protected abstract javax.persistence.metamodel.SingularAttribute<? super P,?>` | `getSingularAttribute(S sortAttribute)` Gets the singular attribute (JPA entity attribute -Column- definition)
    `protected static <R extends Serializable,E extends Storable<R>,D extends Transportable<? super D,R>> void` | `updateDependents(Collection<E> currentDependents, Collection<D> newDependents, DependentUpdater<E,D> updater)` Updates a collection of dependent entities in a one-to-many relation where this DAO represents the independent entity.

    - ### Methods inherited from class java.lang.Object

      `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- - ### Constructor Detail

    - #### AbstractBaseDao

          protected AbstractBaseDao(Class<P> entityClass)

      Construct DAO and initialize query predicate generator.
      Parameters:
        `entityClass` - persistent object class.

  - ### Method Detail

    - #### get

          public P get(Id<T,I> id,
              DataStoreContext context)

      Description copied from interface: `BaseDao`
      Get the persistent object with the given id.
      Specified by:
        `get` in interface `BaseDao<I extends Serializable,P extends Storable<I>,T extends Transportable<? super T,I>,F,S>`
      Parameters:
        `id` - persistent object's id
        `context` - data store context
      Returns:
        the persistent object

    - #### find

          public List<P> find(F filter,
                     SortSpecification<S> sortSpec,
                     DataStoreContext context)

      Description copied from interface: `BaseDao`
      Get the set of persist objects based on the given filter criteria.
      Specified by:
        `find` in interface `BaseDao<I extends Serializable,P extends Storable<I>,T extends Transportable<? super T,I>,F,S>`
      Parameters:
        `filter` - Filter criteria
        `sortSpec` - sort specification
        `context` - data store context
      Returns:
        A set of persistent object instances

    - #### find

          public Page<P> find(F filter,
                     SortSpecification<S> sortSpec,
                     PageRequest pageRequest,
                     DataStoreContext context)
                                           throws IndexOutOfBoundsException

      Description copied from interface: `BaseDao`
      Get the set of persist objects based on the given filter criteria.
      Specified by:
        `find` in interface `BaseDao<I extends Serializable,P extends Storable<I>,T extends Transportable<? super T,I>,F,S>`
      Parameters:
        `filter` - Filter criteria
        `sortSpec` - sort specification
        `pageRequest` - the page of data desired
        `context` - data store context
      Returns:
        A set of persistent object instances
      Throws:
        `IndexOutOfBoundsException` - if page request is for a page outside the maximum or minimum pages for the request

    - #### findAll

          public List<P> findAll(SortSpecification<S> sortSpec,
                        DataStoreContext context)

      Description copied from interface: `BaseDao`
      Gets all the persistent objects.
      Specified by:
        `findAll` in interface `BaseDao<I extends Serializable,P extends Storable<I>,T extends Transportable<? super T,I>,F,S>`
      Parameters:
        `sortSpec` - sort specification
        `context` - data store context
      Returns:
        A set of persist object instances

    - #### count

          public long count(F filter,
                   DataStoreContext context)

      Description copied from interface: `BaseDao`
      Gets the number of persist objects based on a filter criteria.
      Specified by:
        `count` in interface `BaseDao<I extends Serializable,P extends Storable<I>,T extends Transportable<? super T,I>,F,S>`
      Parameters:
        `filter` - Filter criteria
        `context` - data store context
      Returns:
        The instances count

    - #### getQueryPredicateGenerator

          protected QueryPredicateGenerator<P> getQueryPredicateGenerator()

      Get the query predicate generator for this type of entity
      Returns:
        queryPredicateGenerator to assist with constructing queries

    - #### getQueryPredicate

          protected abstract javax.persistence.criteria.Predicate getQueryPredicate(F filter,
                                                               javax.persistence.criteria.CriteriaBuilder builder,
                                                               javax.persistence.criteria.Root<P> root)

      Augment the underlying database query with specifics to be included as part of the where clause
      Parameters:
        `filter` - The input filter from which the criteria is set.
        `builder` - the criteria builder object for augmenting the query object
        `root` - the root object type associated with the query
      Returns:
        Predicate object to be utilized in the query

    - #### getSingularAttribute

          protected abstract javax.persistence.metamodel.SingularAttribute<? super P,?> getSingularAttribute(S sortAttribute)

      Gets the singular attribute (JPA entity attribute -Column- definition)
      Parameters:
        `sortAttribute` - sort attribute to map a column to.
      Returns:
        the singular attribute associated to the sorting attribute.

    - #### updateDependents

          protected static <R extends Serializable,E extends Storable<R>,D extends Transportable<? super D,R>> void updateDependents(Collection<E> currentDependents,
                                                                                                                  Collection<D> newDependents,
                                                                                                                  DependentUpdater<E,D> updater)

      Updates a collection of dependent entities in a one-to-many relation where this DAO represents the independent entity.
      Type Parameters:
        `E` - type of the dependent persistent object.
        `D` - type of the dependent transport object.
      Parameters:
        `currentDependents` - entities currently persisted as dependents.
        `newDependents` - new dependent entities.
        `updater` - dependent updater.

Copyright © 2014. All Rights Reserved.