Google

Jun 19, 2013

JPA interview questions and answers and high level overview - part 1

Q. What is a JPA? What are its key components?
A. The process of mapping Java objects to database tables and vice versa is called "Object-relational mapping" (ORM). The Java Persistence API provides Java developers with an object/relational mapping  (ORM) facility for managing relational data in Java applications. JPA is a specification and several implementations are available like EJB, JDO, Hibernate, and Toplink. Via JPA the developer can map, store, update and retrieve data from relational databases to Java objects and vice versa. 


Q. What is the difference between hibernate.cfg.xml and persistence.xml?
A. If you are using Hibernate's proprietary API, you'll need the hibernate.cfg.xml. If you are using JPA i.e. Hibernate EntityManager, you'll need the persistence.xml. You will not need both as you will be using either Hibernate proprietary API or JPA. However, if you had used Hibernate Proprietary API using hibernate.cfg.xml with hbm.xml mapping files, and now wanted to start using JPA, you can reuse the existing configuration files by referencing the hibernate.cfg.xml in the persistence.xml in the hibernate.ejb.cfgfile property and reuse the existing hbm.xml files. In a long run, migrate hbm.xml files to JPA annotations.


Q. What is an EntityManagerFactory and a Persistence unit?
A. The EntityManager is created by the EntitiyManagerFactory which is configured by the persistence unit. The persistence unit is described via the file "persistence.xml" in the directory META-INF in the source folder. It defines a set of entities which are logically connected and the connection properties as shown below via an example.

 
<?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="myapp-server" transaction-type="RESOURCE_LOCAL">

  <provider>org.hibernate.ejb.HibernatePersistence</provider>
  
        <!-- import other mapping files if any -->
        <mapping-file>META-INF/myApp2.xml</mapping-file>

  <class>com.mycompany.myapp.Person</class>
  
  <exclude-unlisted-classes>true</exclude-unlisted-classes>

  <properties>
   <property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.EmbeddedDriver" />
            <property name="javax.persistence.jdbc.url" value="jdbc:derby:/home/myapp/databases/simpleDb;create=true" />
            <property name="javax.persistence.jdbc.user" value="test" />
            <property name="javax.persistence.jdbc.password" value="test" />
    
   <!-- force Hibernate to use a singleton of Ehcache CacheManager -->
   <property name="hibernate.cache.region.factory_class"
    value="org.hibernate.cache.ehcache.EhCacheRegionFactory" />
   <property name="hibernate.cache.use_second_level_cache" value="true" />
         <property name="hibernate.cache.use_query_cache" value="true" />
   <property name="net.sf.ehcache.configurationResourceName" value="ehcache.xml" />
  </properties>

 </persistence-unit>
</persistence>


Usually, JPA defines a persistence unit through the META-INF/persistence.xml file. Starting with Spring 3.1, this XML file is no longer necessary – the LocalContainerEntityManagerFactoryBean now supports a ‘packagesToScan’ property where the packages to scan for @Entity classes can be specified. The snippet below shows how you can bootstrap with or without persistence.xml.

 
package com.mycompany.app.config;

import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
import org.springframework.orm.hibernate4.HibernateExceptionTranslator;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;


@Configuration
@PropertySource(value =
{"classpath:/common/jpa.properties"
})
@EnableTransactionManagement
public class JpaConfig
{
    @Value("${my_app_common_jpa_showSql:false}")
    private Boolean showSql;
    
    @Value("${my_app_common_jpa_hibernateDialect}")
    private String hibernateDialect;
    
    @Value("${my_app_common_jpa_generateStatistics:false}")
    private Boolean generateStatistics;
    
    @Value("${my_app_common_jpa_generateDdl:false}")
    private Boolean generateDdl;
    
    @Value("${my_app_common_jpa_databasePlatform}")
    private String databasePlatform;
    
    @Resource(name = "myAppDataSource")
    private DataSource dataSource;
    
    private static Logger LOGGER = LoggerFactory.getLogger(JpaConfig.class);
    
    @Bean
    public Map<String, Object> jpaProperties()
    {
        LOGGER.debug("jpaProperties hibernateDialect=" + hibernateDialect);
        
        Map<String, Object> props = new HashMap<String, Object>();
        props.put("hibernate.dialect", hibernateDialect);
        props.put("hibernate.generate_statistics", generateStatistics);
        
        return props;
    }
    
    @Bean
    public JpaVendorAdapter jpaVendorAdapter()
    {
        LOGGER.debug("jpaProperties databasePlatform=" + databasePlatform);
        
        HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
        hibernateJpaVendorAdapter.setShowSql(showSql);
        hibernateJpaVendorAdapter.setGenerateDdl(generateDdl);
        hibernateJpaVendorAdapter.setDatabasePlatform(databasePlatform);
        
        return hibernateJpaVendorAdapter;
    }
    
    @Bean
    public PlatformTransactionManager transactionManager()
    {
        return new JpaTransactionManager(entityManagerFactory());
    }
    
    @Bean
    public EntityManagerFactory entityManagerFactory()
    {
        LocalContainerEntityManagerFactoryBean lef = new LocalContainerEntityManagerFactoryBean();
        
        lef.setDataSource(dataSource);
        lef.setJpaPropertyMap(this.jpaProperties());
        lef.setJpaVendorAdapter(this.jpaVendorAdapter());
        lef.setPersistenceXmlLocation("META-INF/persistence.xml");
        //alternative without persistence.xml from Spring 3.1
        //lef.setPackagesToScan("com.mycompany.myapp");
        lef.afterPropertiesSet();
        
        return lef.getObject();
    }
    
    @Bean
    public PersistenceExceptionTranslationPostProcessor exceptionTranslation()
    {
        return new PersistenceExceptionTranslationPostProcessor();
    }
    
    @Bean
    public HibernateExceptionTranslator hibernateExceptionTranslator()
    {
        return new HibernateExceptionTranslator();
    }
}

The jpa.properties can be defined as shown below.

 
# properties for JPA
my_app_common_jpa_showSql=false
my_app_common_jpa_generateDdl=false

my_app_common_jpa_databasePlatform=SYBASE
my_app_common_jpa_hibernateDialect=org.hibernate.dialect.SybaseASE15Dialect
my_app_common_jpa_generateStatistics=true
my_app_common_aesJndiName=java:comp/env/jdbc/my_db

The configuration shown above is Java based config, and  if you want to use a Spring xml file based config, it will look like

 
<bean id="myEmf"
 class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
   <property name="dataSource" ref="dataSource" />
   <property name="packagesToScan" value="org.rest" />
   <property name="jpaVendorAdapter">
      <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
         <property name="showSql" value="${my_app_common_jpa_showSql}" />
         <property name="generateDdl" value="${my_app_common_jpa_generateDdl}" />
         <property name="databasePlatform" value="${my_app_common_jpa_hibernateDialect}" />
      </bean>
   </property>
</bean>
 
<bean id="dataSource"
 class="org.springframework.jdbc.datasource.DriverManagerDataSource">
   <property name="driverClassName" value="${driverClassName}" />
   <property name="url" value="${url}" />
   <property name="username" value="${user}" />
   <property name="password" value="${password}" />
</bean>
 
<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
   <property name="entityManagerFactory" ref="myEmf" />
</bean>
<tx:annotation-driven transaction-manager="txManager" />

Labels: , ,

0 Comments:

Post a Comment

Subscribe to Post Comments [Atom]

<< Home