You are on page 1of 14

Hibernate on

SAP NetWeaver
Usando Data Source
El SAP NWAS el concepto de "Data Source" puede ser utilizado
para establecer conexiones a la base de datos. Un Data Source
encapsula la BD's usada, el JDBC-Driver es el indicado para
iniciar la session de la información. Aunque la información
puede ser acezada mediante hibérnate, es recomendable el uso del
Data Source, ya que viene con un built-in Connection Pooling -
en contraste con una conexión normal JDBC no es necesario
utilizar un componente de terceros para realizar un pool de
conexiones en SAP NWAS. Este es un servicio automático del
Application Server.

Hay tres tipos de Data Source que establecen conexiones a la BD


elegida. El primero, es un Vendor SQL Data Source Este solo
encapsula un controlador JDBC normal de la base de datos
descrita anteriormente.

Un Native SQL Data Source sin embargo ofrece una capa adicional
al rededor del controlador. Esto le permite usar SQL Tracing y
Statement Pooling así como unas características adicionales. Esto
aumenta el rendimiento de las aplicaciones, por un lado, por otro lado
puede seguir haciendo declaraciones en el SAP SQL Trace Tool
(Accesible desde el SAP NetWeaver Administrator desde
http://<servername>:<port>).

No se recomienda utilizar el System default Data Source con hibernate


ya que este utiliza el Open SQL layer. Su sintaxis específica
prevista para la base de datos de programación independiente no
es compatible con Hibernate - y, de hecho, no es necesario como
Hibernate sí los resúmenes de la base de datos.

Por lo tanto, es recomendado para el uso de Hibernate en SAP


NWAS utilizar un Native SQL Data Source. Por eso se propone lo
siguiente:

• Desplegar el controlador JDBC apropiado para tu Base de


Datos en el JDBC Connector Service de el Visual
Administrator.
• Crear un Data Source propio y proveer el controlador de la
clase y la URL de la Base de Datos para conectarse a la
base de datos. En el caso de una Base de Datos de
SAPDB/MaxDB por ejemplo la información será:

o Driver Class: com.sap.dbtech.jdbc.DriverSapDB


o atabase URL: jdbc:sapdb://<Hostname>/<databaseName>
jdbc:sapdb://localhost/F04

En la pestaña Additional de el JDBC Conector Service puedes


definir los parámetros de la Conection Pooling para tu Data
Source.

Puedes referirte a este Data Source creado desde la


configuración del hibernate con el documento hibernate.cfg.xml
con el fin de ofrecer una conexión de BDs con hibernate. Este
tema es discutido en la próxima sección.

Configuraciones de Hibernate

Aquí está un panorama general de cómo configurar Hibernate para


el SAP NWAS.
Además de un programa de configuración, Hibernate ofrece un archivo de
configuración XML hibernate.cfg.xml para ajustar el comportamiento de
hibernate en tiempo de ejecución que puedan tener este aspecto:

<!DOCTYPE hibernate-configuration PUBLIC


"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Provide the Data Source you defined before -->
<property name="connection.datasource">jdbc/Hibernate3</property>
<property
name="dialect">org.hibernate.dialect.SAPDBDialect</property>

<!-- Delegate Hibernate´s transactions to the J2EE-Engine´s JTA->


<property name="transaction.factory_class">
org.hibernate.transaction.JTATransactionFactory
</property>
<property name="transaction.manager_lookup_class">
org.hibernate.transaction.SAPWebASTransactionManagerLookup
</property>

<!-- Bind Session Factory to JNDI -->


<property name="hibernate.session_factory_name">
hibernate/SessionFactory
</property>

<!-- Use EHCache as Cache Provider and use its Query Cache -->
<property name="hibernate.cache.provider_class">
org.hibernate.cache.EhCacheProvider
</property>
<property name="hibernate.cache.use_query_cache">true</property>
<property name="show_sql">true</property>
<property name="current_session_context_class">thread</property>

<!-- declare all mapping files -->


<mapping
resource="com/sap/j2ee/examples/hibernate/ObjectA.hbm.xml"/>
<mapping
resource="com/sap/j2ee/examples/hibernate/ObjectB.hbm.xml"/>
</session-factory>
</hibernate-configuration>

Como se comento anteriormente, este documento define la


configuración que hibernate utiliza para crear su Data Source en
SAP NWAS. Adicionalmente, una vez creado, La Session Factory de
Hibernate es ligada al JNDI y puede ser consultado bajo el
nombre que se proporciona aquí. También tienes que definir, que
documentos mapeados te gustaría utilizar en su aplicación. Las
configuraciones de transacciones y cacheo que serán explicadas
en las siguientes secciones.
El archivo de configuración hibernate.cfg.xml debe residir
naturalmente en el proyecto EJB, ya que depende de la misma
aplicación y un EJB es el usuario de Hibernate en una
arquitectura de capas. Por lo tanto, usted debe colocar este
archivo en la raíz del proyecto EJB. EL archivo es leído por una
instancia de la configuración antes de la creación de una
SessionFactory. Desde la SAP NWAS utilizas una sintaxis para el
camino diferente, el nombre del archivo tiene que ser siempre
como un parámetro de cadena en el llamado desde el método
configure(), la instancia de la configuración se muestra a
continuación:

Configuration cfg = new Configuration();


sessionFactory = cfg.configure("hibernate.cfg.xml"). buildSessionFactory();

Esto no suele ser necesario en otros entornos, pero debe de


tenerse en cuenta para las aplicaciones que utilizan Hibernate
ejecutándose en SAP NWAS.

Transacciones Hibernate y J2EE


Para la portabilidad entre los entornos administrados y no
administrados, Hibernate define un API de transacciones propias
el cual abstrae desde la implementación actual.

En entornos no administrados el mismo Hibernate puede ejecutar


transacciones JDBC. Sin embargo, en un entorno administrado como
el SAP NWAS, es conveniente integrar las APIs de Hibernate con
la implementación JTA proporcionada por el servidor de
aplicaciones.

Por lo tanto, el método recomendado es usar las APIs de


transacciones de Hibernate a fin de implementar las
transaccionabiliad en el código JAVA, el cual actualmente es
delegado para el servicio JTA del SAP NWAS.

Para la delegación de la transacción tendrá que proporcionar la


interfaz UserTransaction de la JTA de Hibernate.

Sin embargo, con el fin de integrar plenamente a los


contenedores con las transacciones y permitir a la caché de
Segundo Nivel de SAP NWAS, es necesario facilitar el acceso al
servidor interno así como al componente TransactionManager.
Lamentablemente, la especificación J2EE no dice mucho acerca de
si esto está permitido o si está prohibido. Uno siempre debe
tener en cuenta, que para obtener un acceso a este objeto, usted
obtendrá un acceso para el servidor-interno de la transacción de
objetos. Usted debe tener cuidado con el uso del acceso para el
Transaction Manager, ya que esto es filosóficamente no se ha
probado por la especificación J2EE. Una aplicación debería tomar
una influencia sobre las transacciones sólo a través de la
interfaz javax.transaction.UserTransaction.

Ambas interfaces están expuestos para Hibernate usando una


simple clase Java en el proyecto EJB, ofreciendo dos métodos,
simplemente retornando los nombres de las interfaces en el JNDI.
Por favor, ten cuidado de que el nombre del paquete y los
nombres sean correctos así como de donde tienen que derivar las
clases.

La aplicación es bastante fácil y se ve a continuación:

package org.hibernate.transaction;

public class SAPWebASTransactionManagerLookup


extends org.hibernate.transaction.JNDITransactionManagerLookup {
protected String getName() {
return "TransactionManager";
}
public String getUserTransactionName() {
return "UserTransaction";
}
}

El nombre de esta clase de búsqueda que proporciono en su


proyecto EJB, es el nombre que ya hemos utilizado en la sección
Configuración. Ahí definimos el documento de configuración
hibernate.cfg.xml:
<property name="transaction.manager_lookup_class">
org.hibernate.transaction.SAPWebASTransactionManagerLookup
</property>

La plena integración de Hibernate en el servidor de aplicaciones


no siempre es necesaria. Hibernate utiliza el TransactionManager
del ambiente de ejecución de la capa inferior para su propio
denominado cache de segundo nivel. Si no utiliza esta cache, No
necesitas necesariamente la aplicación del servidor
TransactionManager. Más sobre el segundo nivel de caché sigue en
la siguiente sección.

Mecanismo de cacheo en Hibernate


Hibernate implementa un nivel de dos-niveles-cache-arquitectura

• Primer nivel de Cache-La misma Session


• Segundo nivel de cache- proceso o grupo, por lo general el
alcance de la SessionFactory

Hibernate le permite integrar una caché de Segundo Nivel de


implementación. Los proveedores de caché están inicializadas y
utilizados por Hibernate automáticamente.

Tenga en cuenta que el uso de una caché de segundo nivel


requiere de las medidas mencionadas antes en relación con el
acceso al servidor-interno de gestión de transacciones.

Hibernate viene con el EHCache en el paquete Hibernate Core, que


es fácilmente aplicable a un solo servidor de configuración.

Usted también puede elegir uno de los siguientes proveedores de


cache:

EHCache-VM único de cacheo (contruido en) o agrupado en caché.

OpenSymphony OSCache - VM único de cacheo.

SwarmCache basado sobre JGroups - agrupadas cache.

JBossCache - agrupadas cache.

Solo la configuración del servidor


EHCache en un único servidor de configuración, tres pasos serán
necesarios:

Con el fin de configurar la memoria caché, usted tiene que:

• Agregue el archivo Java proveedor de la memoria caché (por


ejemplo, ehcache-1.1.jar) para la Librería ya se ha
mencionado proyecto y desplegar en SAP NWAS. para la
librería del proyecto mencionada al principio y
desplegándolo en SAP NWAS.
• Definir el uso de la caché de proveedor deseado en la
configuración de documento hibernate.cfg.xm:
<property name="hibernate.cache.provider_class">
org.hibernate.cache.EhCacheProvider
</property>
• Usted también puede decidir utilizar la caché de consultas
<property name="hibernate.cache.use_query_cache">true</property>
• Usted puede decidir para cada objeto y cada colección, si
debe ser en cache y en cual vía será mapeado el
correspondiente documento. Puede seleccionar una de las
estrategias:
o “read-write”
o “read-only”
o “transactional”
o “nonstrict-read-write”

Mapeando un documento, por ejemplo,


(Employee.hbm.xml), puede verse como sigue:

<hibernate−mapping>
<class name="com.sap.j2ee.examples.hibernate.Employee"
table="hib_employee">
<cache usage="read−write"/>
...

• Para el cacheo así como para el almacenamiento, usted


tendrá que activar el mecanismo de caché para cada query:

• Criteria criteria.setCachable(true); and/or


• Query query.setCachable(true);

Ambiente Distribuido
Con el fin de utilizar el almacenamiento en caché en entornos
distribuidos con varios nodos de servidor que debe tener la
coherencia de las caches en consideración. Dado que todos los
nodos de servidor se ejecuta en una máquina virtual de Java,
cada nodo servidor tiene su propio caché de Segundo Nivel, que
tiene que ser sincronizados a través de la agrupación, ya sea
por repetición o por invalidación. Porque el Open SQL Layer no
se puede utilizar para este fin, se puede integrar una
aplicación Open Source Cache. Se pueden utilizar dos proveedores
de cache, JBoss Cache y EHCache, se basan en la multidifusión en
la red para buscar y unirse a un grupo de replicación para el
intercambio o invalidación de mensajes.

Una solución para estos entornos es el uso del JBoss Cache, El


cual es un servidor independiente del componente de soporte
sincrono y asincrono de almacenamiento de cache. En general, el
despliegue de las librerías necesarias así como la configuración
en el documento xml obteniendo JBoss Cache corriendo dentro de
SAP NWAS.

Aunque no se menciona en la documentación de referencia


Hibernate Sin embargo, desde EHCache 1.2 es posible configurar
EHCache agrupado como un caché. Si bien la configuración de la
caché de JBoss es relativamente complejo, EHCache ofrece mucho
menos atributos para configurar en su configuración ehcache.xml
documento, que tiene que residir en el classpath de la
aplicación.

En general, para el uso en un entorno distribuido, tendrá que


seguir los pasos explicados antes en la configuración del
servidor único.

Además, usted tiene que configurar el archivo ehcache.xml, que


puede verse como el siguiente (sólo extracto, documento completo
en el Apéndice de este documento)

<ehcache>
<diskStore path="java.io.tmpdir"/>

<!-- Enable automatic peer discovery using multicasting -->


<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=automatic, multicastGroupAddress=230.0.0.1,
multicastGroupPort=4446"/>

<cacheManagerPeerListenerFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
properties="port=40001, socketTimeoutMillis=2000"/>

<!-- Sample Setting for distributed caching of Employee objects


- has to be done for every object/collection for distributed caching -->
<cache name="com.sap.j2ee.examples.hibernate.Employee"
maxElementsInMemory="10"
eternal="false"
timeToIdleSeconds="100"
timeToLiveSeconds="100"
overflowToDisk="false">
<cacheEventListenerFactory
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"/>
</cache>
...
</ehcache>

Los dos primeros son los atributos necesarios para que el "
Automatic Peer Discovery " EHCache proporcione. Como ya se ha
mencionado la red multidifusión se utiliza para este fin.
Además, usted tiene que definir los objetos y colecciones que se
almacena en caché en un entorno distribuido. Por favor refiérase
a la muestra EHCache Configuración y descargar el documento
ehcache.xml muestra en el paquete de EHCache más posibilidades
de configuración, tales como para definir el uso sincrónica de /
replicación asíncrona o invalidación.
(http://ehcache.sourceforge.net/documentation/configuration.html).

Por favor, si no a utilizar la misma dirección de multidifusión


si su sistema lanscape se compone de un desarrollo, prueba y
sistema productivo en la misma red. De lo contrario esto podría
conducir a la caché de sincronización a través de todo tipo de
sistemas. Por lo tanto, usted debe cambiar la dirección de
multidifusión cuando el transporte de su solicitud a través del
sistema de landscape.

Rastreando SQL
Hibernate usa mensajes internos con log4j para registrar los
logs. El SAP NWAS es posible que transmita esta información y
depurar los mensajes del log del servidor de aplicaciones. Esto
también le permite rastrear los informes que SQL Hibernate
genera y lo envía a la BDs. Por lo tanto, usted será capaz de
detectar con declaraciones el mal desempeño en el ámbito de la
optimización de los procesos de ejecución.

Para poder utilizar la funcionalidad de rastreo de SQL sobre SAP


para su NWAS Hibernate sólo dos aplicaciones de las medidas que
sean necesarias:

• Agregar el archivo JAVA log4j (log4j-1.2.13.jar) a la


librería del proyecto que ya se a mencionado y desplegarlo
dentro de SAP NWAS (como ya se ha definido)

• Agrega una configuración en el documento nombrado


log4j.propertie en el classpath de tu aplicación.

• La configuración log4j.properties documento puede tener


esto:

### direct log messages to stdout ###


log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### set log levels - for more verbose logging change 'info' to 'debug' ###

log4j.rootLogger=debug, stdout, file


log4j.logger.org.hibernate=info

### log just the SQL ###


log4j.logger.org.hibernate.SQL=debug

### log JDBC bind parameters ###


log4j.logger.org.hibernate.type=info

### log HQL parse trees ###


#log4j.logger.org.hibernate.hql=info
### log cache activity ###
log4j.logger.org.hibernate.cache=info
### log JDBC resource acquisition ###
log4j.logger.org.hibernate.jdbc=info

### enable the following line if you want to track down connection ###
### leakages when using DriverManagerConnectionProvider ###
#log4j.logger.org.hibernate.connection.DriverManagerConnectionProvider=trace

log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=c:/hibernate.log
log4j.appender.file.MaxFileSize=100KB

# Keep one backup file


log4j.appender.file.MaxBackupIndex=1
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%p %t %c - %m%n

Tu puedes accesar a las herramientas SAP SQL Trance visita la


interface http:// <nombreDeServidor>: <puerto> -> Administrador
de SAP NetWeaver. Aquí usted puede capturar sentencias SQL
generado y enviado por Hibernate durante el uso de su aplicación
y vigilar después.

Por favor considere cambiar el nivel de los mensajes Log4J


cuando capta a través de su aplicación en un sistema productivo.
Se puede tomar más tiempo para Log4J a escribir todos los
mensajes de depuración de Hibernate para la persistencia de
ejecutar las operaciones. Por lo tanto, se recomienda a todos
los mensaje de cambio a niveles INFO en un sistema productivo.

Usando Hibernate
La última sección abarca algunos aspectos relacionados con el
desarrollo de capas de aplicaciones J2EE con Hibernate en
general.

Se trata de las mejores prácticas para un uso Singleton EJB


dentro de un proyecto que proporciona la funcionalidad de la
configuración de Hibernate, la construcción de un SessionFactory
y pasar un período de sesiones. Esto se puede hacer con la
siguiente clase

package com.sap.j2ee.examples.hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
/**
* This class executes the initial operations to build a Configuration and the *
SessionFactory. Consumers are able to obtain new Session-Objects for each user.
*/
public class HibernateSessionFactory {
private static SessionFactory sessionFactory;
static {
try {
Configuration cfg = new Configuration();
sessionFactory =
cfg.configure("hibernate.cfg.xml").buildSessionFactory();
} catch (Throwable ex) {
System.err.println(
nal SessionFactory creation failed." + ex.getMessage());
"Iiti throw new ExceptionInInitializerError(ex);
}
}
public static Session openSession() throws HibernateException {
Session session = null;
try {
session = sessionFactory.openSession();
} catch (HibernateException e) {
System.err.println(
"Session creation failed." + e.getMessage());
e.printStackTrace();
} return session;
}
public static void closeSession(Session session) {
try {
if (session != null) {
session.close();
}
} catch (HibernateException e) {
System.err.println(
"Initial SessionFactory creation failed." + e.getMessage());
e.printStackTrace();
}
}
}

Dentro de los métodos ejbCreate() y setSessionContext() de un


EJB no se permite establecer conexiones con bases de datos. Esto
está explícitamente prohibido por la especificación J2EE y da
lugar a una excepción, lo que indica un conflicto Ressource.

Por lo tanto, no está autorizado a abrir un período de sesiones


Hibernate en estos métodos. Esto sólo tiene influencia sobre la
aplicación de un procedimiento Session-per-conversation, cuando
un período de sesiones debe estar a disposición de cada método
en el EJB. Una solución puede ser un método adicional llamado
directamente después de la creación de un EJB en la Web de nivel
- por otra parte, este tiene un impacto sobre el modelo de
negocio al añadir un método de inicialización de negocios.

Como también se aplicará en la aplicación de ejemplo asociado


con este tutorial, también puede aplicar la Session-per-request
procedure. Esto significa abrir y cerrar una sesión de Hibernate
en todos los métodos del negocio en un EJB. Cuando se utiliza
este procedimiento que es más fácil de aplicar, usted debe ser
consciente de algunas cuestiones relacionadas con la "Lazy
Initialization" característica que ofrece Hibernate. Esto tiene
un enorme impacto en arquitecturas en capas:

Cuando un objeto se recupera de la base datos, no todos los


objetos asociados (objeto gráfico) se leen al mismo tiempo la
base de datos, por ejemplo, cuando la recuperación de un
"Employee" de objetos, sus asociados "Department"-objeto no es
leer uno a la vez. En lugar de ello, por defecto en vigor a
partir de Hibernate en la versión 3, estos objetos se leen en el
momento en que se utilizan, respectivamente, acceder a ella. Con
este fin, la reunión de Hibernate ha de ser abierto.

Usando el procedimiento session-per-request, esto lleva a la


cuestión que, en una capa de la aplicación objetos asociados se
puede acceder (inicializar y leer de la base de datos) en el
nivel Web, por ejemplo, para la impresión de una tabla en un JSP
con todos los "empleados" de datos -, pero en este momento la
session ya está cerrado por el EJB después de la recuperación
del objeto "main" y, por tanto, conduce a una
LazyInitializationException.

Hay tres posibles soluciones para este problema:

La primera solución mantiene esta característica funcionamiento


que mejora el rendimiento significativamente, ya que sólo
acceder a los objetos en realidad se leen. Hibernate proporciona
el concepto "thread-local session", que un solo período de
sesiones se asocia con toda la petición de todos los niveles, y
no se cierra antes de la tramitación de la solicitud en su
conjunto (que se describe en "Hibernate en acción" por Gavin
King, página 300). Esto implica para una simple evaluación de
una solicitud mucho trabajo por ejecutar, servlet o filtros
interceptores se deben utilizar en este contexto, también.

a) En la segunda solución a menudo mencionada para hibernate


en general, lazy initialization es desabilitada mediante el
marcado de cada asociación con una "<lazy=false>" tag.
Tenga en cuenta que esto no siempre realmente desactiva la
función de inicialización lazy.

b) En la tercera solución se puede utilizar una solución


rápida para las pequeñas aplicaciones en el nivel EJB.
Después de la recuperación del objeto es posible
inicializar explícitamente la asociación mediante el uso
del API Hibernate, por ejemplo, en el ejemplo Empleado:
1 Hibernate.initialize(employee.getDepartment());
c) Esto obliga a Hibernate para cargar el "departamento" de
los datos "empleado" a la vez. El uso de esta declaración,
el "empleado" el objeto puede ser transmitido a la web de
nivel y el período de sesiones se puede cerrar a la vez al
final del método.

Integración de Hibernate Paso a Paso

1. Integrar la librería en el IDE y desplegarla. Consulte la


sección "Librerías del Framework de Hibernate " en el
capítulo anterior de la lista de los JARs. Puedes integrar
la libreria de la edicion al archivo server/provider de la
libreriy en su proyecto de NetWeaver Developer Studio.

o Abre una nueva librería en tu proyecto en al Developer


Studio.

o Dele a su libreria un nombre logico, por ejemplo


“Hibernate3_Library”.

o Desplegar la librería.

2. Desplegar la base de datos con un controlador apropiado,


crear su propio DataSource y desplegarlo. Esto se puede hacer a
través del Visual Administrator.

o Obtener un controlador JDBC para el sistema de base de


datos que desea utilizar, por ejemplo classes12.jar en el
caso de Oracle.
o Despliega el driver JDBC usando el servicio del JDBC
Connector en el Visual Administrator.

o Crea tu propio DataSource para este controlador JDBC


utilizando el Conector de servicio en el Visual
Administrator y despliégalo, también.

3. Crear tu propia aplicación de Hibernate.

o Consulte el apéndice para una muestra de codificación de la


aplicación del singleton de muestra y de la configuración
de Hibernate SessionFactory con la clase
HibernateSessionFactory.java.

o Agregué la clase SAPWebASTransactionManagerLookup.java para tu


proyecto EJB con el fin de integrarla transaccionalidad de
Hibrenate con el JTA Service de SAP NWAS.

o Ponga el archivo de configuración (s) (hibernate.properties


y / o hibernate.cfg.xml) en el classpath de su proyecto o
proyecto EJB Java.

4. Establezca una referencia desde su aplicación a las


librerías desplegadas. Esta es la edición realizada por el
proveedor específico descriptor de despliegue de
aplicaciones J2EE-engine.xml archivo del Enterprise Archive
(que residen junto con application.xml).

También proporcionamos una muestra Hibernate solicitud de


descarga gratuita. La aplicación está diseñada de acuerdo con el
patrón MVC y lleva a cabo la reunión Fachada patrón J2EE. El
modelo es aplicado plenamente con Hibernate utilizando como
functionalites primaria y la generación de Hibernate Query
Language. El paquete descargable contiene NetWeaver Developer
Studio de proyectos para la aplicación de ejemplo, que usted
puede importar en su propio IDE y, por tanto, fácil instalar y
ejecutar.

https://www.sdn.sap.com/irj/sdn/softwaredownload?download=/irj/servlet/prt/port
al/prtroot/com.sap.km.cm.docs/business_packages/a1-8-
4/HibernateExampleEHCache.zip

You might also like