EJB3: Mapping Persistent Objects Example 4

by admin ~ October 21, 2008

Following are the example from the chapter “Mapping Persistent Objects” from the book “Enterprise JavaBeans 3.0″ by Bill Bruke & Richard Monson-Haefel. This example I have tried it out on JBoss AS 5.0.0.CR1. I have used Postgresql as the database. And I have used eclipse WTP as IDE.


Example 4: Multitable Mappings

This example shows the use of @javax.persistence.SecondaryTable annotation to map one entity class to multiple tables.


Client.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package com.titan.clients;
 
import com.titan.travelagent.TravelAgentRemote;
import com.titan.domain.*;
import javax.naming.Context;
 
public class Client {
	public static void main(String[] args) {
		try {
			Context jndiContext = getInitialContext();
			Object ref = jndiContext
					.lookup("TitanCruises/TravelAgentBean/remote");
			TravelAgentRemote dao = (TravelAgentRemote) ref;
 
			Customer cust = new Customer();
			cust.setFirstName("Bill");
			cust.setLastName("Burke");
			cust.setStreet("Clarendon Street");
			cust.setCity("Boston");
			cust.setState("MA");
 
			long pk = dao.createCustomer(cust);
 
			System.out.println("pk :" + pk);
			cust = dao.findCustomer(pk);
			System.out.println(cust.getFirstName());
			System.out.println(cust.getLastName());
			System.out.println(cust.getStreet());
			System.out.println(cust.getCity());
			System.out.println(cust.getState());
		} catch (javax.naming.NamingException ne) {
			ne.printStackTrace();
		}
	}
 
	public static Context getInitialContext()
			throws javax.naming.NamingException {
		return new javax.naming.InitialContext();
	}
}

jndi.properties

1
2
3
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
java.naming.provider.url=127.0.0.1:1099

TravelAgentRemote.java

1
2
3
4
5
6
7
8
9
10
package com.titan.travelagent;
 
import javax.ejb.Remote;
import com.titan.domain.Customer;
 
@Remote
public interface TravelAgentRemote {
	public long createCustomer(Customer cust);
	public Customer findCustomer(long pk);
}

TravelAgentBean.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.titan.travelagent;
 
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import com.titan.domain.Customer;
 
@Stateless
public class TravelAgentBean implements TravelAgentRemote {
	@PersistenceContext(unitName = "titan")
	private EntityManager manager;
 
	public long createCustomer(Customer cust) {
		manager.persist(cust);
		return cust.getId();
	}
 
	public Customer findCustomer(long pk) {
		return manager.find(Customer.class, pk);
	}
}

Customer.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package com.titan.domain;
 
import javax.persistence.*;
 
@Entity
@Table(name = "CUSTOMER_TABLE")
@SecondaryTable(name = "ADDRESS_TABLE", pkJoinColumns = { @PrimaryKeyJoinColumn(name = "ADDRESS_ID") })
public class Customer implements java.io.Serializable {
	private long id;
	private String firstName;
	private String lastName;
	private String street;
	private String city;
	private String state;
 
	@Id
	@GeneratedValue
	public long getId() {
		return id;
	}
 
	public void setId(long id) {
		this.id = id;
	}
 
	public String getFirstName() {
		return firstName;
	}
 
	public void setFirstName(String first) {
		this.firstName = first;
	}
 
	public String getLastName() {
		return lastName;
	}
 
	public void setLastName(String last) {
		this.lastName = last;
	}
 
	@Column(name = "STREET", table = "ADDRESS_TABLE")
	public String getStreet() {
		return street;
	}
 
	public void setStreet(String street) {
		this.street = street;
	}
 
	@Column(name = "CITY", table = "ADDRESS_TABLE")
	public String getCity() {
		return city;
	}
 
	public void setCity(String city) {
		this.city = city;
	}
 
	@Column(name = "STATE", table = "ADDRESS_TABLE")
	public String getState() {
		return state;
	}
 
	public void setState(String state) {
		this.state = state;
	}
}

persistence.properties

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="UTF-8"?>
<persistence:persistence version="1.0" xmlns:persistence="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 persistence_1_0.xsd ">
  <persistence:persistence-unit name="titan" transaction-type="JTA">
    <persistence:description>Chapter: 6</persistence:description>
    <persistence:jta-data-source>java:/TitanDB</persistence:jta-data-source>
    <persistence:properties>
    	<persistence:property name="hibernate.hbm2ddl.auto" value="create"/>
    </persistence:properties>
  </persistence:persistence-unit>
</persistence:persistence>

application.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE application PUBLIC
	"-//Sun Microsystems, Inc.//DTD J2EE Application 1.3//EN"
	"http://java.sun.com/dtd/application_1_3.dtd">
<application>
	<display-name>TitanCruisesExample</display-name>
	<module>
		<ejb>TravelAgentBean.jar</ejb>
	</module>
	<module>
		<ejb>Customer.jar</ejb>
	</module>
</application>

Building the application: build.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?xml version="1.0" encoding="UTF-8"?>
<project name="Packaging Generator" default="_packaging_generation_">
	<target name="_packaging_generation_" depends="TitanCruisesExample" />
	<target name="TitanCruisesExample" description="TitanCruises.ear" depends="TravelAgentBean">
		<jar destfile="TitanCruises.ear">
			<zipfileset dir="conf" prefix="META-INF">
 
				<include name="application.xml" />
			</zipfileset>
			<zipfileset dir="/home/ranjan/workspaceEJB3/TitanCruises6_4">
				<include name="TravelAgentBean.jar" />
				<include name="Customer.jar" />
			</zipfileset>
		</jar>
	</target>
	<target name="TravelAgentBean" description="TravelAgentBean.jar" depends="Customer">
		<jar destfile="TravelAgentBean.jar">
			<zipfileset dir="/home/ranjan/workspaceEJB3/TitanCruises6_4/bin/com/titan/travelagent" prefix="com/titan/travelagent">
				<include name="TravelAgentRemote.class"/>
				<include name="TravelAgentBean.class"/>
			</zipfileset>	
		</jar>
	</target>
	<target name="Customer" description="Customer.jar">
		<jar destfile="Customer.jar">
			<zipfileset dir="conf" prefix="META-INF">
				<include name="persistence.xml" />
			</zipfileset>
			<zipfileset dir="/home/ranjan/workspaceEJB3/TitanCruises6_4/bin/com/titan/domain" prefix="com/titan/domain"/>
		</jar>
	</target>
</project>

Packaging Structure

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
TitanCruises.ear
  |
  |--- META-INF
  |     |
  |     |--- application.xml
  |     |
  |     |--- MENIFEST.MF
  |
  |--- Customer.jar
  |     |
  |     |--- META-INF 
  |     |     |
  |     |     |--- persistence.xml
  |     |     |    
  |     |     |--- MENIFEST.MF
  |     |
  |     |--- com
  |           |
  |           |--- titan
  |                  |
  |                  |--- domain
  |                         |
  |                         |--- Customer.class
  |
  |--- TravelAgentBean.jar
  |     |
  |     |--- META-INF 
  |     |     |
  |     |     |--- MENIFEST.MF
  |     |
  |     |--- com
  |            |
  |            |--- titan
  |                  |
  |                  |--- travelagent
  |                         |
  |                         |
  |                         |--- TravelAgentRemote.class
  |                         |
  |                         |--- TravelAgentBean.class

Server Console after successful deployment of the application

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
12:31:25,923 INFO  [JBossASKernel] Created KernelDeployment for: Customer.jar
12:31:25,931 INFO  [JBossASKernel] installing bean: persistence.units:ear=TitanCruises.ear,unitName=titan
12:31:25,931 INFO  [JBossASKernel]   with dependencies:
12:31:25,931 INFO  [JBossASKernel]   and demands:
12:31:25,931 INFO  [JBossASKernel]      jboss.jca:name=TitanDB,service=DataSourceBinding
12:31:25,931 INFO  [JBossASKernel]   and supplies:
12:31:25,932 INFO  [JBossASKernel]      persistence.units:unitName=titan
12:31:25,932 INFO  [JBossASKernel] Added bean(persistence.units:ear=TitanCruises.ear,unitName=titan) to KernelDeployment of: Customer.jar
12:31:26,052 INFO  [STDOUT] ======> Creating interceptor metadata bridge
12:31:26,623 INFO  [JBossASKernel] Created KernelDeployment for: TravelAgentBean.jar
12:31:26,623 INFO  [JBossASKernel] installing bean: jboss.j2ee:ear=TitanCruises.ear,jar=TravelAgentBean.jar,name=TravelAgentBean,service=EJB3
12:31:26,623 INFO  [JBossASKernel]   with dependencies:
12:31:26,624 INFO  [JBossASKernel]   and demands:
12:31:26,624 INFO  [JBossASKernel]      persistence.units:ear=TitanCruises.ear,unitName=titan
12:31:26,624 INFO  [JBossASKernel]      jboss.ejb:service=EJBTimerService
12:31:26,624 INFO  [JBossASKernel]   and supplies:
12:31:26,624 INFO  [JBossASKernel]      jndi:TitanCruises/TravelAgentBean/remote
12:31:26,624 INFO  [JBossASKernel]      jndi:TravelAgentBean
12:31:26,624 INFO  [JBossASKernel]      Class:com.titan.travelagent.TravelAgentRemote
12:31:26,624 INFO  [JBossASKernel]      jndi:TitanCruises/TravelAgentBean/remote-com.titan.travelagent.TravelAgentRemote
12:31:26,624 INFO  [JBossASKernel] Added bean(jboss.j2ee:ear=TitanCruises.ear,jar=TravelAgentBean.jar,name=TravelAgentBean,service=EJB3) to KernelDeployment of: TravelAgentBean.jar
12:31:26,662 INFO  [PersistenceUnitDeployment] Starting persistence unit persistence.units:ear=TitanCruises.ear,unitName=titan
12:31:26,859 INFO  [Version] Hibernate Annotations 3.4.0.CR1
12:31:26,897 INFO  [Environment] Hibernate 3.3.0.CR1
12:31:26,908 INFO  [Environment] hibernate.properties not found
12:31:26,915 INFO  [Environment] Bytecode provider name : javassist
12:31:26,948 INFO  [Environment] using JDK 1.4 java.sql.Timestamp handling
12:31:27,191 INFO  [Version] Hibernate Commons Annotations 3.1.0.CR1
12:31:27,198 INFO  [Version] Hibernate EntityManager 3.4.0.CR1
12:31:27,357 WARN  [Ejb3Configuration] Persistence provider caller does not implement the EJB3 spec correctly. PersistenceUnitInfo.getNewTempClassLoader() is null.
12:31:27,607 INFO  [AnnotationBinder] Binding entity from annotated class: com.titan.domain.Customer
12:31:27,705 INFO  [EntityBinder] Bind entity com.titan.domain.Customer on table CUSTOMER_TABLE
12:31:27,718 INFO  [EntityBinder] Adding secondary table to entity com.titan.domain.Customer -> ADDRESS_TABLE
12:31:27,827 INFO  [Version] Hibernate Validator 3.1.0.CR1
12:31:28,100 INFO  [ConnectionProviderFactory] Initializing connection provider: org.hibernate.ejb.connection.InjectedDataSourceConnectionProvider
12:31:28,104 INFO  [InjectedDataSourceConnectionProvider] Using provided datasource
12:31:28,524 INFO  [SettingsFactory] RDBMS: PostgreSQL, version: 8.1.11
12:31:28,525 INFO  [SettingsFactory] JDBC driver: PostgreSQL Native Driver, version: PostgreSQL 8.1 JDBC3 with SSL (build 412)
12:31:29,102 INFO  [Dialect] Using dialect: org.hibernate.dialect.PostgreSQLDialect
12:31:29,119 INFO  [TransactionFactoryFactory] Transaction strategy: org.hibernate.ejb.transaction.JoinableCMTTransactionFactory
12:31:29,126 INFO  [TransactionManagerLookupFactory] instantiating TransactionManagerLookup: org.hibernate.transaction.JBossTransactionManagerLookup
12:31:29,133 INFO  [TransactionManagerLookupFactory] instantiated TransactionManagerLookup
12:31:29,133 INFO  [SettingsFactory] Automatic flush during beforeCompletion(): disabled
12:31:29,133 INFO  [SettingsFactory] Automatic session close at end of transaction: disabled
12:31:29,133 INFO  [SettingsFactory] JDBC batch size: 15
12:31:29,133 INFO  [SettingsFactory] JDBC batch updates for versioned data: disabled
12:31:29,136 INFO  [SettingsFactory] Scrollable result sets: enabled
12:31:29,136 INFO  [SettingsFactory] JDBC3 getGeneratedKeys(): disabled
12:31:29,136 INFO  [SettingsFactory] Connection release mode: auto
12:31:29,139 INFO  [SettingsFactory] Default batch fetch size: 1
12:31:29,139 INFO  [SettingsFactory] Generate SQL with comments: disabled
12:31:29,139 INFO  [SettingsFactory] Order SQL updates by primary key: disabled
12:31:29,139 INFO  [SettingsFactory] Order SQL inserts for batching: disabled
12:31:29,139 INFO  [SettingsFactory] Query translator: org.hibernate.hql.ast.ASTQueryTranslatorFactory
12:31:29,148 INFO  [ASTQueryTranslatorFactory] Using ASTQueryTranslatorFactory
12:31:29,149 INFO  [SettingsFactory] Query language substitutions: {}
12:31:29,149 INFO  [SettingsFactory] JPA-QL strict compliance: enabled
12:31:29,149 INFO  [SettingsFactory] Second-level cache: enabled
12:31:29,149 INFO  [SettingsFactory] Query cache: disabled
12:31:29,171 INFO  [SettingsFactory] Cache region factory : org.hibernate.cache.impl.bridge.RegionFactoryCacheProviderBridge
12:31:29,172 INFO  [RegionFactoryCacheProviderBridge] Cache provider: org.hibernate.cache.HashtableCacheProvider
12:31:29,176 INFO  [SettingsFactory] Optimize cache for minimal puts: disabled
12:31:29,176 INFO  [SettingsFactory] Cache region prefix: TitanCruises_ear,titan
12:31:29,176 INFO  [SettingsFactory] Structured second-level cache entries: disabled
12:31:29,200 INFO  [SettingsFactory] Statistics: disabled
12:31:29,200 INFO  [SettingsFactory] Deleted entity synthetic identifier rollback: disabled
12:31:29,202 INFO  [SettingsFactory] Default entity-mode: pojo
12:31:29,202 INFO  [SettingsFactory] Named query checking : enabled
12:31:29,328 INFO  [SessionFactoryImpl] building session factory
12:31:29,868 INFO  [SessionFactoryObjectFactory] Factory name: persistence.units:ear=TitanCruises.ear,unitName=titan
12:31:29,872 INFO  [NamingHelper] JNDI InitialContext properties:{java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory, java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces}
12:31:29,876 INFO  [SessionFactoryObjectFactory] Bound factory to JNDI name: persistence.units:ear=TitanCruises.ear,unitName=titan
12:31:29,876 WARN  [SessionFactoryObjectFactory] InitialContext did not implement EventContext
12:31:29,920 INFO  [SchemaExport] Running hbm2ddl schema export
12:31:29,923 INFO  [SchemaExport] exporting generated schema to database
12:31:30,389 INFO  [SchemaExport] schema export complete
12:31:30,390 INFO  [NamingHelper] JNDI InitialContext properties:{java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory, java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces}
12:31:30,986 INFO  [EJBContainer] STARTED EJB: com.titan.travelagent.TravelAgentBean ejbName: TravelAgentBean

Client’s Console after running the Client.java

1
2
3
4
5
6
pk :1
Bill
Burke
Clarendon Street
Boston
MA

References:

“Java Persistence with Hibernate” by Christian Bauer and Gavin King.
“Enterprise JavaBeans 3.0″ by Bill Burke & Richard Monson-Haefel
JBoss Documentations for EJB 3

Share This Post

Leave a Reply