The bundle uses JPA to create a Person service. The Person has a one to many
relationship to Address, but to keep the example simple only the Person
is used by the web module. JPA is using Hibernate for persistence.
The bundle imports javax.sql, HSQL DB, Spring, and Hibernate.
It also exports the package containing the Hibernate persistence beans
and the Person DAO interface.
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Simple Spring MVC Person Bundle
Bundle-Description: Simple Spring MVC Person
Bundle-SymbolicName: org.springbyexample.sdms.simpleForm.person
Bundle-Version: 1.0.0
Bundle-Vendor: Spring by Example
Import-Package: javax.sql
Import-Bundle: com.springsource.org.hsqldb;version="[1.8.0,2.0.0)"
Import-Library: org.springframework.spring;version="[2.5.5,3.0.0)",
org.hibernate.ejb;version="[3.3.2.GA,3.3.2.GA]"
Export-Package: org.springbyexample.sdms.simpleForm.orm.bean;version="1.0.0",
org.springbyexample.sdms.simpleForm.orm.dao;version="1.0.0"
The JPA configuration sets up Hibernate as the persistence provider and
registers the two entity classes Person and Address.
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="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 http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0">
<persistence-unit name="personDatabase">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>org.springbyexample.sdms.simpleForm.orm.bean.Person</class>
<class>org.springbyexample.sdms.simpleForm.orm.bean.Address</class>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" />
<!--
Note: setting 'hibernate.hbm2ddl.auto' to 'create' will result in
'import.sql' (in the root of the classpath) being used to populate
the DB
-->
<property name="hibernate.hbm2ddl.auto" value="create" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.HashtableCacheProvider" />
</properties>
</persistence-unit>
</persistence>
The context:component-scan is used to Person DAO implementation,
and tx:annotation-driven configures Spring to process
transaction annotations. A JPA transaction manager is created and
JPA with i and also with the DataSource from the OSGi service.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:component-scan base-package="org.springbyexample.sdms.simpleForm.orm.impl"/>
<tx:annotation-driven />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
</bean>
</beans>
The javax.sql.DataSource exposed by the previous bundle is referenced,
and the Person DAO implementation is registered as an OSGi service.
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/osgi"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/osgi
http://www.springframework.org/schema/osgi/spring-osgi-1.0.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<reference id="dataSource" interface="javax.sql.DataSource" />
<service ref="personDao" interface="org.springbyexample.sdms.simpleForm.orm.dao.PersonDao" />
</beans:beans>
The Person entity uses javax.persistence annotation for configuration.
Example 1. Person Entity
Excerpt from sdms/simple-spring-mvc/simple-spring-mvc-person/src/main/java/org/springbyexample/sdms/simpleForm/orm/bean/Person.java
@Entity
@Table(name="PERSON")
public class Person implements Comparable<Person>, Serializable {
...
private Integer id = null;
private String firstName = null;
private String lastName = null;
private Set<Address> addresses = null;
private Date created = null;
/**
* Gets id (primary key).
*/
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
public Integer getId() {
return id;
}
/**
* Sets id (primary key).
*/
public void setId(Integer id) {
this.id = id;
}
/**
* Gets first name.
*/
@Column(name="FIRST_NAME")
public String getFirstName() {
return firstName;
}
/**
* Sets first name.
*/
public void setFirstName(String firstName) {
this.firstName = firstName;
}
/**
* Gets last name.
*/
@Column(name="LAST_NAME")
public String getLastName() {
return lastName;
}
/**
* Sets last name.
*/
public void setLastName(String lastName) {
this.lastName = lastName;
}
/**
* Gets list of <code>Address</code>es.
*/
@OneToMany(fetch=FetchType.EAGER, cascade=CascadeType.ALL)
@JoinColumn(name="PERSON_ID", nullable=false)
public Set<Address> getAddresses() {
return addresses;
}
/**
* Sets list of <code>Address</code>es.
*/
public void setAddresses(Set<Address> addresses) {
this.addresses = addresses;
}
/**
* Gets date created.
*/
public Date getCreated() {
return created;
}
/**
* Sets date created.
*/
public void setCreated(Date created) {
this.created = created;
}
public Address findAddressById(Integer id) {
Address result = null;
if (addresses != null) {
for (Address address: addresses) {
if (address.getId().equals(id)) {
result = address;
break;
}
}
}
return result;
}
...
}
The Person DAO implementation uses the JPA EntityManager for managing a Person.
Example 2. Person DAO Implementation
@Repository("personDao")
@Transactional(readOnly = true)
public class PersonDaoImpl implements PersonDao {
private EntityManager em;
@PersistenceContext
public void setEntityManager(EntityManager em) {
this.em = em;
}
/**
* Find persons.
*/
@SuppressWarnings("unchecked")
public Person findPersonById(Integer id) {
return em.find(Person.class, id);
}
/**
* Find persons using a start index and max number of results.
*/
@SuppressWarnings("unchecked")
public Collection<Person> findPersons(final int startIndex, final int maxResults) {
return em.createQuery("select p from Person p order by p.lastName, p.firstName")
.setFirstResult(startIndex).setMaxResults(maxResults).getResultList();
}
/**
* Find persons.
*/
@SuppressWarnings("unchecked")
public Collection<Person> findPersons() {
return em.createQuery("select p from Person p order by p.lastName, p.firstName").getResultList();
}
/**
* Find persons by last name.
*/
@SuppressWarnings("unchecked")
public Collection<Person> findPersonsByLastName(String lastName) {
return em.createQuery("select p from Person p where p.lastName = :lastName order by p.lastName, p.firstName")
.setParameter("lastName", lastName).getResultList();
}
/**
* Saves person.
*/
@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
public Person save(Person person) {
return em.merge(person);
}
/**
* Deletes person.
*/
@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
public void delete(Person person) {
em.remove(em.merge(person));
}
/**
* Saves address to person.
*/
@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
public Person saveAddress(Integer id, Address address) {
Person person = findPersonById(id);
if (person.getAddresses().contains(address)) {
person.getAddresses().remove(address);
}
person.getAddresses().add(address);
return save(person);
}
/**
* Deletes address from person.
*/
@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
public Person deleteAddress(Integer id, Integer addressId) {
Person person = findPersonById(id);
Address address = new Address();
address.setId(addressId);
if (person.getAddresses().contains(address)) {
person.getAddresses().remove(address);
}
return save(person);
}
}