Upload
madison-hutchinson
View
221
Download
0
Embed Size (px)
Citation preview
OK lets start,who am I ?
Nayden Gochev(a.k.a. JOKe)
JavaSpring
Android
Hybris
GWT
EJBJSF
RMIJAX-RS
StrutsJMS
JPA
Hibernate
C#
ASP.NET
TestStudio
JustMock
WCF
JAX-WS
EntityFrameworkRichFaces
RadControls
DataAccess
MVC
MbUnit WebFormsJustCode
Eclipse
PHP
JavaScript
Objective-C
ExtJS
KendoUI
jQuery UIjQuery
TFSSpring MVC
AngularJS
JPA Advanced Topics
Data Types and Converters
String (char, char[]) VARCHAR (CHAR, VARCHAR2, CLOB, TEXT)
Number (BigDecimal, BigInteger, Integer, Double, Long, Float, Short,
Byte)
NUMERIC (NUMBER, INT, LONG, FLOAT, DOUBLE)
int, long, float, double, short, byte NUMERIC (NUMBER, INT, LONG, FLOAT, DOUBLE)
byte[] VARBINARY (BINARY, BLOB)
boolean (Boolean) BOOLEAN (BIT, SMALLINT, INT, NUMBER)
java.util.Date, java.sql.Date, java.sql.Time, java.sql.Timestamp, java.util.Calendar
TIMESTAMP (DATE, DATETIME)
java.lang.Enum NUMERIC (VARCHAR, CHAR)
java.util.Serializable VARBINARY (BINARY, BLOB)
Relationships Supported Relations in JPA are :
• OneToOne: In this relationship each entity has exactly one reference to the other entity and vice versa.
• OneToMany / ManyToOne: In this relationship one entity can have multiple child entities and each child entity belongs to one parent entity.
• ManyToMany: In this relationship multiple entites of one type can have multiple references to entities from the other type.
• Embedded: In this relationship the other entity is stored in the same table as the parent entity (i.e. we have two entites for one table).
• ElementCollection: This relationship is similar to the OneToMany relation but in contrast to it the referenced entity is an Embedded entity. This allows to define OneToMany relationships to simple objects that are stored in contrast to the “normal” Embedded relationship in another table.
OneToOne
@Entity@Table(name = "T_ID_CARD")public class IdCard {
private Long id;…
@Id@GeneratedValuepublic Long getId() {
return id;}
…}
@Entity@Table(name = "T_PERSON")public class Person {
...private IdCard idCard;...
@OneToOne@JoinColumn(name =
"ID_CARD_ID")public IdCard getIdCard() {
return idCard;}
OneToOne
@OneToOne(fetch = FetchType.EAGER)
The value FetchType.EAGER is the default value and specifies that each time we load a person we also want to load the ID card. On the other hand we can specify that we only want to load the ID when we actually access it by calling person.getIdCard()
@OneToOne(fetch = FetchType.LAZY)
OneToMany@Entity@Table(name = "T_PHONE")public class Phone {
private Long id; private Person person;
…
@Id@GeneratedValuepublic Long getId() {
return id;}
@ManyToOne(fetch = FetchType.LAZY)@JoinColumn(name = "PERSON_ID")public Person getPerson() {
return person;}
…}
@Entity@Table(name = "T_PERSON")public class Person {
private List<Phone> phones = new ArrayList<>();...@OneToMany(mappedBy = "person", fetch = FetchType.LAZY)public List<Phone> getPhones() {
return phones;}
ManyToMany@Entity@Table(name = "T_PROJECT")public class Project {
private Long id;private String title;private List<Geek> geeks
= new ArrayList<Geek>();… @ManyToMany(mappedBy="projects")
public List<Geek> getGeeks() {
return geeks;}
…}
@Entity@Table(name = "T_GEEK")public class Geek {
…private List<Project> projects = new
ArrayList<>();...@ManyToMany@JoinTable(
name="T_GEEK_PROJECT",
joinColumns={@JoinColumn(name="GEEK_ID", referencedColumnName="ID")},
inverseJoinColumns={@JoinColumn(name="PROJECT_ID", referencedColumnName="ID")})
public List<Project> getProjects() {return projects;
}
Embedded / ElementCollection
@Embeddablepublic class Period {
private Date startDate;private Date endDate;
@Column(name ="START_DATE")public Date getStartDate() {
return startDate;}public void setStartDate(Date startDate) {
this.startDate = startDate;}@Column(name ="END_DATE")public Date getEndDate() {
return endDate;}public void setEndDate(Date endDate) {
this.endDate = endDate;}
}
Then to Use Itprivate Period projectPeriod;
@Embeddedpublic Period getProjectPeriod() {
return projectPeriod;}
public void setProjectPeriod(Period projectPeriod) {
this.projectPeriod = projectPeriod;}
@Embeddable Entities in One-to-Many Relations
private List<Period> billingPeriods = new ArrayList<Period>();
@ElementCollection@CollectionTable(
name="T_BILLING_PERIOD",joinColumns=@JoinColumn(name="PROJECT_ID")
)public List<Period> getBillingPeriods() {
return billingPeriods;}
public void setBillingPeriods(List<Period> billingPeriods) {this.billingPeriods = billingPeriods;
}
Inheritance
• SINGLE_TABLE This strategy maps all classes to one single table. It uses a DiscriminatorColumn .
• JOINED - separate table. Join is used when fetching entities which can be slower.
• TABLE_PER_CLASS - separate table but doesn't use JOIN, instead both (or more) tables contain all the information entity needs.
Single@Entity@Table(name = "T_GEEK")public class Geek extends Person {
private String favouriteProgrammingLanguage;private List<Project> projects = new ArrayList<Project>();
@Column(name = "FAV_PROG_LANG")public String getFavouriteProgrammingLanguage() {
return favouriteProgrammingLanguage;}
public void setFavouriteProgrammingLanguage(String favouriteProgrammingLanguage) {
this.favouriteProgrammingLanguage = favouriteProgrammingLanguage;}...
}
//In the database you will notice new column DTYPE
sql> select * from t_person;DTYPE | ID | FIRST_NAME | LAST_NAME | FAV_PROG_LANGPerson | 1 | Homer | Simpson | nullGeek | 2 | Gavin | Coffee | JavaGeek | 3 | Thomas | Micro | C#Geek | 4 | Christian | Cup | Java
Single (2)@Entity@Inheritance@DiscriminatorColumn(name="PERSON_TYPE", discriminatorType = DiscriminatorType.INTEGER)@Table(name=“T_PERSON")public class Person { …}
//then same query will show this result:sql> select * from t_person;PERSON_TYPE | ID | FIRST_NAME | LAST_NAME | FAV_PROG_LANG-1907849355 | 1 | Homer | Simpson | null2215460 | 2 | Gavin | Coffee | Java2215460 | 3 | Thomas | Micro | C#2215460 | 4 | Christian | Cup | Java
Single inheritance ISSUES
• No class discriminator column (if you have OLD legacy database.. which doesn't have discriminator column .. then you need to use crazy stuff like DescriptorCustomizer(EclipseLink) and @ DiscriminatorFormula (Hibernate)
• Non nullable attributes
JOINED @Entity@Inheritance(strategy = InheritanceType.JOINED)@Table(name=“T_PERSON")public class Person { …}
//then same query will show this result:sql> select * from t_person;ID | FIRST_NAME | LAST_NAME1 | Homer | Simpson2 | Gavin | Coffee3 | Thomas | Micro4 | Christian | Cup(4 rows, 12 ms)sql> select * from t_geek;FAV_PROG_LANG | IDJava | 2C# | 3Java | 4(3 rows, 7 ms)
JOINED inheritance ISSUES
• Poor query performance
• Do not have/want a table for every subclass
TABLE_PER_CLASS @Entity@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)public abstract class Project { @Id private long id; ...}
@Entity@Table(name="LARGEPROJECT")public class LargeProject extends Project { private BigDecimal budget;}
@Entity@Table(name="SMALLPROJECT")public class SmallProject extends Project {}
TABLE_PER_CLASS inheritance ISSUES
• Poor query performance - The main disadvantage to the table per class model is queries or relationships to the root or branch classes become expensive.
• Issues with ordering and joins Because table per class inheritance requires multiple queries, or unions, you cannot join to, fetch join, or traverse them in queries. Also when ordering is used the results will be ordered by class, then by the ordering.
Mapped Superclass • Mapped superclass inheritance allows
inheritance to be used in the object model, when it does not exist in the data model. It is similar to table per class inheritance, but does not allow querying, persisting, or relationships to the superclass. Its main purpose is to allow mappings information to be inherited by its subclasses.
• The subclasses are responsible for defining the table, id and other information, and can modify any of the inherited mappings
MappedSuperclass @MappedSuperclasspublic abstract class Project { @Id private long id; @Column(name="NAME") private String name; ...}
@Entity@Table(name="LARGEPROJECT")@AttributeOverride(name="name", column=@Column(name="PROJECT_NAME"))public class LargeProject extends Project { private BigDecimal budget;}
@Entity@Table("SMALLPROJECT")public class SmallProject extends Project {}
Mapped Superclass Issues
• Cannot query, persist, or have relationships.
• You also cannot have a relationship to a mapped superclass
Criteria APICriteriaBuilder builder = entityManager.getCriteriaBuilder();CriteriaQuery<Person> query = builder.createQuery(Person.class);Root<Person> personRoot = query.from(Person.class);query.where(builder.equal(personRoot.get("firstName"), "Homer"));List<Person> resultList = entityManager.createQuery(query).getResultList();
//or we can write
query.where(builder.and(builder.equal(personRoot.get("firstName"), "Homer"), builder.equal(personRoot.get("lastName"), "Simpson")));
In general CriteriaQuery defines the following clauses and options:distinct(), from(), select(), multiselect(), where(),orderBy(), groupBy(), having(), subquery()
ContactsBlog : http://gochev.orgFacebook: https://www.facebook.com/gochevLinkedin: https://www.linkedin.com/in/gochevSkype: joke.gochevGitHub : https://github.com/gochev/