Tuesday, 11 April 2017

JPA

ref. to Spring Data JPA

Spring Data

Special feathers

1. Spring Query DSL Data Extension


Benefits of Using JPA

1. Productive, cardinality relationships.
2. Independent of underly database diabetes. Increasing code portabilities.
3. Caching. free to have.  cache holding all entities, and maintain transactions.
4. JPA may generate efficient SQL queries



Persistence

'Persistence' means that the data may be physically stored for retrieving, processing, transforming, or analyzing even the application life cycle has reached the end of the life cycle.


ORM

Java data model is created according to the object-oriented principle. However, in the database, all tables are related to each other via foreign keys and cardinality relationships.

ORM is about how mapping a Plain Java Old Object (POJO) into a relational database table. One object(instance) stands for a row in a database table.  Its attributes are persisted into table columns, excluding ones modified by 'transient'.

Entities

An entity class is a POJO decorated by annotation @Entity. It must follow the following requirements.
  •  It is not inherited from any framework class or interface.
  • The class must be annotated with the Entity annotation.
  • The class must have a public or protected, no-argument constructor. The class may have other constructors.
  • The class must not be declared final. No methods or persistent instance variables must be declared final.
  • If an entity instance is passed by value as a detached object, such as through a session bean’s remote business interface, the class must implement the Serializable interface.
  • ?It may be an abstracted class, which is persisted by its derivatives
  • ?An entity may be extended from an abstract class; abstract class will be a part of the table.
  • ?An entity may be extended from another entity.
  • An entity may be extended from a non-entity class, but the non-entity class is not included in the table.
  • An entity may be extended from a non-entity class but decorated by annotation @MappedSupperClass. The superclass will be included as a part of the table. 
  • Instance attributes must be declared as private, protected, or package-private and can be accessed directly only by the entity class’s getters and setters.
Entity Relationships

Entity relationships(cardinality) are used to describe the instance relationships like one customer may have many orders, one customer must have one address, or one student is enrolled in many courses, meanwhile, a course may be registered by many students, etc.

@OneToOne(owning side can be any side)
@OneToMany and @ManyToOne(owning side at many)
@ManyToMany(@JoinTable)

Fetch types: lazy or eager.
to-one is by default eager.
to-many is by default lazy.

@JoinColumn (owning side, keeping the foreign reference.)
@Mapped (inverse side)

Instance relationship may be bidirectional or unidirectional, describing the dependencies of instances. For a bidirectional relationship, both instances are able to access each other. So they both need to keep a reference that points to another. For a unidirectional relationship, only one side of both instances needs to access the instance at the anther side.

How these instance relationships are mapped into relational database tables?
For bidirectional instance relationships: a designer must know which entity keeps the foreign key. It is called the owning side, thus the opposite side is called the inverse side.

Owning side is annotated by @JoinColumn. It declares a column to store a foreign key, which points to the inverse side. It is also called Children points to the Parrent. 

Inverse side is annotated by @OneToMany(mappedBy = "propertyNameAtOwningSide")
mappedBy means its reference is kept at the owning side as a foreign key.
owning: annotated by @ManyToOne @JoinColumn
inverse: annotated by @OneToMany(mappedBy)
  • One to Many:  Many-side is always owning side, one side is an inverse side(mapped by).
  • One to One: the owning side corresponding to the side to store the foreign key. 
  • Many to Many: owning side at the conjunction table. 

Inverse side
@Entity
@Table(name = "LISTER")
public class Lister extends User {

    @OneToOne(mappedBy = "lister") //inverse side 
    private Yard listedYard;

Owning side:
    @OneToOne
    @JoinColumn(name = "Lister_ID_FK", referencedColumnName = "USER_PK")
    protected Lister lister;

Unidirectional relationship: two entities, only one entity has a field to keep a foreign key to another entity. So it has only the owning side, which should be defined as the following. The key point is to declare the joined column.
    
    @OneToOne
    @JoinColumn(name = "ADDRESS_ID_FK", referencedColumnName = "ADDRESS_ID_PK")
    protected Address address; //owning side keeping FK

Persistence Context

The persistence context is a set of entity instances, which are accessed via an interface, an entity manager. We may manage underlying entities using this interface. The persistence context serves as a first-level cache, buffering the entity instances.

Within the persistence context, the entity instances' lifecycle is managed. An entity instance has four states, i.e. new, managed, removed, or detached.

New state: when an entity is instantiated at the application. It enters the new state.
Managed state: when the instance is persisted, it becomes managed in the persistence context. 
Removed state: when the entity instance is set to be removed, after flushing, its counterpart is deleted from the DB.
Detached state: a managed entity instance becomes not managed, and detached from the PC. 

The EntityManager API is used to create and remove persistence instances, to find entities by their primary key, and query over entities.




Primary Key

The primary key may uniquely identify an entity(entry), thus the entry can be located and fetched back. A primary key could be simple(one field) or composite(multiple fields).

The simple primary key is defined by an annotation @Id 
@Id: Primary key
@GeneratedValue(default strategy = auto-generated)

The composite primary key is defined by an annotation @EmbeddedId, meanwhile, a composite primary key is defined by a  class, decorated with annotation: @Embedable

Large Objects

@Lob(large object): designates BLOB(binary large objects) or CLOB(character large objects)
@Basic: designates the fetching type
BLOB: byte[] Byte[]
CLOB: char[] Characeter[]

Inheritance Mapping 

There are four types to map inheritance strategies.

Mapped Superclass:  

@MappedSuperClass: Table created for each subclass, but not for the superclass; the superclass will be part of the subclass table.

Pros: it is the easiest way to map inheritance; 
Cons: cannot query all superclass in one kick, but having to query from subclass tables one by one.

Single table: 


Table per class:



Joined table:

Each class in the hierarchy is mapped to an independent database table. Superclass and subclasses are designated as Entities; however, the subclass doesn't hold the fields of the superclass. In the database, they are mapped to their own table.






Dealing Collection of Objects

I think there are two ways to handle a collection of objects.
If an entity contains a collection of a basic type of embedded classes, then using the javax.persistence.ElementCollection targetClass, fetch) annotation. Otherwise from a performance view, it would be better to carry out in a one-to-many relationship.
@Entity
public class Person {
    ...
    @ElementCollection(fetch=EAGER)
    protected Set nickname = new HashSet();
    ...
}
Collections may be beyond the List, and Set.

Collections of entity elements and relationships may be represented by java.util.Map collections. A Map consists of a key and a value.

When using Map elements or relationships, the following rules apply.

If the Map value is an entity and part of a many-to-many or one-to-many unidirectional relationship, it will be mapped as a join table in the underlying database. A unidirectional one-to-many relationship that uses a Map may also be mapped using the @JoinColumn annotation.

If the entity is part of a one-to-many/many-to-one bidirectional relationship, it will be mapped in the table of the entity that represents the value of the Map. If generic types are not used, the target entity attribute of the @OneToMany and @ManyToMany annotations must be set to the type of the Map value.

@Embeded  (Entity)
@Embedable (Plain Java Class)

@ElementCollection


@Column: designates a database table column.
@Enumrated: designates a persistent attribute that is an enumeration type.

@Transient (a field having no need to be persisted)





Creating Auditing Using Spring JPA

For a large-scale application, it must track when an entity was created and modified and which user did it.

Spring data automatically do that tracking for you
There are two ways.
1. Decorating Entity with predefined Annotations.

@CreatedDate  : the entity is first persisted
@Column
private ZonedDateTime createdAt;

@LastModifiedBy: the entity's update was last persisted.
@Column
private User updatedBy;

@CreatedBy: an injected user who created the record
@Column
private User createdBy

@LastModifiedDate:  the date last modified.
@Column
private  ZonedDateTime lastModified

2. Entity entends from AbstractAuditable Implements Auditable

@Bean SpringSecurityAuditorAware


Managing Transactions

Required
Supports
Mandatory
Never

References: 

No comments:

Can Jackson Deserialize Java Time ZonedDateTime

Yes, but must include JSR310. Thus ZonedDateTime can be deserialized directly from JSON response to POJO field. <dependency> <g...