08. HelloJPA - AntonioDiaz/examples.spring.mvc GitHub Wiki
Proof of concept of a Spring MVC project using JPA (Java Persistence API) to access to a MySQL database.
Thanks to: www.javacodegeeks.com/2015/02/jpa-tutorial.html
- Project structure
- pom.xml
- applicationContext.xml
- Entities
- DAOs
- Services
- Controllers
- Avoid lazy-loading exception
- Adding HSQLDB
- Run HSQLDB
- Query with JPQL

<properties>
<spring.version>4.1.4.RELEASE</spring.version>
<log4j.version>1.2.17</log4j.version>
<jstl.version>1.2</jstl.version>
<apache.commons>3.4</apache.commons>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>${jstl.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${apache.commons}</version>
</dependency>
<!-- persistence dependences. -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.2.0.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate.common</groupId>
<artifactId>hibernate-commons-annotations</artifactId>
<version>4.0.1.Final</version>
<classifier>tests</classifier>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.0.0.GA</version>
</dependency>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.0-api</artifactId>
<version>1.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<version>3.1.0.CR2</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.4</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.10</version>
</dependency>
</dependencies> <!-- This produces a container-managed EntityManagerFactory; rather than application-managed EntityManagerFactory as in case of LocalEntityManagerFactoryBean -->
<bean id="entityManagerFactoryBean" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- This makes /META-INF/persistence.xml is no longer necessary -->
<property name="packagesToScan" value="com.persistence" />
<!-- JpaVendorAdapter implementation for Hibernate EntityManager. Exposes Hibernate's persistence provider and EntityManager extension interface -->
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">create</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
</props>
</property>
</bean>
<!-- This transaction manager is appropriate for applications that use a single JPA EntityManagerFactory for transactional data access. JTA (usually through
JtaTransactionManager) is necessary for accessing multiple transactional resources within the same transaction. -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactoryBean" />
</bean>
<!-- Simple implementation of the standard JDBC DataSource interface, configuring the plain old JDBC DriverManager via bean properties -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://192.168.137.4:3306/test_schema" />
<property name="username" value="test_user" />
<property name="password" value="test_user" />
</bean>
<tx:annotation-driven />import javax.persistence.*;
@Entity
@Table(name = "T_PERSON")
public class Person {
@Id
@GeneratedValue
private Long id;
@Column(name = "FIRST_NAME")
private String firstName;
@Column(name = "LAST_NAME")
private String lastName;
@OneToOne(cascade = { CascadeType.ALL })
@JoinColumn(name = "ID_CARD_ID")
private IdCard idCard;
@OneToMany(mappedBy = "person", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private List<Phone> phones = new ArrayList<>();
/* getters and setters. */
}import javax.persistence.*;
@Entity
@Table(name = "T_PHONE")
public class Phone {
@Id
@GeneratedValue
private Long id;
@Column(name = "NUMBER")
private String number;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "PERSON_ID")
private Person person;
}package com.daos;
public interface GenericDAO<T> {
public void create(T item) throws Exception;
public void update(T item) throws Exception;
public void remove(T item) throws Exception;
}package com.daos;
import java.util.List;
import com.persistence.Person;
public interface PersonDAO extends GenericDAO<Person> {
public List<Person> getPersonAll();
public Person getPersonById(Long id);
public Person getPersonByIdJoin(Long id);
public List<Person> getPersonByNameEqual(String name);
public List<Person> getPersonByNameLike(String name);
public List<Person> getPersonsByPhone(String myPhone);
public List<Person> getPersonsByPhoneCriteria(String myPhone);
}package com.daos;
import javax.persistence.*;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
@Repository
@Transactional
public class PersonDAOImpl implements PersonDAO {
@PersistenceContext
private EntityManager entityManager;
@Override
public void create(Person person) throws Exception {
entityManager.persist(person);
}
@Override
public void update(Person person) throws Exception {
entityManager.merge(person);
}
@Override
public void remove(Person person) throws Exception {
entityManager.remove(entityManager.contains(person) ? person : entityManager.merge(person));
}
@Override
public List<Person> getPersonAll() {
return entityManager.createQuery("Select a From Person a", Person.class).getResultList();
}
@Override
public Person getPersonById(Long id) {
TypedQuery<Person> typedQuery = entityManager.createQuery("Select a From Person a Where a.id=:person_id", Person.class);
Person person = null;
try {
person = typedQuery.setParameter("person_id", id).getSingleResult();
} catch (NoResultException e) { }
return person;
}
@Override
public Person getPersonByIdJoin(Long id) {
TypedQuery<Person> typedQuery = entityManager.createQuery("Select a From Person a left join fetch a.phones s Where s.id=:person_id", Person.class);
Person person = null;
try {
person = typedQuery.setParameter("person_id", id).getSingleResult();
} catch (NoResultException e) { }
return person;
}
@Override
public List<Person> getPersonByNameEqual(String name) {
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Person> query = builder.createQuery(Person.class);
Root<Person> personRoot = query.from(Person.class);
query.where(builder.equal(personRoot.get("firstName"), name));
return entityManager.createQuery(query).getResultList();
}
@Override
public List<Person> getPersonByNameLike(String name) {
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Person> query = builder.createQuery(Person.class);
Root<Person> personRoot = query.from(Person.class);
/* create like expresion. */
EntityType<Person> type = entityManager.getMetamodel().entity(Person.class);
SingularAttribute<Person, String> declaredSingularAttribute = type.getDeclaredSingularAttribute("firstName", String.class);
Path<String> path = personRoot.get(declaredSingularAttribute);
Expression<String> expresion = builder.lower(path);
query.where(builder.like(expresion, name + "%"));
return entityManager.createQuery(query).getResultList();
}
@Override
public List<Person> getPersonsByPhone(String myPhone) {
List<Person> resultList = null;
TypedQuery<Person> typedQuery = entityManager.createQuery("Select a From Person a left join fetch a.phones s Where s.number=:my_number", Person.class);
resultList = typedQuery.setParameter("my_number", myPhone).getResultList();
return resultList;
}
@Override
public List<Person> getPersonsByPhoneCriteria(String myPhone) {
List<Person> resultList = null;
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Person> query = builder.createQuery(Person.class);
Root<Person> personRoot = query.from(Person.class);
Join<Object, Object> join = personRoot.join("phones", JoinType.LEFT);
query.where(builder.equal(join.get("number"), myPhone));
resultList = entityManager.createQuery(query).getResultList();
return resultList;
}
public List<Person> getPersonsByPhoneCriteriaAux(String myPhone) {
List<Person> resultList = null;
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Person> query = builder.createQuery(Person.class);
Root<Person> personRoot = query.from(Person.class);
Fetch<Person, Phone> myFetch = personRoot.fetch("phones", JoinType.LEFT);
query.where(builder.equal(personRoot.get("firstName"), myPhone));
//query.where(builder.equal(myFetch.get("firstName"), myPhone));
resultList = entityManager.createQuery(query).getResultList();
return resultList;
}
}package com.services;
import java.util.List;
import com.persistence.Person;
public interface PersonManager {
public void createUser(Person person) throws Exception;
public void updteUser(Person person) throws Exception;
public List<Person> queryPersonAll() throws Exception;
public Person queryPersonById(Long id) throws Exception;
public Person queryPersonByIdJoin(Long id) throws Exception;
public Person queryPersonByPhone(String myPhone) throws Exception;
public Person queryPersonByPhoneCriteria(String myPhone) throws Exception;
public List<Person> queryPersonByNameEqual(String name) throws Exception;
public List<Person> queryPersonByNameLike(String name) throws Exception;
}package com.services;
@Service
public class PersonManagerImpl implements PersonManager {
@Autowired private PersonDAO personDAO;
@Override
public void createUser(Person person) throws Exception {
personDAO.create(person);
}
@Override
public List<Person> queryPersonAll() throws Exception {
return personDAO.getPersonAll();
}
@Override
public Person queryPersonById(Long id) throws Exception {
return personDAO.getPersonById(id);
}
@Override
public Person queryPersonByIdJoin(Long id) throws Exception {
return personDAO.getPersonByIdJoin(id);
}
@Override
public List<Person> queryPersonByNameEqual(String name) throws Exception {
return personDAO.getPersonByNameEqual(name);
}
@Override
public List<Person> queryPersonByNameLike(String name) throws Exception {
return personDAO.getPersonByNameLike(name);
}
@Override
public void updteUser(Person person) throws Exception {
personDAO.update(person);
}
@Override
public Person queryPersonByPhone(String myPhone) throws Exception {
Person person = null;
List<Person> persons = personDAO.getPersonsByPhone(myPhone);
if (persons.size() > 1) {
throw new Exception("More than one person.");
}
if (persons.size()==1) {
person = persons.get(0);
}
return person;
}
@Override
public Person queryPersonByPhoneCriteria(String myPhone) throws Exception {
Person person = null;
List<Person> persons = personDAO.getPersonsByPhoneCriteria(myPhone);
if (persons.size() > 1) {
throw new Exception("More than one person.");
}
if (persons.size()==1) {
person = persons.get(0);
}
return person;
}
}https://github.com/FasterXML/jackson-datatype-hibernate
- pom.xml
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-hibernate4</artifactId>
<version>2.5.3</version>
</dependency>- applicationContext.xml
<mvc:annotation-driven>
<mvc:message-converters>
<!-- Use the HibernateAware mapper instead of the default -->
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="com.utilities.HibernateAwareObjectMapper" />
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>- HibernateAwareObjectMapper.java
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.hibernate4.Hibernate4Module;
public class HibernateAwareObjectMapper extends ObjectMapper {
private static final long serialVersionUID = 1L;
public HibernateAwareObjectMapper() {
registerModule(new Hibernate4Module());
}
}Thanks to: http://devcrumb.com/hibernate/hibernate-jpa-spring-and-hsqldb
- pom.xml
<!-- Spring JDBC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.1.4.RELEASE</version>
</dependency>
<!-- HyperSQL DB -->
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>2.3.2</version>
</dependency> - applicationContext.xml
<bean id="entityManagerFactoryBean" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.persistence" />
<property name="persistenceUnitName" value="jpaData" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">false</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactoryBean" />
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.hsqldb.jdbcDriver" />
<property name="url" value="jdbc:hsqldb:hsql://localhost/" />
<property name="username" value="sa" />
<property name="password" value="" />
</bean>- pesistence.xml
In META-INF folder.
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0"
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">
<persistence-unit name="jpaData" />
</persistence>Select Java Application: org.hsqldb.Server

import javax.persistence.TypedQuery;
public List<ResourceEntity> getResources(String name, Integer author, String organization) {
String queryStr = "Select a From ResourceEntity a join fetch a.uploadedUser as u where 1=1";
if (StringUtils.isNotEmpty(name)) {
queryStr += " and UPPER(a.name) like :name";
}
if (author!=null) {
queryStr += " and u.id = :id_author";
}
if (StringUtils.isNotEmpty(organization)) {
queryStr += " and UPPER(u.organization) like :organization";
}
TypedQuery<ResourceEntity> typedQuery = em.createQuery(queryStr, ResourceEntity.class);
if (StringUtils.isNotEmpty(name)) {
typedQuery = typedQuery.setParameter("name", "%" + name.toUpperCase() + "%");
}
if (author!=null) {
typedQuery = typedQuery.setParameter("id_author", author);
}
if (StringUtils.isNotEmpty(organization)) {
typedQuery = typedQuery.setParameter("organization", "%" + organization.toUpperCase() + "%");
}
return typedQuery.getResultList();
}