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); } }