Wednesday 16 June 2010

Specificarea relaţiilor dintre entităţile JPA

Există patru tipuri de relaţii între entităţile JPA, şi anume:

Relaţii ``unul cu unul'' (One-to-One)
Relaţii ``unul cu mai mulţi''(One-to-Many)
Relaţii ``mai mulţi cu unul''(Many-to-One)
Relaţii ``mai mulţi cu mai mulţi'' (Many-to-Many)

O relaţie poate fi unidirecţională sau bidirecţională. Într-o relaţie unidirecţională, una şi numai una dintre entităţi conţine un câmp care se referă la cealaltă entitate. Într-o relaţie bidirecţională, fiecare dintre entităţi conţine un câmp care se referă la cealaltă. Direcţia relaţiei dintre două entităţi determină posibilitatea unei interogări (query) de a naviga de la o entitate la cealaltă. Implementarea relaţiilor în contextul de persistenţă, care determină modul în care se fac actualizările în baza de date, se realizează prin adnotarea câmpurilor care se referă la entităţile relaţionate, în funcţie de tipul relaţiei, cu @OneToOne, @ManyToOne@OneToMany, @ManyToMany, @JoinColumn, @JoinTable, etc.

Exemple

@Entity
@Table(name="CURSURI")

@NamedQueries({
@NamedQuery(name="Cursuri.numeTitular",
    query="select o.profesor from Cursuri o " +
          "where o.cursId = :param"),
@NamedQuery(name="Cursuri.studentiInscrisi",
        query="select o.studenti from Cursuri o " +
          "where o.cursId = :param")
})

public class Cursuri implements Serializable{

@Id
@Column(name="CURSID", nullable=false)
private int cursId;

@Column(name="NUME")
private String nume;

//mai multe cursuri la un profesor

@ManyToOne
@JoinColumn(name="PROFESORID",referencedColumnName="PROFESORID")
private Profesori profesor;


//mai multe cursuri la un student, mai multi studenti la un curs
@ManyToMany
@JoinTable(name="STUD_CURS",
       joinColumns=
           @JoinColumn(name="CURSID",referencedColumnName="CURSID"),
       inverseJoinColumns=
           @JoinColumn(name="STUDENTID",referencedColumnName="STUDENTID"))
//name=numele coloanei din tabela STUD_CURS (tabela de join)
//referencedColumnName=numele coloanelor din tabelele CURSURI, respectiv STUDENTI
private List studenti;

...

@Entity
@Table(name="STUDENTI")

@NamedQuery(name="Studenti.note",
    query="select o.note from Studenti o " +
          "where o.studentId = :param")

public class Studenti implements Serializable{

@Id
@Column(name="STUDENTID", nullable=false)
private int studentId;

@Column(name="NUME")
private String nume;

@Column(name="PRENUME")
private String prenume;

@Column(name="EMAIL")
private String email;

@OneToOne
@JoinColumn(name="STUDENTID",referencedColumnName="STUDENTID")
private Note note;

...

@Stateless(name="FatadaCursuri")
public class FatadaCursuriBean implements FatadaCursuri{

@PersistenceContext(unitName="CelestePersistUnit")
EntityManager em;

public String cautaTitular(int id){

Profesori titular = (Profesori)em.createNamedQuery("Cursuri.numeTitular").
            setParameter("param",id).getSingleResult();

return titular.citesteNume();

}

public List cautaStudenti(int idCurs){

List listaStudenti = (List)em.createNamedQuery("Cursuri.studentiInscrisi").setParameter("param",idCurs).getResultList();
return listaStudenti;

}

public Note cautaNote(int idStud){

Note note = (Note)em.createNamedQuery("Studenti.note").
            setParameter("param",idStud).getSingleResult();

return note;

}

public List getGradesforOneStudent(int idStud){
List note = (List)em.createNamedQuery("Grades.forOneStudent").
            setParameter("param",idStud).getResultList();

return note;
}

}

Tuesday 1 June 2010

Gestiunea tranzacţiilor

În limbajul ingineriei software tranzacţiile reprezintă tehnologia care asigură integritatea datelor, controlând accesul concurent la date şi împiedicând actualizarea parţială în cazul apariţiei unei erori în mijlocul execuţiei unui program. Putem defini o tranzacţie ca pe un grup de operaţii dintre care fie se execută toate, fie nu se execută niciuna. O tranzacţie este o unitate indivizibilă de lucru (unit of work).
 
De exemplu, într-o aplicaţie de eLearning, modificarea unei note poate necesita mai mulţi paşi:

begin
  modifica nota
  recalculeaza media
  refa clasamentul
commit

O tranzacţie trebuie să fie atomică (se execută în totalitate sau nu se execută deloc), consecventă (păstrează integritatea bazei de date), izolată (stările intermediare ale sistemului nu sunt vizibile în exterior pâna la încheierea tranzacţiei) şi durabilă (înainte de încheierea tranzacţiei, modificările efectuate de aceasta vor fi scrise într-o memorie fizică, astfel încât să poată fi recuperate chiar în cazul unei căderi a sistemului) (ACID).

Tranzacţii gestionate de container

Într-o componentă de tip sesiune sau bazată pe mesaje care nu specifică tipul de gestiune a tranzacţiilor, codul pe care îl scrieţi nu va conţine instrucţiuni care să marcheze începutul sau sfârşitul tranzacţiilor, acestea fiind setate de către container. Containerul va începe, suspenda şi încheia tranzacţiile în funcţie de valoarea unui atribut specificat pentru fiecare metodă cu adnotarea @TransactionAttribute. Valoarea acestui atribut poate fi una dintre următoarele: REQUIRED, REQUIRES_NEW, MANDATORY, NOT_SUPPORTED, SUPPORTS, NEVER.

Semnificaţiile acestor valori sunt explicate în detaliu aici: http://java.sun.com/javaee/6/docs/tutorial/doc/bncij.html

Tranzacţii gestionate de componente

Interfaţa de programare JTA (Java Transaction API) defineşte metode pentru iniţierea şi terminarea explicită a tranzacţiilor (begin, commit, rollback).