1 / 99

Java Persistence: Core Object/Relational Mapping

Java Persistence: Core Object/Relational Mapping. Goals. Be able to map a single class and properties to the database using class annotations and ORM descriptors Be able to get and set properties using get/set API calls instead of SQL. Objectives. Entities class annotations

pestella
Download Presentation

Java Persistence: Core Object/Relational Mapping

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Java Persistence: Core ORM Java Persistence:Core Object/RelationalMapping

  2. Java Persistence: Core ORM Goals • Be able to map a single class and properties to the database using class annotations and ORM descriptors • Be able to get and set properties using get/set API calls instead of SQL

  3. Java Persistence: Core ORM Objectives • Entities • class annotations • orm.xml descriptor • Primary Key Generation • Primary Keys • simple • composite • Fine Tuning Objects • Multi-table Mappings • Secondary Tables • Embedded Objects

  4. Java Persistence: Core ORM Entities • Plain Old Java Object (POJO) Classes • Instantiated and used just like any other POJO Bike bike = new Bike(1); bike.setMake("trek"); bike.setModel("2200"); bike.setSize(26); • Mapped to the database schema • Interact with EntityManager to perform persistence operations em.persist(bike); Bike bike2 = em.find(Bike.class, 1); em.remove(bike2); • Must • have a no-arg constructor (spec says non-private; hibernate can work with private) • be denoted as an Entity (either within class or descriptor) • have at least 1 field/property labeled as Id

  5. Java Persistence: Core ORM Annotated Entity Example: Bike.java package ejava.examples.orm.core.annotated; import javax.persistence.*; //brings in JPA Annotations @Entity //tells ORM that this class can be mapped public class Bike { private long id; private String make; private String model; private int size; public Bike() {} public Bike(long id) { this.id = id; } @Id //tells ORM that this property provides pk simple value public long getId() { return id; } @SuppressWarnings("unused") //ORM will use this to set pk value private void setId(long id) { this.id = id; } public String getMake() { return make; } public void setMake(String make) { this.make = make; } ... }

  6. Java Persistence: Core ORM Non-Annotated Entity Example: Bike.java package ejava.examples.orm.core.mapped; public class Bike { private long id; private String make; private String model; private int size; public Bike() {} public Bike(long id) { this.id = id; } //orm.xml file will map this field to Identity public long getId() { return id; } @SuppressWarnings("unused") //ORM will use this to set pk value private void setId(long id) { this.id = id; } public String getMake() { return make; } public void setMake(String make) { this.make = make; } ... }

  7. Java Persistence: Core ORM Entity Example: META-INF/persistence.xml <?xml version="1.0" encoding="UTF-8"?> <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0"> <persistence-unit name="ormCore"> <!-- These could have been rolled into a single file. META-INF/orm.xml is the default location for a single file approach. --> <mapping-file>orm/Bike-orm.xml</mapping-file> <mapping-file>orm/Car-orm.xml</mapping-file> ... <properties> <property name="hibernate.hbm2ddl.auto" value="create"/> ... </properties> </persistence-unit> </persistence>

  8. Java Persistence: Core ORM Non-Annotated Entity Example: Bike-orm.xml <?xml version="1.0" encoding="UTF-8"?> <entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_1_0.xsd" version="1.0"> <entity class="ejava.examples.orm.core.mapped.Bike" access="PROPERTY" metadata-complete="true" name="MappedBike"> <!-- name used to avoid name collision with annotated Bike example --> <table name="Bike"/> <attributes> <id name="id"/> </attributes> </entity> </entity-mappings>

  9. Java Persistence: Core ORM Example Directory Layout target/classes/ |-- META-INF | `-- persistence.xml |-- ejava | `-- examples | `-- orm | `-- core | |-- annotated | | |-- Bike.class | `-- mapped | |-- Bike.class `-- orm |-- Bike-orm.xml

  10. Java Persistence: Core ORM Entity Name • Defaults to unqualified name of entity class • Used to determine default table name • Bike class -> Bike table • SQL from Hypersonic log... create table Bike (id bigint not null, make varchar(255), size integer not null, model varchar(255), primary key (id)) • Used to refer to class in EJB-QL • Can be assigned using optional name property • @Entity(name=”entity_name”) • Table name can be specified separate from entity name • @Table(name=”table_name”)

  11. Java Persistence: Core ORM Field/Property Access using @Id • Labels fields/properties used for primary key • Determines access type for remaining values • field – direct access to fields within class @Entity public class Bike { @Id private long id; • property – access through getter/setter methods @Entity public class Bike { private long id; ... @Id //annotation must be on getter method; not setter public long getId() { return id; } private void setId(long id) { this.id = id; }

  12. Java Persistence: Core ORM Field/Property Access using orm.xml • FIELD <entity class="ejava.examples.orm.core.mapped.Bike" access="FIELD" metadata-complete="true" name="MappedBike"> <table name="Bike"/> <attributes> <id name="id"/> </attributes> </entity> • PROPERTY <entity class="ejava.examples.orm.core.mapped.Bike" access="PROPERTY" metadata-complete="true" name="MappedBike"> <table name="Bike"/> <attributes> <id name="id"/> </attributes> </entity>

  13. Java Persistence: Core ORM Getting Started • Java First • appropriate for quick prototypes • most vendors provide tools to create database schema from Java classes • database schema maps closely to Java classes and has not been optimized • less use of javax.persistence metadata because defaults sufficient for functionality of prototype • Database Schema First • common in legacy environments and large developments • vendors provide tools to create Java classes from database schema • Java classes map closely to database schema and do not necessarily represent the business or uses of the application • more use of javax.persistence metadata required to use proper business classes with existing schema

  14. Java Persistence: Core ORM Elementary Schema Mappings • Core Mappings • @Table.name – assigns table name • @Column.name – assigns column name • More detailed attributes • only necessary when generating schema • @Column • unique – column will be defined as being unique • nullable – column will be defined as being nullable • insertable – column will be included in inserts • updatable – column will be included in updates • table – maps column to table separate from class • length – length of VARCHAR() when using a String • precision – defines # digits in NUMERIC types • scale – defines # digits to right of decimal in NUMERIC types • columnDefinition – exact DDL to use for schema

  15. Java Persistence: Core ORM Example Database Schema for Mapping create table ORMCORE_CAR ( CAR_ID bigint not null, CAR_YEAR integer not null, CAR_MODEL varchar(20) not null, CAR_MAKE varchar(20) not null, CAR_COST double, primary key (CAR_ID) )

  16. Java Persistence: Core ORM Database Mappings using Annotations package ejava.examples.orm.core.annotated; import javax.persistence.*; @Entity @Table(name="ORMCORE_CAR", schema="PUBLIC") public class Car { private long id; private String make; private String model; private int year; private BigInteger cost; public Car() {} public Car(long id) { this.id = id; } @Id @Column(name="CAR_ID", nullable=false) public long getId() { return id; } @SuppressWarnings("unused") private void setId(long id) { this.id = id; }

  17. Java Persistence: Core ORM Database Mappings using Annotations (cont.) @Column(name="CAR_MAKE", unique=false, nullable=false, insertable=true, updatable=true, table="", //note: we can point to another table to get prop length=20) public String getMake() { return make; } public void setMake(String make) { this.make = make; } @Column(name="CAR_MODEL", nullable=false, length=20) public String getModel() { return model; } public void setModel(String model) { this.model = model; }

  18. Java Persistence: Core ORM Database Mappings using Annotations (cont.) @Column(name="CAR_YEAR", nullable=false) public int getYear() { return year; } public void setYear(int year) { this.year = year; } @Column(name="CAR_COST", precision=7, scale=2) public BigDecimal getCost() { return cost; } public void setCost(BigDecimal cost) { this.cost = cost; } ... }

  19. Java Persistence: Core ORM Database Mappings using Descriptor <entity-mappings> <entity class="ejava.examples.orm.core.mapped.Car" access="PROPERTY" metadata-complete="true" name="MappedCar"> <table name="ORMCORE_CAR"/> <attributes> <id name="id"> <column name="CAR_ID" nullable="false"/> </id> <basic name="make"> <column name="CAR_MAKE" nullable="false" insertable="true" updatable="true" table="" length="20"/> </basic> <basic name="model"> <column name="CAR_MODEL" nullable="false" length="20"/> </basic> ...

  20. Java Persistence: Core ORM Database Mappings using Descriptor (cont.) ... <basic name="year"> <column name="CAR_YEAR" nullable="false"/> </basic> <basic name="cost"> <column name="CAR_COST" precision="7" scale="2"/> </basic> </attributes> </entity> </entity-mappings>

  21. Java Persistence: Core ORM More on Scale //precision defined in ORM as precision=7, scale=2 car.setCost(new BigDecimal("12345.66")); em.persist(car); em.flush(); em.clear(); //get a fresh copy from the DB Car car2 = em.find(Car.class, car.getId()); assertTrue("unexpectected value", car.getCost().equals(car2.getCost())); //update beyond scale values -- too many digits to right of decimal car2.setCost(new BigDecimal("1234.666")); em.flush(); em.clear(); Car car3 = em.find(Car.class, car.getId()); log.info("car2.cost=" + car2.getCost()); log.info("car3.cost=" + car3.getCost()); assertFalse("unexpected scale", car2.getCost().equals(car3.getCost())); //output -car2.cost=1234.666 -car3.cost=1234.67

  22. Java Persistence: Core ORM More on Precision //update beyond precision values -- too many digits overall car2 = car3; car2.setCost(new BigDecimal("123456.66")); try { em.flush(); fail("database accepted too many digits"); } catch (PersistenceException ex) { log.info("caught expected exception:" + ex); } //output -caught expected exception:javax.persistence.PersistenceException: org.hibernate.exception.DataException: Value too long for column "CAR_COST DECIMAL(7, 2)": "123456.66 (8)"; SQL statement: update ORMCORE_CAR set CAR_COST=?, CAR_MAKE=?, CAR_MODEL=?, CAR_YEAR=? where CAR_ID=? [22001-168]

  23. Java Persistence: Core ORM Primary Keys • Every entity must have an primary key • Primary keys must be unique • Map to one (simple primary key) or more (composite primary key) properties • Properties must be of type • Java primitive types (including wrappers; Integer, etc.) • java.lang.String • primary key class (composed of legal property types)

  24. Java Persistence: Core ORM Generated Primary Keys

  25. Java Persistence: Core ORM Generated Primary Keys public interface javax.persistence.GeneratedValue { javax.persistence.GenerationType strategy(); String generator(); } public final class javax.persistence.GenerationType extends java.lang.Enum{ public static final GenerationType TABLE; public static final GenerationType SEQUENCE; public static final GenerationType IDENTITY; public static final GenerationType AUTO; ... }

  26. Java Persistence: Core ORM AUTO GenerationType • Persistence providers required to provide primary key generation • Specific type of generator provided through strategy property • Using annotations @Entity @Table(name="ORMCORE_DRILL") public class Drill implements Serializable { ... @Id @GeneratedValue( //AUTO is default;could be left off strategy=GenerationType.AUTO) public long getId() { return id; } • Using descriptor <entity class="ejava.examples.orm.core.mapped.Drill" ...> <table name="ORMCORE_DRILL"/> <attributes> <id name="id"> <generated-value strategy="AUTO"/> </id> </attributes> </entity>

  27. Java Persistence: Core ORM AUTO GenerationType @Entity @Table(name="ORMCORE_DRILL") public class Drill implements Serializable { private static final long serialVersionUID = 1L; private long id=0; private String make; public Drill() {} public Drill(long id) { this.id = id; } @Id @GeneratedValue( //AUTO is default strategy=GenerationType.AUTO) public long getId() { return id; }

  28. Java Persistence: Core ORM AUTO GeneratedValue Test (Good) public void testAUTOGood() { //note that since PKs are generated, we must pass in //object that has not yet been assigned a PK value. ejava.examples.orm.core.annotated.Drill drill = new Drill(0); drill.setMake("acme"); //insert a row in the database em.persist(drill); log.info("created drill:" + drill); assertFalse(drill.getId() == 0L); } insert into ORMCORE_DRILL (id, make) values (null, ?) Hibernate: call identity() -created drill: ejava.examples.orm.core.annotated.Drill@1d9e279, id=1, make=acme

  29. Java Persistence: Core ORM AUTO GeneratedValue Test (Bad) public void testAUTOBad() { ejava.examples.orm.core.annotated.Drill drill = new Drill(25L); drill.setMake("BD"); boolean exceptionThrown = false; try { assertFalse(drill.getId() == 0L); em.persist(drill); } catch (PersistenceException ex) { log.info("got expected exception: " + ex); exceptionThrown = true; } assertTrue(exceptionThrown); } -got expected exception: javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: ejava.examples.orm.core.annotated.Drill

  30. Java Persistence: Core ORM TABLE GenerationType • Defines user-defined relational table to generate numeric values • example table create table ORMCORE_EB_UID ( UID_ID varchar(255), //holds name of table UID_VAL integer //holds the counter value ) • example values • UID_ID=ORMCORE_EGGBEATER • UID_VAL=2 • Must be setup by a definition of the table generator

  31. Java Persistence: Core ORM Defining Table Generator • Using annotations @Entity @Table(name="ORMCORE_EGGBEATER") @TableGenerator( //note:all but name are optional if gen schema name="eggbeaterGenerator", //logical name of gen table="ORMCORE_EB_UID", //name of table with seq pkColumnName="UID_ID", //pk column for seq table pkColumnValue="ORMCORE_EGGBEATER", //pk value in pk col valueColumnName="UID_VAL", //column for seq value allocationSize=17 //amount to increment ) public class EggBeater implements Serializable { • Using descriptor <entity class="ejava.examples.orm.core.mapped.EggBeater" ...> <table name="ORMCORE_EGGBEATER"/> <table-generator name="eggbeaterGenerator" table="ORMCORE_EB_UID" pk-column-name="UID_ID" pk-column-value="ORMCORE_EGGBEATER" value-column-name="UID_VAL" allocation-size="17"/>

  32. Java Persistence: Core ORM Using TABLE GenerationType • Using annotations @Id @GeneratedValue( strategy=GenerationType.TABLE, //use DB table generator="eggbeaterGenerator") //point to logical def public long getId() { return id; } • Using descriptor <attributes> <id name="id"> <generated-value strategy="TABLE" generator="eggbeaterGenerator"/> </id> </attributes> </entity>

  33. Java Persistence: Core ORM Testing TABLE GeneratedType public void testTABLE() { ejava.examples.orm.core.annotated.EggBeater eggbeater = new EggBeater(0); eggbeater.setMake("done right"); //insert a row in the database em.persist(eggbeater); log.info("created eggbeater:" + eggbeater); assertFalse(eggbeater.getId() == 0L); } -created eggbeater: ejava.examples.orm.core.annotated.EggBeater@1cba87, id=1, make=done right

  34. Java Persistence: Core ORM Finishing the allocationSize Hibernate: insert into ORMCORE_EGGBEATER (make, id) values (?, ?) -table id after[2]=1 Hibernate: insert into ORMCORE_EGGBEATER (make, id) values (?, ?) -table id after[3]=1 … … Hibernate: insert into ORMCORE_EGGBEATER (make, id) values (?, ?) -table id after[16]=1 Hibernate: insert into ORMCORE_EGGBEATER (make, id) values (?, ?) -table id after[17]=2

  35. Java Persistence: Core ORM SEQUENCE GenerationType • Some DBMS vendors provide • built-in structure to efficiently generate unique IDs

  36. Java Persistence: Core ORM Defining Sequence Generator • Using Annotations @Entity @Table(name="ORMCORE_FAN") @SequenceGenerator( name="fanSequence", //required logical name sequenceName="FAN_SEQ", //name in database initialValue=44, //doesn’t seem to be used allocationSize=13) //increment seq when reached public class Fan implements Serializable {... • Using Descriptor <entity class="ejava.examples.orm.core.mapped.Fan" ...> <table name="ORMCORE_FAN"/> <sequence-generator name="fanSequence" sequence-name="FAN_SEQ" initial-value="44" allocation-size="13"/>

  37. Java Persistence: Core ORM Using SEQUENCE GenerationType • Using Annotations @Id @GeneratedValue( strategy=GenerationType.SEQUENCE, generator="fanSequence") //point to logical def public long getId() { return id; } private void setId(long id) { this.id = id; } • Using Descriptor <attributes> <id name="id"> <generated-value strategy="SEQUENCE" generator="fanSequence"/> </id> </attributes>

  38. Java Persistence: Core ORM Testing Sequence Generator public void testSEQUENCE() { ejava.examples.orm.core.annotated.Fan fan = new Fan(0); fan.setMake("cool runner 1"); //insert a row in the database em.persist(fan); log.info("created fan:" + fan); assertFalse(fan.getId() == 0L); } -created fan:ejava.examples.orm.core.annotated.Fan@1dcb3cd, id=1, make=cool runner 1

  39. Java Persistence: Core ORM IDENITY GenerationType • Let database generate • from Hypersonic Log create table ORMCORE_GADGET ( id bigint generated by default as identity (start with 1), make varchar(255), primary key (id) ) ... INSERT INTO ORMCORE_GADGET VALUES(null,'gizmo 1') INSERT INTO ORMCORE_GADGET VALUES(null,'gizmo 2') • HSQL supports a “call identity()” stored procedure to get last generated ID

  40. Java Persistence: Core ORM Using IDENTITY Generator • Using Annotations @Id @GeneratedValue(strategy=GenerationType.IDENTITY) public long getId() { return id; } • Using Descriptor <attributes> <id name="id"> <generated-value strategy="IDENTITY"/> </id> </attributes>

  41. Java Persistence: Core ORM Testing Identity Generator public void testIDENTITY() { ejava.examples.orm.core.annotated.Gadget gadget = new Gadget(0); gadget.setMake("gizmo 1"); //insert a row in the database em.persist(gadget); log.info("created gadget:" + gadget); assertFalse(gadget.getId() == 0L); } -created gadget: ejava.examples.orm.core.annotated.Gadget@23d278, id=1, make=gizmo 1

  42. Java Persistence: Core ORM Composite Primary Keys

  43. Java Persistence: Core ORM Composite Primary Keys • Primary Key consisting of multiple properties • Can be represented by a primary key class • must be Serializable public class MowerPK implements java.io.Serializable { • must have a public no-arg constructor public MowerPK() {} • must implement equals() and hashCode() methods public int hashCode() { ... } public boolean equals(Object obj) { ... }

  44. Java Persistence: Core ORM Example Composite PK Class package ejava.examples.orm.core; import java.io.Serializable; public class MowerPK implements Serializable { private static final long serialVersionUID = 1L; private String make; private String model; public MowerPK() {} public MowerPK(String make, String model) { this.make = make; this.model = model; } public static long getSerialVersionUID() { return serialVersionUID; } public String getMake() { return make; } private void setMake(String make) { this.make = make; }

  45. Java Persistence: Core ORM Example Composite PK Class (cont.) public String getModel() { return model; } private void setModel(String model) { this.model = model; } public int hashCode() { return make.hashCode() + model.hashCode(); } public boolean equals(Object obj) { try { if (this == obj) return true; return make.equals(((MowerPK)obj).getMake()) && model.equals(((MowerPK)obj).getModel()); } catch (Throwable ignored) { //catch NP & Cast Exceptions return false; } } public String toString() { return super.toString() + ", make=" + make + ", model=" + model; } }

  46. Java Persistence: Core ORM Using a Primary Key Class as an IdClass • Not used internally by persistent class • Used by entity manager • Properties of IdClass map to @Id properties of persistent class • Example Database Schema create table ORMCORE_MOWER ( make varchar(255) not null, model varchar(255) not null, size integer not null, primary key (make, model) )

  47. Java Persistence: Core ORM Example Usage of an IdClass package ejava.examples.orm.core.annotated; import java.io.Serializable; import javax.persistence.*; import ejava.examples.orm.core.MowerPK; @Entity @Table(name="ORMCORE_MOWER") @IdClass(MowerPK.class) public class Mower implements Serializable { private static final long serialVersionUID = 1L; private String make; private String model; private int size; public Mower() {} public Mower(String make, String model) { this.make = make; this.model = model; }

  48. Java Persistence: Core ORM Example Usage of an IdClass (cont.) @Id @Column(nullable=false, updatable=false) public String getMake() { return make; } private void setMake(String make) { this.make = make; } @Id @Column(nullable=false, updatable=false) public String getModel() { return model; } private void setModel(String model) { this.model = model; } public int getSize() { return size; } public void setSize(int size) { this.size = size; }

  49. Java Persistence: Core ORM Example Usage of an IdClass • Using a Descriptor <entity class="ejava.examples.orm.core.mapped.Mower" access="PROPERTY" metadata-complete="true" name="MappedMower"> <table name="ORMCORE_MOWER"/> <id-class class="ejava.examples.orm.core.MowerPK"/> <attributes> <id name="make"/> <id name="model"/> </attributes> </entity>

  50. Java Persistence: Core ORM Example Usage of an IdClass public void testIdClass() { ejava.examples.orm.core.annotated.Mower mower = new Mower("acme", "power devil2"); mower.setSize(21); //insert a row in the database em.persist(mower); log.info("created mower:" + mower); -created mower:ejava.examples.orm.core.annotated.Mower@d2b64e, make=acme, model=power devil2, size=21 Mower mower2 = em.find(Mower.class, new MowerPK("acme", "power devil2")); assertNotNull(mower2); log.info("found mower:" + mower2); assertEquals(mower.getSize(), mower2.getSize()); -found mower: ejava.examples.orm.core.annotated.Mower@d2b64e, make=acme, model=power devil2, size=21

More Related