Enterprise Java Development@TOPIC@
@Entity.name - assigns entity name to entity class
@Table.name - assigns table name to entity class
@Column.name - assigns column name to entity property
Mostly used when generating schema
@Table
uniqueConstraints * - column groupings that will have a unique value
@Column
unique * - column will have unique value
nullable * - column may contain a null value/is optional
insertable - column will be included in SQL during initial insert
updatable - column will be included in SQL during follow-on updates
table - table for column in a multi-table mapping
length * - length of column for Strings
precision * - defines number of digits used for Numeric types (e.g., 100.02 is precision=5)
scale * - defines number of digits to use to the right of decimal place (e.g., 100.01 is scale=2)
columnDefinition * - custom DDL for column creation
* - Used only in schema generation
create table ORMCORE_CAR ( CAR_ID bigint not null, CAR_COST decimal(7,2), CAR_MAKE varchar(20) not null, CAR_MODEL varchar(20) not null, CAR_YEAR integer not null, primary key (CAR_ID) )
@Entity
@Table(name="ORMCORE_CAR")
public class Car {
@Id
@Column(name="CAR_ID", nullable=false)
private long id;
@Column(name="CAR_MAKE",
unique=false,
nullable=false,
insertable=true,
updatable=true,
length=20)
private String make;
@Column(name="CAR_MODEL", nullable=false, length=20)
private String model;
@Column(name="CAR_YEAR", nullable=false)
private int year;
@Column(name="CAR_COST", precision=7, scale=2)
private BigDecimal cost;
...
<entity class="ejava.examples.orm.core.mapped.Car"
access="FIELD">
<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"
length="20"/>
</basic>
<basic name="model">
<column name="CAR_MODEL" nullable="false" length="20"/>
</basic>
<basic name="year">
<column name="CAR_YEAR" nullable="false"/>
</basic>
<basic name="cost">
<column name="CAR_COST" precision="7" scale="2"/>
</basic>
</attributes>
</entity>
Added precision and scale only has impact for certain Java types (e.g., BigDecimal). Check the dialect for specific mappings and what SQL types they translate to in the source code.
# H2Dialect.java
registerColumnType( Types.DECIMAL, "decimal($p,$s)" );
registerColumnType( Types.NUMERIC, "decimal($p,$s)" );
registerColumnType( Types.DOUBLE, "double" );
Figure 47.1. 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());
log.info("car.cost=" + car.getCost());
log.info("car2.cost=" + car2.getCost());
assertTrue("unexpectected value", car.getCost().equals(car2.getCost()));
//update beyond the 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()));
-car.cost=12345.66 //Value created within scale=2 -car2.cost=12345.66 //Value correctly retrieved from DB -car2.cost=1234.666 //Value goes beyond scale=2 -car3.cost=1234.67 //Value rounded down to scale from DB
Figure 47.2. More on Precision
//update beyond the 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);
}
-caught expected exception:javax.persistence.PersistenceException: org.hibernate.exception.DataException: could not execute statement
Entity using PROPERTY access
Entity class contains property that complies with default rules that should *not* be mapped to database
setters
getters
relations to other classes, including collections
Figure 47.3. Transient Example Entity Class
@Entity
@Table(name="ORMCORE_TANK")
public class Tank {
private long id;
private String make;
private String model;
public Tank() {}
public Tank(long id) { this.id = id; }
@Id
public long getId() { return id; }
protected void setId(long id) {
this.id = id;
}
@Transient //if you remove this, it will fail trying to locate setter
public String getMakeModel() {
return make + " " + model;
}
public String getMake() { return make; }
public void setMake(String make) {
this.make = make;
}
public String getModel() { return model; }
public void setModel(String model) {
this.model = model;
}
Figure 47.4. Transient Example orm.xml
<entity class="ejava.examples.orm.core.mapped.Tank" access="PROPERTY">
<table name="ORMCORE_TANK"/>
<attributes>
<id name="id"/>
<transient name="makeModel"/>
</attributes>
</entity>
Figure 47.5. Transient Example Database Schema
create table ORMCORE_TANK ( id bigint not null, make varchar(255), model varchar(255), primary key (id) )
Figure 47.6. Transient Example Test
ejava.examples.orm.core.annotated.Tank tank = new Tank(1);
tank.setMake("acme");
tank.setModel("great guns");
//insert a row in the database
em.persist(tank);
log.info("created tank:" + tank);
-created tank:ejava.examples.orm.core.annotated.Tank@4eef4eb7make=acme, model=great guns
Storing large text document as CLOB
Storing large binary data as BLOB
Figure 47.7. CLOB Example Database Schema
create table ORMCORE_UMBRELLA ( id bigint not null, make clob, model varchar(255), primary key (id) )
Figure 47.8. CLOB Example Entity Class
@Entity
@Table(name="ORMCORE_UMBRELLA")
public class Umbrella {
@Lob
@Basic(fetch=FetchType.LAZY) //ignored
public char[] getMake() {
return make.toCharArray();
}
public void setMake(char[] make) {
this.make = new String(make);
}
Figure 47.9. Temporal/Enum Example Schema
create table ORMCORE_VASE (
id bigint not null,
aDate date,
aTime time,
aTimestamp timestamp,
colorId integer,
colorName varchar(255),
primary key (id)
)
Figure 47.10. Temporal/Enum Example Entity Class
@Entity
@Table(name="ORMCORE_VASE")
public class Vase {
@Id
private long id;
@Temporal(TemporalType.DATE)
private Date aDate;
@Temporal(TemporalType.TIME)
private Date aTime;
@Temporal(TemporalType.TIMESTAMP)
private Date aTimestamp;
@Enumerated(EnumType.ORDINAL)
private ColorType colorId;
@Enumerated(EnumType.STRING)
private ColorType colorName;
Figure 47.11. Temporal/Enum Example orm.xml
<entity class="ejava.examples.orm.core.mapped.Vase" access="FIELD">
<table name="ORMCORE_VASE"/>
<attributes>
<id name="id"/>
<basic name="aDate">
<temporal>DATE</temporal>
</basic>
<basic name="aTime">
<temporal>TIME</temporal>
</basic>
<basic name="aTimestamp">
<temporal>TIMESTAMP</temporal>
</basic>
<basic name="colorId">
<enumerated>ORDINAL</enumerated>
</basic>
<basic name="colorName">
<enumerated>STRING</enumerated>
</basic>
</attributes>
</entity>
Figure 47.12. Temporal/Enum Example Test
@Test
public void testValues() {
log.info("testValues");
ejava.examples.orm.core.annotated.Vase vase = new Vase(1);
Date date = new Date();
vase.setADate(date);
vase.setATime(date);
vase.setATimestamp(date);
vase.setColorId(ColorType.RED);
vase.setColorName(ColorType.RED);
//insert a row in the database
em.persist(vase);
log.info("created case:" + vase);
//find the inserted object
em.flush();
em.clear();
Vase vase2 = em.find(Vase.class, 1L);
log.info("found vase:" + vase2);
-created case:ejava.examples.orm.core.annotated.Vase@7f68f33c, id=1, aDate=Mon Sep 23 00:11:10 EDT 2013, aTime=Mon Sep 23 00:11:10 EDT 2013, aTimestamp=Mon Sep 23 00:11:10 EDT 2013, colorId=RED, colorName=RED -found vase:ejava.examples.orm.core.annotated.Vase@5f0d8b74, id=1, aDate=2013-09-23, aTime=00:11:10, aTimestamp=2013-09-23 00:11:10.296, colorId=RED, colorName=RED
select * from ORMCORE_VASE ID ADATE ATIME ATIMESTAMP COLORID COLORNAME -- ---------- -------- ----------------------------- ------- --------- 1 2006-09-23 14:08:22 2006-09-23 14:08:22.221000000 0 RED
Notice impact of temporal DB-mapping does effect until data saved and retrieved from database