Introduzione a JPA(2)

Marco Andreini

Entity lifecycle

Entity Lifecycle

Entity lifecycle(2)

  • le entity che sono nello stato di managed/persistent possono essere modificati dall’applicazione

  • qualsiasi modifica a queste entity è automaticamente identificata e persistita al momento in cui sarà effettuata la flush del Pesistence Context

  • non è necessario effettuare chiamate a metodi particolari per rendere queste modifiche persisitenti

  • ci possono comunque essere altre modalità di gestire le transazioni.

Altre operazioni su EntityManager

In funzione del lifecycle appena visto introduciamo gli ulteriori metodi:

  • contains

  • merge

  • getReference

EntityManager::contains

Per verificare che una istanza di entity sia gestita (managed) dal corrente Persistence Context si utilizza il metodo contains:

 if (entityManager.contains(myBlogEntry)) {
  // ...

EntityManager::merge

  • per rendere una istanza di un’entity gestita e persistente

  • se non esiste ancora (su db) l’istanza viene persistita

  • se esiste già (su db), l’istanza viene aggiornata

 entityManager.merge(myBlogEntry);

EntityManager::getReference

  • Si utilizza per ottenere un oggetto non ancora caricato dal db, ma che contiene i corretti riferimenti.

  • Accetta gli stessi parametri del metodo find:

 BlogEntry entry = entityManager.getReference(BlogEntry.class, 1);
dove 1 è la chiave univoca di ricerca.

@Transient

  • si utilizza sui campi delle entity per indicare che il campo non è persistente

  • tipicamente il valore è calcolato in base ad altri campi

class BlogEntry {
...

  @Transient
  public String getLabel() {
    return title + " " + date;
  }
}

@MappedSuperclass

Viene utilizzata per creare una gerarchia di oggetti che hanno dei campi in comune:

@MappedSuperclass
public abstract class BaseEntity {

  @Id @GeneratedValue
  protected Integer id;

  @Temporal(TemporalType.TIMESTAMP)
  private Date createdAt;

  @Temporal(TemporalType.TIMESTAMP)
  private Date updatedAt;
  //...

@MappedSuperclass(2)

Così altri oggetti possono ereditarne i campi, mantenendo le informazioni su tabelle diverse:

@Entity
public class Person extends BaseEntity {

  @Column(nullable=false)
  private String firstname;

  @Column(nullable=false)
  private String lastname;

  private String phone;

  private String email;
}

Gerarchia di entity

Notare che gli oggetti Person e quindi le righe della tabella person hanno:

  • firstname, lastname, phone, email

  • ma anche id, createdAt, updatedAt

@Embeddable

Con @Embeddable si definisce che le istanza della classe saranno inseribili all’interno di altre entity

@Embeddable
public class Address {    // le istanza di questo oggetto sono persistite
  public String street;   // nell'oggetto che le contiene.
  public String city;
  public String country;
}

@Embedded

Con @Embedded si definisce che l’oggetto indicato dal campo è contenuto in questa entity

@Entity
public class Person {
  @Id
  public Integer id;
  public String firstname;
  public String lastname;

  @Embedded
  public Address address;
}

@Embedded e @Embeddable all’opera

Address address = new Address();
address.setStreet("Crest Hill");
address.setCity("Gotham City");
address.setCountry("United States");

Person person = new Person();
person.setFirstname("Bruce");
person.setLastname("Wayne");
person.setAddress(address);

Il database ha una sola tabella correlata:

idfirstnamelastnamestreetcitycountry

1

Bruce

Wayne

Crest Hill

Gotham City

United States

@Embedded multiple

In caso si voglia avere più istanza di una tipologia @Embedded all’interno di una entity occorre rinominarne le colonne (almeno n-1)

public class Person {
  // ...

  @Embedded
  AttributeOverrides({
    @AttributeOverride(name="street", column=@Column(name = "home_street")),
    @AttributeOverride(name="city", column=@Column(name="home_city")),
    @AttributeOverride(name="country", column=@Column(name = "home_country"))
  })
  private Address home;
  @Embedded
  AttributeOverrides({
    @AttributeOverride(name="street", column=@Column(name = "work_street")),
    @AttributeOverride(name="city", column=@Column(name="work_city")),
    @AttributeOverride(name="country", column=@Column(name = "work_country"))
  })
  private Address work;
}