Enterprise Java Development@TOPIC@
In this chapter we will create custom class/database mappings for some class properties
Map a class to a specific table
Map a property to a specific column
Define constraints for properties
Take a look at using getters and setters
Copy your Animal.java class to Cat.java
package myorg.entityex.mapped;
import java.util.Date;
public class Cat {
private int id;
private String name;
private Date dob;
private double weight;
public Cat() {} //must have default ctor
public Cat(String name, Date dob, double weight) {
this.name = name;
this.dob = dob;
this.weight = weight;
}
public int getId() { return id; }
...
Copy your Animal2.java class to Cat2.java
package myorg.entityex.annotated;
import java.util.Date;
@javax.persistence.Entity
public class Cat2 {
private int id;
private String name;
private Date dob;
private double weight;
public Cat2() {} //must have default ctor
public Cat2(String name, Date dob, double weight) {
this.name = name;
this.dob = dob;
this.weight = weight;
}
@javax.persistence.Id
public int getId() { return id; }
...
Name the new Cat entity class in the Animal-orm.xml
# src/main/resources/orm/Animal-orm.xml
<entity class="myorg.entityex.mapped.Animal">
...
<entity class="myorg.entityex.mapped.Cat">
<attributes>
<id name="id"/>
</attributes>
</entity>
Name the new Cat2 entity class in the persistence.xml
# src/test/resources/META-INF/persistence.xml
<mapping-file>orm/Animal-orm.xml</mapping-file>
<class>myorg.entityex.Auto</class>
<class>myorg.entityex.annotated.Animal2</class>
<class>myorg.entityex.annotated.Cat2</class>
$ more target/classes/ddl/* ... create table Cat ( id integer not null, dob timestamp, name varchar(255), weight double not null, primary key (id) ); create table Cat2 ( id integer not null, dob timestamp, name varchar(255), weight double not null, primary key (id) );
Add a table element to the orm.xml definition to map Cat to the ENTITYEX_CAT table.
<entity class="myorg.entityex.mapped.Cat">
<table name="ENTITYEX_CAT"/>
<attributes>
@javax.persistence.Entity
@javax.persistence.Table(name="ENTITYEX_CAT")
public class Cat2 {
private int id;
$ more target/classes/ddl/* ... create table ENTITYEX_CAT ( id integer not null, dob timestamp, name varchar(255), weight double not null, primary key (id) );
@javax.persistence.Id
@javax.persistence.Column(name="CAT_ID")
@javax.persistence.GeneratedValue
private int id;
<entity class="myorg.entityex.mapped.Cat">
<table name="ENTITYEX_CAT"/>
<attributes>
<id name="id">
<column name="CAT_ID"/>
<generated-value/>
</id>
</attributes>
</entity>
@javax.persistence.Column(nullable=false, length=20)
private String name;
<basic name="name">
<column nullable="false" length="20"/>
</basic>
# src/main/java/myorg/entityex/annotated/Cat2.java
@javax.persistence.Column(precision=3, scale=1) //10.2lbs
private BigDecimal weight;
...
public Cat2(String name, Date dob, BigDecimal weight) {
...
public BigDecimal getWeight() { return weight; }
public void setWeight(BigDecimal weight) {
# src/main/java/myorg/entityex/mapped/Cat.java
private BigDecimal weight;
...
public Cat(String name, Date dob, BigDecimal weight) {
...
public BigDecimal getWeight() { return weight; }
public void setWeight(BigDecimal weight) {
# src/main/resources/orm/Animal-orm.xml
<basic name="weight">
<column precision="3" scale="1"/>
</basic>
# target/classes/ddl/entityEx-createJPA.ddl create table ENTITYEX_CAT ( CAT_ID integer generated by default as identity, dob date, name varchar(20) not null, weight decimal(3,1), primary key (CAT_ID) );
All defaults not overwritten are preserved (e.g., column names)
The Cat and Cat2 entities have been mapped to the ENTITYEX_CAT table.
The id property will have a unique value automatically generated and assigned
The dob and weight properties continue to be optional since that is the default and not overridden
# implies FIELD access
@javax.persistence.Id
@javax.persistence.Column(name="CAT_ID")
@javax.persistence.GeneratedValue
private int id;
...
public int getId() { return id; }
# implies PROPERTY access
private int id;
...
@javax.persistence.Id
@javax.persistence.Column(name="CAT_ID")
@javax.persistence.GeneratedValue
public int getId() { return id; }
<entity class="myorg.entityex.mapped.Cat"
access="FIELD">
@javax.persistence.Access(javax.persistence.AccessType.FIELD)
public class Cat2 {
private double weight;
...
@javax.persistence.Column(precision=3, scale=1) //10.2lbs
@javax.persistence.Access(javax.persistence.AccessType.PROPERTY)
public BigDecimal getWeight() {
return new BigDecimal(weight);
}
public void setWeight(BigDecimal weight) {
this.weight = weight==null ? 0 : weight.doubleValue();
}
Add a logger and some log statements to help identify the calls to the getter and setter methods
# src/main/java/myorg/entityex/annotated/Cat2.java
private static final Log logger = LogFactory.getLog(Cat2.class);
...
public BigDecimal getWeight() {
logger.debug("annotated.getWeight()");
return new BigDecimal(weight);
}
public void setWeight(BigDecimal weight) {
logger.debug("annotated.setWeight()");
this.weight = weight==null ? 0 : weight.doubleValue();
}
# src/test/java/myorg/entityex/AnimalTest.java
@Test
public void testCreateCatAnnotated() {
logger.info("testCreateCatAnnotated");
myorg.entityex.annotated.Cat2 cat = new myorg.entityex.annotated.Cat2("fluffy", null, 99.9);
em.persist(cat); //get provider to call getters
em.flush(); em.detach(cat);
cat = em.find(myorg.entityex.annotated.Cat2.class, cat.getId()); //get provider to call setters
}
Run your new test method and observe the calls to getWeight and setWeight printed.
$ mvn clean test -Dtest=myorg.entityex.AnimalTest#testCreateCatAnnotated
...
-testCreateCatAnnotated
-annotated.getWeight() //<----------------
Hibernate:
insert
into
ENTITYEX_CAT
(CAT_ID, dob, name, weight)
values
(null, ?, ?, ?)
-annotated.getWeight() //<----------------
-annotated.getWeight() //<----------------
Hibernate:
select
cat2x0_.CAT_ID as CAT1_2_0_,
cat2x0_.dob as dob2_0_,
cat2x0_.name as name2_0_,
cat2x0_.weight as weight2_0_
from
ENTITYEX_CAT cat2x0_
where
cat2x0_.CAT_ID=?
-annotated.setWeight() //<----------------
# src/main/java/myorg/entityex/mapped/Cat.java
public class Cat {
private static final Log logger = LogFactory.getLog(Cat.class);
...
private double weight;
...
public Cat(String name, Date dob, double weight) {
...
public BigDecimal getWeight() {
logger.debug("mapped.getWeight()");
return new BigDecimal(weight);
}
public void setWeight(BigDecimal weight) {
logger.debug("mapped.setWeight()");
this.weight = weight==null ? 0 : weight.doubleValue();
}
Add the following test method to your JUnit class.
@Test
public void testCreateCatMapped() {
logger.info("testCreateCatMapped");
myorg.entityex.mapped.Cat cat = new myorg.entityex.mapped.Cat("fluffy", null, 99.9);
em.persist(cat); //get provider to call getters
em.flush(); em.detach(cat);
cat = em.find(myorg.entityex.mapped.Cat.class, cat.getId()); //get provider to call setters
}
Add the access="PROPERTY" to the weight definition within the orm.xml
<basic name="weight" access="PROPERTY">
<column precision="3" scale="1"/>
</basic>
-testCreateCatMapped -mapped.getWeight() //<---------------- Hibernate: insert into ENTITYEX_CAT (CAT_ID, dob, name, weight) values (null, ?, ?, ?) -mapped.getWeight() //<---------------- -mapped.getWeight() //<---------------- Hibernate: select cat0_.CAT_ID as CAT1_2_0_, cat0_.dob as dob2_0_, cat0_.name as name2_0_, cat0_.weight as weight2_0_ from ENTITYEX_CAT cat0_ where cat0_.CAT_ID=? -mapped.setWeight() //<----------------
In this chapter you performed some core class/database table mappings that allowed you to
Define the name of the table used to store instances of the entity class
Define the column name used to store properties within the entity class
Define property constraints to require a property to exist or continue to be optional
Define maximum column lengths for string properties witin your entity class