Ejb3 basics: Entities

Entity Beans? Better than 2.1, I promise.

Ejb3 Entity beans are a type of enterprise java bean construct used to model data used by the ejb framework. The basic idea is to manipulate simple java objects, which represent in concrete terms your database data, and then have the framework handle as much of the plumbing as possible when you persist the data. Persisting means to store for later use in some data repository – usually some kind of database. By persisting these entities within the ejb framework we are able to abstract out tasks like updating a table and its associated foreign key table elements, perform queries and caching that automatically handles stuff like pre-populating java objects, and lots of the other boring stuff. In short, using entities in your application will allow you to work more on implementing business logic and less on wiring and mapping DAOs to TransferObjects. For the sake of completeness, the other two other important types of ejb beans should be mentioned: the Session and Message driven beans. In case it wasn’t obvious, ejb3 is only possible with java 1.5+ since that’s the release that initially introduced annotations into the java language.

One of the great things about ejb3 is that entities and persistence got a major overhaul from 2.1 = MAJOR SEXY TIME. Ejb3 does a really good job of simplifying the object model by using annotations in pojos to mark up entities. You can now model your entire data structure in terms of plain old java objects and their relationships, and the persistence engine will go and create all the necessary tables and sequencers and supporting schema elements.

Example Entity

Here’s an example of a bidirectional one to many relationship between User and Contact. Consider the following class:

package com.examples.entities;  

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.*;

@Entity
@Table(name="tb_user")
@SequenceGenerator(name = "sq_user",sequenceName = "sq_user", initialValue=1)
public class User implements Serializable {

	private static final long serialVersionUID = 1L;
	
	@Id
	@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="sq_user")
	protected Long id;

	@Column(name="user_name", nullable=false, length=32)
	protected String username;
	protected String password;
	protected String email;	
	
	@OneToMany(mappedBy="user")
	@JoinTable(name="tb_user_contact") 
	protected List<Contact> contacts = new ArrayList<Contact>();
 
	public Long getId() {
		return id;
	}
	public void setId(Long id) {
		this.id = id;
	}	
	
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}	
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	
	public List<Contact> getContacts() {
		return contacts;
	}
	public void setContacts(List<Contact> contacts) {
		this.contacts = contacts;
	}

}

This is a fairly common type of entity. Going from top to bottom, lets take a look at the annotations used and examine what they do.

@Entity

@Entity is the annotation that marks this particular java class as an ejb entity. This tells the persistence engine to load up this class and its associated annotations and use it as a model for data in the database. Technically this is the only annotation required in the class for a very simple entity, but there are other annotations we can use to customize and declare more complex relationships.

@Table(name=”tb_user”)

@Table lets you name the table modeled by your pojo. Its just a simple way to keep things organized in the database. If you don’t specify the table name it will default to the class name.

@SequenceGenerator(name = “sq_user”,sequenceName = “sq_user”, initialValue=1)

@Sequence lets you set up the sequence used for the primary key generation. This is required when you choose GeneratorType.SEQUENCE as your primary key generator. The name must match the @GeneratedValue’s name value. This is how the persistence engine knows how to map the sequence to the column.

@Id

@Id indicates that the following class method or field will map the table’s primary key.

@GeneratedValue(strategy=GenerationType.SEQUENCE, generator = “sq_user”)

@GeneratedValue maps the type of primary key incrementing strategy to use when adding new records to the database. Here are the possible strategies:

  • GenerationType.AUTO
    This indicates that the persistence engine will decide what incrementing strategy to use. Lazy man multiple vendor option.
  • GenerationType.IDENTITY
    This indicates that the persistence engine should use the identity column for incrementing. Vendors that can use this a ones that set “AUTO-INCREMENT” value type of flag to true. MySQL is one example of a vendor that can use this type.
  • GenerationType.SEQUENCE
    This tells the persistence engine to use a sequence to manage the increment values when inserting new values into the table. Postgres is an example of a vendor that uses sequences.
  • GenerationType.TABLE
    This tells the persistence engine to use a separate table to track increments on the primary key. This is more of a general strategy than a vendor specific implementation.

@Column(name=”user_name”, nullable=false, length=32)

@Column allows you to define column attributes for each class field. You can choose to define all of the possible relevant attributes or just the ones that you want to define. Other possible attributes are:

  • columnDefinition=”varchar(512) not null”
    Allows you to define native sql to your column definition
  • updatable=false
    Sets the column to allow updates or not. If it is not explicitly set to false, it will default to true, allowing updates to happen.
  • precision=10
    Decimal precision
  • scale=5
    Decimal scale
  • unique=true
    Defines if the column should contain only unique values.
  • table=”tb_user”
    Maps the table name for which this column belongs.

@OneToMany(mappedBy=”user”)

@OneToMany lets the persistence engine know that this field or method has a one to many type of relationship with the mapped object and the mappedBy attribute lets the persistence engine know the foreign key used when mapping the relationship. It will then set up any necessary relationship tables needed to express the relationship. This would normally include creating a separate table to hold all the key mappings.

@JoinTable(name=”tb_user_contact”)

@JoinTable lets you define the join table’s properties. In this case we’re using it to name the join table mapping the one to many relationship. A more complete @JoinTable annotation looks like this:

	@OneToMany(mappedBy="user")
	@JoinTable(
	    name="tb_user_contact",
	    joinColumns=@JoinColumn(name="user_id",referencedColumnName="id"),
	    inverseJoinColumns=@JoinColumn(name="contact_id",referencedColumnName="id")
	)
	public List<Contact> getContacts() {
		return contacts;
	}

This covers the owning class, here’s the class being pwnt:

import javax.persistence.*;

@Entity
@Table(name="tb_contact")
public class Contact {

	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	protected Long id;
	protected String email;	

	@ManyToOne
	protected User user;
	
	
	public Long getId() {
		return id;
	}
	public void setId(Long id) {
		this.id = id;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public User getUser() {
		return user;
	}
	public void setUser(User user) {
		this.user = user;
	}
	
}

@ManyToOne

@ManyToOne annotation implies the connecting foreign key used in the bidirectional mapping. When the persistence engine reads all the entities in and starts generating all the sql to model the object model it will generate three tables between these two java classes. One table “tb_user” will represent the user class, “tb_contact” will represent the contact class, and finally, “tb_user_contact” which represents the relationship mapping table. This annotation is what turns a unidirecitonal relationship into a bidirectional relationship. Here’s an example:

	@ManyToOne
	public User getUser() {
		return user;
	}

@ManyToMany

@ManyToMany describes the many to many association between entities. It is used in conjunction with the @JoinTable annotation to define the mapping table used for storing all the relationships. Here’s an example:

	@ManyToMany
	@JoinTable(name="tb_user_contact")
	public List<Contact> getContacts() {
		return contacts;
	}

and then in the Contact class we would have:

	@ManyToMany(mappedBy="contacts")
	public User getUser() {  
 		return user;  
	}  

The owning entity will always have the @JoinTable, and the owned entity will always have the @ManyToMany(mappedBy=?) annotation.

These are just a few things that can be done with ejb3. I would suggest sifting through the java 5 javadocs to get a better feel for the other possible annotations.

For more reading:
Javax Persistence API
Java 5 Persistence Tutorial
Official Java Persistence FAQ

Comments (0)

› No comments yet.

Leave a Reply

Allowed Tags - You may use these HTML tags and attributes in your comment.

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Pingbacks (1)

  1. 7:36 PM, February 17, 2010Favicon of www.edansys.comlinks for 2010-02-17 « edansys