Schlagwörter: Hibernate Kommentarverlauf ein-/ausschalten | Tastaturkürzel

  • Andreas Höhmann 13:48 am Wednesday, 14. March 2012 Permalink |
    Tags: ehcache, Hibernate, jmx   

    Enable JMX Management for Hibernate EhCache 

    Have a look at

    • net.sf.ehcache.hibernate.SingletonEhCacheRegionFactory.start(Settings, Properties)
    • net.sf.ehcache.hibernate.management.impl.ProviderMBeanRegistrationHelper.registerMBean(CacheManager, Properties)
    What we need is a system property „tc.active“ with value „true“
    🙂
     
  • Andreas Höhmann 10:38 am Thursday, 19. January 2012 Permalink |
    Tags: , Hibernate   

    Good to know this Hibernate Envers API changes 

    Today I tried to update the hibernate version for an internal customer project from 3.6.0.Final to 3.6.9.Final. In the project we are using Envers to track entity revisions. I already posted about that here.

    I noticed that some tests broken with the new version. These tests doing something like this: „create a bean, do changes X times, check available revisions and changed properties from rev A to B“.  In the new version I missed some changed properties.  I’m so happy that we have some tests for that aspect because without them I guess I had found these effects.

    I found  this entries in the Envers user forum:

    – Envers not auditing properties in super class
    – Envers modification in Hibernate 3.6.8 is causing problems

    Then I use the „try and fail“ principle to find the latest working version: ONLY 3.6.0.Final works 😀

    So there was an API change from 3.6.0.Final to 3.6.1.Final. Since 3.6.1.Final Envers doesn’t inspect parent class (es) per default to find out the audit able properties. But it’s easy to fix that:

    • put a @Audited to all the base classes
    • or use org.hibernate.envers.Audited.auditParents() (if you can’t change the base class)

    🙂

     
  • Andreas Höhmann 13:46 am Friday, 31. July 2009 Permalink |
    Tags: C3PO, Connection, , Hibernate, JPA, Pool, revision managment,   

    I use connection pooling to fix a hibernate problem 

    Yesterday i had a problem with hibernate envers and a sql-server database and the solution was to switch from a „non pooled“ to a „pooled“ datasource with JPA/hibernate/spring.

    The problem

    I got this wonderfull stacktrace:

    Caused by: org.hibernate.exception.JDBCConnectionException: Cannot open connection
     at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:97)
     at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
     at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:52)
     at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:449)
     at org.hibernate.jdbc.ConnectionManager.getConnection(ConnectionManager.java:167)
     at org.hibernate.jdbc.AbstractBatcher.prepareQueryStatement(AbstractBatcher.java:161)
     at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1573)
     at org.hibernate.loader.Loader.doQuery(Loader.java:696)
     at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:259)
     at org.hibernate.loader.Loader.doList(Loader.java:2228)
     at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2125)
     at org.hibernate.loader.Loader.list(Loader.java:2120)
     at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:401)
     at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:361)
     at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:196)
     at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1148)
     at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102)
     at org.hibernate.envers.entities.mapper.relation.lazy.initializor.AbstractCollectionInitializor.initialize(AbstractCollectionInitializor.java:62)
     at org.hibernate.envers.entities.mapper.relation.lazy.proxy.CollectionProxy.checkInit(CollectionProxy.java:47)
     at org.hibernate.envers.entities.mapper.relation.lazy.proxy.CollectionProxy.toString(CollectionProxy.java:118)
     at org.apache.commons.beanutils.converters.StringConverter.convert(StringConverter.java:57)
     at org.apache.commons.beanutils.ConvertUtilsBean.convert(ConvertUtilsBean.java:400)
     at org.apache.commons.beanutils.BeanUtilsBean.getNestedProperty(BeanUtilsBean.java:699)
     at org.apache.commons.beanutils.BeanUtilsBean.getProperty(BeanUtilsBean.java:723)
     at org.apache.commons.beanutils.BeanUtilsBean.describe(BeanUtilsBean.java:504)
     at org.apache.commons.beanutils.BeanUtils.describe(BeanUtils.java:145)
     at de.ahoehma.persistence.revision.BeanDiff.getAllProperties(BeanDiff.java:170)

    The background story

    We use envers for revision-management of persisted objects. Our application have a „changelog-view“ for change-statistics (which object changed from version A to version B, differences between these versions for each object etc.):

    changelog_table

    During the creation of the table data our code find out the changed objects (with a envers query). We use our RevisionsDaoImpl for that, i.e. the getRevisions method:

    
    @Repository
    @Transactional
    class RevisionsDaoImpl<T,KEY, REVINFO> {
    
     protected final Class<T> classOfT;
     protected EntityManager entityManager;
    
     public RevisionsDaoImpl(final Class<T> clazz) {
     super(clazz);
     }
    
     public List<Revision<T, REVINFO>> getRevisions(final int theRevisionFrom, final int theRevisionTo) {
     final AuditReader reader = ExtendedAuditReaderFactory.get(entityManager);
     AuditQuery query = reader.createQuery().forRevisionsOfEntity(classOfT, false, true);
     query = query.addOrder(AuditEntity.revisionNumber().asc());
     // all items newer or equal than theRevisionFrom
     query = query.add(AuditEntity.revisionNumber().ge(Integer.valueOf(theRevisionFrom)));
     // all items older or equal than theRevisionTo
     query = query.add(AuditEntity.revisionNumber().le(Integer.valueOf(theRevisionTo)));
     return fetchRevisions(query, reader);
     }
    
     protected List<Revision<T, REVINFO>> fetchRevisions(final AuditQuery query, final AuditReader reader) {
     try {
     final Object resultList = query.getResultList();
     final List<Object[]> queryResult = (List<Object[]>) resultList;
     final List<Revision<T, REVINFO>> result = new ArrayList<Revision<T, REVINFO>>(queryResult.size());
     for (final Object[] array : queryResult) {
     result.add(new RevisionImpl<T, REVINFO>((T) array[0], (REVINFO) array[1], (RevisionType) array[2]));
     }
     return result;
     } catch (final RevisionDoesNotExistException ex) {
     return null;
     } catch (final NoResultException ex) {
     return null;
     }
     }
     ...
    }
    
    

    In the datatable bean we are loading all revisions (from version A to version B) . Then we use org.apache.commons.beanutils.BeanUtils to get all properties from version A and B and then we compare these properties for each object. The result is the list of changed objects and all differences for each object (diffRevision(T versionA, T version B)):

    
    protected List<T> getChangeLog() {
     final List<T> result = new ArrayList<T>();
     final VersionedDao<T, Integer, RevisionInfo> dao = getRevisionsDao();
     // get all revisions from A to B for objects T
     final List<Revision<T, RevisionInfo>> revs = dao.getRevisions(fromRevision.intValue(), toRevision.intValue());
     // get A revision and B revision for each object T with revisions
     final Map<Integer, List<Revision<T, RevisionInfo>>> oldNewRevisions = dao.getOldNewRevisions(revs, fromRevision, toRevision);
     // build diff for each object
     for (final Revision rev : revs) {
     final T entity = rev.getEntity();
     final Revision<T, RevisionInfo> oldestRevision = oldNewRevisions.get(entity.getId()).get(0);
     final Revision<T, RevisionInfo> newestRevision = oldNewRevisions.get(entity.getId()).get(1);
     result.add(diffRevision(newestRevision, oldestRevision));
     }
    
    

    In the ui layer we are using rich:dataTable which have sortable columns. The above exception occured if a column-sort was triggered.

    Maybe inside hibernate or envers too many transactions or connections created and not fast enough released during the table data creation or the table rendering (lazy loaded properties may play a role in this game). Or the jdbc driver we are using is the bad guy (net.sourceforge.jtds:jtds:1.2).

    The solution

    Anyway! A workaround was to use a pooled datasource instead of a standard datasource. I found a list of pooling frameworks for hibernate here. The Hibernate  documentation contains some information too. I decide to try the 3CPO framework. Its very easy to add  a new dependency:

    
    <dependency>
     <groupId>org.hibernate</groupId>
     <artifactId>hibernate-c3p0</artifactId>
     <version>3.3.1.GA</version>
     <scope>runtime</scope>
     </dependency>
    
    

    And change the datasource:

    
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="${jpa.driver}" />
    <property name="url" value="${jpa.url}" />
    <property name="username" value="${jpa.username}" />
    <property name="password" value="${jpa.password}" />
    </bean>
    
    <bean id="pooledDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
    <property name="jdbcUrl" value="${jpa.url}" />
    <property name="user" value="${jpa.username}" />
    <property name="password" value="${jpa.password}" />
    <property name="initialPoolSize" value="1" />
    <property name="minPoolSize" value="1" />
    <property name="maxPoolSize" value="3" />
    <property name="idleConnectionTestPeriod" value="500" />
    <property name="acquireIncrement" value="1" />
    <property name="maxStatements" value="50" />
    <property name="numHelperThreads" value="1" />
    </bean>
    
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="loadTimeWeaver">
     <bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
     </property>
    <property name="dataSource" ref="pooledDataSource" />
    <property name="persistenceUnitName" value="sid-admin-web-persistence" />
    <property name="jpaVendorAdapter">
     <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
    <property name="showSql" value="false" />
    <property name="generateDdl" value="true" />
    <property name="databasePlatform" value="${jpa.hibernate.dialect}" />
     </bean>
     </property>
    </bean>
    
    
    <bean id=“dataSource“ class=“org.springframework.jdbc.datasource.DriverManagerDataSource“>
    <property name=“driverClassName“ value=“${jpa.driver}“ />
    <property name=“url“ value=“${jpa.url}“ />
    <property name=“username“ value=“${jpa.username}“ />
    <property name=“password“ value=“${jpa.password}“ />
    </bean>

    <bean id=“pooledDataSource“ class=“com.mchange.v2.c3p0.ComboPooledDataSource“ destroy-method=“close“>
    <description>
    Wir muessen eine „pooled data source“ benutzen weil im changelog massiv transaktionen/connections
    erzeugt werden, dies fuehrt in verbindung mit dem sql-server zu einem knappwerden der sockets und
    zu einem jdbc-error
    </description>
    <property name=“driverClass“ value=“${jpa.driver}“ />
    <property name=“jdbcUrl“ value=“${jpa.url}“ />
    <property name=“user“ value=“${jpa.username}“ />
    <property name=“password“ value=“${jpa.password}“ />
    <property name=“initialPoolSize“ value=“1″ />
    <property name=“minPoolSize“ value=“1″ />
    <property name=“maxPoolSize“ value=“3″ />
    <property name=“idleConnectionTestPeriod“ value=“500″ />
    <property name=“acquireIncrement“ value=“1″ />
    <property name=“maxStatements“ value=“50″ />
    <property name=“numHelperThreads“ value=“1″ />
    </bean>

    <bean id=“entityManagerFactory“ class=“org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean“>
    <property name=“loadTimeWeaver“>
    <bean class=“org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver“ />
    </property>
    <property name=“dataSource“ ref=“dataSource“ />
    <property name=“persistenceUnitName“ value=“sid-admin-web-persistence“ />
    <property name=“jpaVendorAdapter“>
    <bean class=“org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter“>
    <property name=“showSql“ value=“false“ />
    <property name=“generateDdl“ value=“true“ />
    <property name=“databasePlatform“ value=“${jpa.hibernate.dialect}“ />
    </bean>
    </property>
    </bean>

     
    • anshuiitk 18:45 am Donnerstag, 29. Dezember 2011 Permalink | Zum Antworten anmelden

      Hello .. I am trying to solve the same problem once more … I just stumbled upon your post .. I am trying to implement revision management for our entites using envers too …

      Can you tell me how did you generate object differences on a given object graph ?, Would it be possible to share some code docs to explain the way you implemented revision management ?. You can email me at himanshu _ kgp at gmail dot com

      • Andreas Höhmann 1:43 am Samstag, 31. Dezember 2011 Permalink | Zum Antworten anmelden

        Sorry I can’t give you any code examples … this was a commercial project for Siemens. I remember we wrote some utility methods to calculate the differences between to bean revisions but there was no „generic way“ for that. I guess Envers allows to access the changed properties per revision?!

    • bkiew 19:11 am Freitag, 20. Januar 2012 Permalink | Zum Antworten anmelden

      anshuiitk :
      Hello .. I am trying to solve the same problem once more … I just stumbled upon your post .. I am trying to implement revision management for our entites using envers too …
      Can you tell me how did you generate object differences on a given object graph ?, Would it be possible to share some code docs to explain the way you implemented revision management ?. You can email me at himanshu _ kgp at gmail dot com

      Using the AuditReader of Envers you can get the state of an object with given revision. Get the two states of the object (f.e. User) to compare. Then compare the properties using BeanUtils and reflection.

      Pseudo-Code / there are good examples in the web out there

      revisionA=AuditReader.getRevisionXXX(42, User.class);
      revisionB=AuditReader.getRevisionXXX(43, User.class);

      String valueA=org.apache.commons.beanutils.BeanUtils.getProperty(revisionA, "email")
      String valueB=org.apache.commons.beanutils.BeanUtils.getProperty(revisionB, "email")

      hasChanged=!valueA.equals(valueB);

      + special handling of deletes (when revisionB does not exist)
      + special handling of inserts (when revisionA does not exist)

      I know BeanUtils works with reflection and the iteration of all properties is slow (so it can be a performance issue), but you got the basics?

  • Andreas Höhmann 12:02 am Wednesday, 3. June 2009 Permalink |
    Tags: Hibernate, jdbc, logging, , , sql   

    Hibernate sql logging with values 

    As you might know already, Hibernate supports logging for sql-statements. Your Spring-configuration (e.g. spring-database.xml) must contain this:

    
    <bean id="entityManagerFactory"
     class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="persistenceUnitName" value="logging-test" />
    <property name="jpaVendorAdapter">
     <bean>
    <property name="showSql" value="true" />
    <property name="generateDdl" value="true" />
    <property name="databasePlatform" value="${jpa.hibernate.dialect}" />
     </bean>
     </property>
    <property name="jpaProperties" value="hibernate.dialect=${jpa.hibernate.dialect}" />
     </bean>
    
    

    With showSql=true hibernate will show you logmessages like this:

    Hibernate:
       delete
       from
          SoftwareCategory_SoftwareCategory
       where
          SoftwareCategory_id=?
    Hibernate:
       update
          SoftwareCategory
       set
          concurrentVersion=?,
          CATEGORY_NAME=?,
          PARENT_ID=?
       where
          id=?
          and concurrentVersion=?
    Hibernate:
       insert
       into
          SoftwareCategory_SoftwareCategory
          (SoftwareCategory_id, POSITION, children_id)
       values
          (?, ?, ?)

    To see the values and not the placeholders (?) you must define the loglevel trace for hibernate-types in the log4j.xml:

    
    <category name="org.hibernate.type">
    <priority value="trace" />
     </category>
    
    

    Then you will see logmessages like this:

    Hibernate:
       insert
       into
          SoftwareCategory_SoftwareCategory
          (SoftwareCategory_id, POSITION, children_id)
       values
          (?, ?, ?)
    NullableType:151 - binding '68' to parameter: 1
    NullableType:151 - binding '0' to parameter: 2
    NullableType:151 - binding '69' to parameter: 3

    Not bad but there is a better way for this 🙂

    Yesterday i found the project JDBCLogger.  They have implemented a „JDBC-Proxy“ with logging support. Its Maven-ready and comes with a easy Spring-integration. So how can we use this cool stuff … it is so easy:

    1. Define the JDBCLogger dependencies in the pom.xml:

    
    <dependencies>
    <dependency>
     <groupId>net.sourceforge.jdbclogger</groupId>
     <artifactId>jdbclogger-core</artifactId>
     <version>0.7-SNAPSHOT</version>
     </dependency>
     <dependency>
     <groupId>net.sourceforge.jdbclogger</groupId>
     <artifactId>jdbclogger-spring</artifactId>
     <version>0.7-SNAPSHOT</version>
     </dependency>
     </dependencies>
    
    

    The informations from the installation-guide on the project-site is a little too old, so the maven-repository http://jdbclogger.sourceforge.net/m2-repo/ doesn’t exists. No problem we can build jdbclogger-core and jdbclogger-spring by ourself (read more). The simplest way to build the two artifacts is:

    • checkout from  svn
    • edit master-pom, comment out all modules, leave only core and spring active
    • run mvn clean install from root-dir

    2. Change your Spring-configuration, switch showSql off and add the following bean:

    
    <bean id="jdbcLoggerConfig"
     class="net.sourceforge.jdbclogger.spring.JdbcLoggerBeanPostProcessor">
    <property name="enabled" value="true" />
    <property name="dataSourceConfigurations">
    	<list>
     <bean class="net.sourceforge.jdbclogger.spring.JdbcLoggerDataSourceConfiguration">
    <property name="dataSourceBeanName" value="dataSource" />
    <property name="driverClassNamePropertyName" value="driverClassName" />
     </bean>
     </list>
     </property>
    <property name="targetDriverClassNames">
    	<list>
     <value>${jpa.driver}</value>
     </list>
     </property>
     </bean>
    
    

    3.  Activate logging in the log4j.xml:

    
    <category name="net.sourceforge.jdbclogger">
    <priority value="debug" />
     </category>
    <category name="net.sourceforge.jdbclogger.spring">
    <priority value="error" />
     </category>
    
    

    Thats it 🙂 Now you will see logmessages like this:

    JdbcLoggerDriver:65 – Wrapper ’net.sourceforge.jdbclogger.JdbcLoggerDriver‘ successfully registed for driver ‚com.mysql.jdbc.Driver‘
    PreparedStatementWrapper:156 – Prepared Statement : select softwareca0_.id as id0_, softwareca0_.concurrentVersion as concurre2_0_, softwareca0_.CATEGORY_NAME as CATEGORY3_0_, softwareca0_.PARENT_ID as PARENT4_0_ from SoftwareCategory softwareca0_ where softwareca0_.PARENT_ID is null
    StatementWrapper:45 – Statement : delete from softwarecategory_softwareobject
    PreparedStatementWrapper:156 – Prepared Statement : insert into SoftwareCategory_SoftwareCategory (SoftwareCategory_id, POSITION, children_id) values (’92‘, ‚3‘, ’96‘)

     
    • Amit Telang 19:34 am Dienstag, 6. Mai 2014 Permalink | Zum Antworten anmelden

      Hi, I tried everything like setting type to TRACE and everything found in other sites, but still I am unable to see parameter values. I am using hibernate 3.6.

c
Neuen Beitrag erstellen
j
nächster Beitrag/nächster Kommentar
k
vorheriger Beitrag/vorheriger Kommentar
r
Antworten
e
Bearbeiten
o
zeige/verstecke Kommentare
t
Zum Anfang gehen
l
zum Login
h
Zeige/Verberge Hilfe
Shift + ESC
Abbrechen