Hibernate with Annotation Mapping

Hibernate with Annotation

Place the DB mapping information as Java Annotation

package com.innotrekker.app.annotation;

import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import org.hibernate.annotations.GenericGenerator;

@Entity  // Define a persistent Hiberanate Object
@Table( name = "orders" )
public class Order implements Serializable {
    private Long id;

    private String comment;
    private Date date;

    public Order() {
    }

    public Order(String comment, Date date) {
	this.comment = comment;
	this.date = date;
    }

    @Id
    @GeneratedValue(generator="increment")
    @GenericGenerator(name="increment", strategy = "increment")
    public Long getId() {
	return id;
    }

    private void setId(Long id) {
	this.id = id;
    }

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "o_time")
    public Date getDate() {
	return date;
    }

    public void setDate(Date date) {
	this.date = date;
    }

    @Column(name = "o_comment")
    public String getComment() {
	return comment;
    }

    public void setComment(String comment) {
	this.comment = comment;
    }
}
  • @Entity (@javax.persistence.Entity) marks the class as a Hibernate annotated entity Java class

Hibernate annotation replaces the need of a separate mapping file: Order.hbm.xml

Common Hibernate Annotation for the Java Entity Class

Hibernate Annotation Description
@Table Database table name. Without @Table, Hibernate assumes the uppercase name of the class "ORDER" as the DB table name
@Immutable Set object not mutable. It helps Hibernate in optimizing the DB access if the object is read only
@Proxy(lazy=false) Turn off lazy loading. Default is true. Set to false if you know the referenced object is always needed. This will reduce the number of SQL queries.
@Where Specify a where condition to narrow down the entity objects to be returned
@BatchSize Specify the batch size in fetching the Entity Objects by identifier
@Check Define a SQL expression for a multi-row check constraint if automatic schema generation is used

Hibernate Table Annotation (@Table)

@Entity
@Table(name="orders",
   schema="mydb",
   uniqueConstraints=
     @UniqueConstraint(name="some_constraint", columnNames={"col_name1", "col_name2"} )
  • name override the default DB table name: the class name)
  • uniqueConstraints defines a unique constraint on the DB

Create a Hibernate View

@Entity
@Subselect("select students.name, count(*) "
        + "from students "
        + "join tutors on students.s_id = tutors.s_id "
        + "group by students.s_id")
@Synchronize( {"students", "tutors"} )
  • @Subselect defines the Hibernate view to be used by the Entity class
  • @Synchronize defines the tables the view is accessing. It helps Hibernate to perform the auto flush correctly

Hibernate Identifier (Mapping to DB primary key)

Create a Hibernate identifier id to map to a DB primary key

@Entity
public class Student {
   @Id Integer getId() { return id; }
   ...
}
  • @Id define the identifier of a Persistent Instance. It maps to the DB primary key
  • @Column overrides the primary key column name used in the DB

Using Complex Primary Key in Hibernate Annotation

Using @EmbeddedId to Define a Complex Hibernate Primary Key

Create a complex Hibernat primary key composed of 2 DB columns

@Entity
class Customer {
   @EmbeddedId
   @AttributeOverrides( {
            @AttributeOverride(name="firstName", column = @Column(name="c_firstname") ),
            @AttributeOverride(name="lastName", column = @Column(name="c_lastname") )
    } )
   UserName id;
}

@Embeddable
class UserName implements Serializable {
   String firstName;
   String lastName;
}
  • @AttributeOverride overrides the default DB column name
    • It can be skipped if no changes in the default value

Use the content of a @EmbeddedId to reference an associated object

@Entity
public class Child {
   @EmbeddedId UserId id;

   @MapsId("userid")
   @ManyToOne User father;
}

@Entity
public class User {
   @id long id;
   ...
}

@Embeddable
public class UserId implements Serializable {
   long userid;
   long companyid;
   ...
   // Must implements equals and hashCode
}
@MapsId("userid")
  • use the userid in Child (as a foreign key) to reference the User object father

Hibernate Auto Generated Primary Id

Using the identity column used in DB2, MySQL, MS SQL Server & Sybase to generate the primary key

@Entity
public class Order {
   @Id @GeneratedValue(strategy=GenerationType.IDENTITY)
   Integer getId() { ... };
}

Set new_generator_mappings to true in the Hibernate configuration file

Use Oracle Sequence generator to generate the Hibernate id

@Id
@GeneratedValue(
    strategy=GenerationType.SEQUENCE,
    generator="sequence_1")
@javax.persistence.SequenceGenerator(
    name="SEQUENCER",
    sequenceName="sequence_1",
    allocationSize=10
)

Custom Hibernate Insert, Update, Delete SQL

Customize the SQL statement used to insert, update or delete a Hibernate persistent entity

@Entity
@Table(name="orders")
@SQLInsert( sql="INSERT INTO orders(id, title) VALUES(?,?)")
@SQLUpdate( sql="UPDATE orders SET id = ?, title = ? WHERE id = ?")
@SQLDelete( sql="DELETE orders WHERE id = ?")
@SQLDeleteAll( sql="DELETE CHAOS")
@Loader(namedQuery = "orders")
@NamedNativeQuery(name="orders", query="select id, title from orders where id= ?", resultClass = Order.class)
public class Order {
...
}

Hibernate Optimistic Locking

Using version number for Hibernate Optimistic Locking

Hibernate Optimistic Locking Using a Column containing a Version number

@Entity
public class Customer implements Serializable {
    @Version
    @Column(name="c_lock_version")
    public Integer getVersion() { ... }
}
  • A column c_lock_version is defined in the table to hold the version number
  • If the version number was changed during an update request is made, the write operation will fail

Using timestamp for Hibernate Optimistic Locking

Use a timestamp column for Hibernate optimistic locking

public class Customer implements Serializable {

...

    @Version
    public Date getModifyDate() { ... }

}

Version number is preferable over timestamp

Hibernate Method Annotation

@Entity
public class Order implements Serializable {
    @Basic(fetch = FetchType.LAZY)
    public List<Item> getItems() { ... }
}
Hibernate Method Annotation Description
@Transient Data is not persistent to DB
@Basic(fetch = FetchType.LAZY) Use Lazy loading for Hibernate instead of the default eager loading
@Temporal(TemporalType.TIME) Specify the DB to be used for this column: TemporalType.DATE, TemporalType.TIME, or TemporalType.TIMESTAMP
@Enumerated(EnumType.STRING) String based enumerator type
@Lob Large Object
@Generated The property is generated by the DB directly (like some timestamp value)

Hibernate Embedded Object

Embed a Embeddable class in a Persistent Entity class

public class Customer implements Serializable {

    @Embedded
    @AttributeOverrides( {
            @AttributeOverride(name="firstname", column = @Column(name="o_firstname") ),
            @AttributeOverride(name="lastname", column = @Column(name="o_lastname") )
    } )
    Name customerName;
}

@Embeddable
public class Name implements Serializable {
    @Column(name="first_name") private String firstname;

    public String getFirstname() { return firstname; }
    public void setFirstname(String firstname) { this.firstname = firstname; }

    ...
}
  • Use @AttributeOverride to override the column name

Hibernate Table Inheritance

Use a Single Table to Host Multiple Hibernate Persistent Entity Object

@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(
    name="member_code",
    discriminatorType=DiscriminatorType.STRING
)
@DiscriminatorValue("GENERAL")
public class Customer { ... }

@Entity
@DiscriminatorValue("PREMIUM")
public class VIP extends Customer { ... }
  • The member_code column differentiate whether it is a Customer Entity or a VIP entity (member_code with value "PREMIUM")

One DB Table for the Parent Class & One Table for Each Children

@Entity @Table(name="customers")
@Inheritance(strategy=InheritanceType.JOINED)
public class Customer implements Serializable {
    ...
}

@Entity @Table(name="vips")
@PrimaryKeyJoinColumn(name="Customer")
public class VIP extends Customer {
    public String getMemberCode() { ... }
}
  • Entity VIP joins the vips table with the customers table

Inherited Properties Defined in the Parent Class

@MappedSuperclass shares common properties through a superclass. However, the MappedSuperclass property is persisted in the children table

@MappedSuperclass
public class Customer {
   ...
}

@Entity class VIP extends Customer {
    ...
}

To overriding the parent class mapping definition

@Entity
@AttributeOverride( name="name", column = @Column(name="m_name") )
@AssociationOverride(
   name="contact",
   joinColumns = @JoinColumn(name="f_contact_id")
)
public class VIP extends Customer

Column Transformmer

Apply function to individual column

@Entity

class User {
   private String password;

   @Column(name="password")
   @ColumnTransformer(
      read="decrypt(password)",
      write="encrypt(?)")
   public String getPassword() { ... }

   public void setPassword(String number) { this.creditCardNumber = number; }

}