1
votes

I have a persistence.xml where i need to connect to 5 different databases, so I have defined 5 different persistence units. My current persistence.xml looks as shown below

<?xml version="1.0" encoding="UTF-8" ?>
<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_2_0.xsd"
version="2.0" xmlns="http://java.sun.com/xml/ns/persistence">
<persistence-unit name="ec2Production" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
    <properties>
        <property name="hibernate.connection.provider_class" value="org.hibernate.connection.C3P0ConnectionProvider" />
        <property name="hibernate.show_sql" value="false" />
        <property name="hibernate.format_sql" value="false" />

        <property name="hibernate.connection.driver_class"  value="com.mysql.jdbc.Driver" />
        <property name="hibernate.connection.url" value="jdbc:mysql://xxxxx:3306/xxxxx?autoReconnect=true" />
        <property name="hibernate.connection.username" value="xxxxxx" />
        <property name="hibernate.connection.password" value="xxxxx" />

        <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
        <property name="hibernate.c3p0.acquire_increment" value="1"/>
        <property name="hibernate.c3p0.max_size" value="15"/>
        <!-- it must be set to LESS than the wait_timout setting for the mysql server (this setting defaults to 28800 secs (8 hours)) -->
        <property name="hibernate.c3p0.idle_test_period" value="28680" />
        <property name="hibernate.c3p0.preferredTestQuery" value="select 1;" />
        <property name="hibernate.c3p0.timeout" value="60000"/>
        <property name="hibernate.connection.zeroDateTimeBehavior" value="convertToNull"/>
        <property name="hibernate.c3p0.debugUnreturnedConnectionStackTraces " value="true"/>
        <property name="debugUnreturnedConnectionStackTraces " value="true"/>
        <property name="hibernate.cache.use_second_level_cache" value="true" />
        <property name="hibernate.cache.use_query_cache" value="true" />
        <property name="hibernate.cache.region.factory_class" value="com.mc.hibernate.memcached.MemcachedRegionFactory" />
        <property name="hibernate.memcached.operationTimeout" value = "40000"/>
        <property name="hibernate.memcached.connectionFactory" value = "KetamaConnectionFactory"/>
        <property name="hibernate.memcached.hashAlgorithm" value = "HashAlgorithm.FNV1_64_HASH"/>
        <property name="hibernate.memcached.servers" value = "xxxxxxxxxx:11211"/>

        <property name="hibernate.cache.region_prefix" value=""/>
    </properties>
</persistence-unit>

<persistence-unit name="ec2Marketing" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
    <properties>
        <property name="hibernate.connection.provider_class" value="org.hibernate.connection.C3P0ConnectionProvider" />
        <property name="hibernate.show_sql" value="false" />
        <property name="hibernate.format_sql" value="false" />

        <property name="hibernate.connection.driver_class"  value="com.mysql.jdbc.Driver" />
        <property name="hibernate.connection.url" value="jdbc:mysql://xxxxxx:3306/xxxxxx?autoReconnect=true" />
        <property name="hibernate.connection.username" value="xxxxx" />
        <property name="hibernate.connection.password" value="xxxxxxx" />

        <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
        <property name="hibernate.c3p0.acquire_increment" value="1"/>
        <property name="hibernate.c3p0.max_size" value="40"/>
        <property name="hibernate.c3p0.idle_test_period" value="28680" />
        <property name="hibernate.c3p0.preferredTestQuery" value="select 1;" />
        <property name="hibernate.c3p0.timeout" value="60000"/>
        <property name="hibernate.connection.zeroDateTimeBehavior" value="convertToNull"/>
        <property name="hibernate.c3p0.debugUnreturnedConnectionStackTraces " value="true"/>
        <property name="debugUnreturnedConnectionStackTraces " value="true"/>
        <property name="hibernate.cache.use_second_level_cache" value="true" />
        <property name="hibernate.cache.use_query_cache" value="true" />
        <property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory" />
        <property name="hibernate.cache.region.factory_class" value="com.mc.hibernate.memcached.MemcachedRegionFactory" />
        <property name="hibernate.memcached.operationTimeout" value = "40000"/>
        <property name="hibernate.memcached.connectionFactory" value = "KetamaConnectionFactory"/>
        <property name="hibernate.memcached.hashAlgorithm" value = "HashAlgorithm.FNV1_64_HASH"/>
        <property name="hibernate.memcached.servers" value = "xxxxxx:11211"/>

        <property name="hibernate.cache.region_prefix" value=""/>
    </properties>
</persistence-unit>

Everything works fine, except that when i start the server, it tries to connect to all the persistence unit and hence the server startup becomes pretty slow. In most of my cases, i rarely need to connect to all the persistence units.

I want to make my server startup fast, by skipping the validations for each persistence unit.

I am using hibernate4, with tomee 1.7.4 as server.

Following is the snippet of log generated on tomee server

2016-05-19 06:11:31 http-bio-8080-exec-2 INFO C3P0Registry - Initializing c3p0-0.9.2.1 [built 20-March-2013 10:47:27 +0000; debug? true; trace: 10] 2016-05-19 06:11:31 http-bio-8080-exec-2 INFO AbstractPoolBackedDataSource - Initializing c3p0 pool... com.mchange.v2.c3p0.PoolBackedDataSource@b7e616dd [ connectionPoolDataSource -> com.mchange.v2.c3p0.WrapperConnectionPoolDataSource@ecdf85aa [ acquireIncrement -> 1, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, debugUnreturnedConnectionStackTraces -> true, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> 1hge1369g1j2d3s55wlq0u|77b47a17, idleConnectionTestPeriod -> 28680, initialPoolSize -> 3, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 60000, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 40, maxStatements -> 0, maxStatementsPerConnection -> 0, minPoolSize -> 3, nestedDataSource -> com.mchange.v2.c3p0.DriverManagerDataSource@668bb235 [ description -> null, driverClass -> null, factoryClassLocation -> null, identityToken -> 1hge1369g1j2d3s55wlq0u|687e1712, jdbcUrl -> jdbc:mysql://localhost:3306/xxxxx?autoReconnect=true, properties -> {user=******, password=******, autocommit=true, zeroDateTimeBehavior=convertToNull, release_mode=auto} ], preferredTestQuery -> select 1;, propertyCycle -> 0, statementCacheNumDeferredCloseThreads -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false; userOverrides: {} ], dataSourceName -> null, factoryClassLocation -> null, identityToken -> 1hge1369g1j2d3s55wlq0u|65f14317, numHelperThreads -> 3 ]

This is the log that gets generated for each persistence unit, and later on when any connection happens for a persistence unit for the first time, i see this log again in my log file.

Thanks

1
set hibernate.hbm2ddl.auto property to noneArgb32
@Argb32 I added the property and made it none, still i am seeing connection being made at tomee startup in logs . Property added was <property name="hibernate.hbm2ddl.auto" value="none"/>vishva
I'd look into connection pool setings also.Argb32
@Argb32 can u be a bit more specific, like what property i need to add in persistence.xmlvishva
It's better to show application log. Then we'll see where the slowdown actually occurs.Argb32

1 Answers

0
votes

I think the main reasons your application starts slow is because the way it is written. I have plenty of apps that have 5-10 datasources and the TomEE start is just a few seconds.

The main problem is you're not letting the container manage any of your objects. The container is designed to do this efficiently, whereas Hibernate has limited scope into whats happening in the outside world. Here's a few starting points:

<persistence-unit transaction-type="RESOURCE_LOCAL"> Means you are manually managing your PU's lifecycle. I would highly advise against this. Instead, the application container is optimized to pool these objects efficiently. Switch to <persistence-unit transaction-type="JTA"> and let the container manage the lifecycle of your objects, that's what it is designed to do. Inject an instance of a persistance unit like so: @PersistenceContext private EntityManager em;

Second, you are defining your datasources and pools inside the application. I would highly recommend against this. Again, the point of an application container is to efficiently pool and manage the lifecycle of your objects. To fix this, define a datasource in tomee.xml sort of like this:

<Resource id="jdbc/moviesdb" type="DataSource">
  JdbcDriver=com.mysql.jdbc.Driver
  JdbcUrl=jdbc:mysql:localhost:3306/moviesdb
  UserName=sa
  Password=secret
  JtaManaged=true
  ValidationQuery=SELECT 1
  TestOnBorrow=true
</Resource>

Then remove all of these:

   <property name="hibernate.connection.provider_class" value="org.hibernate.connection.C3P0ConnectionProvider" />
        <property name="hibernate.show_sql" value="false" />
        <property name="hibernate.format_sql" value="false" />

        <property name="hibernate.connection.driver_class"  value="com.mysql.jdbc.Driver" />
        <property name="hibernate.connection.url" value="jdbc:mysql://xxxxx:3306/xxxxx?autoReconnect=true" />
        <property name="hibernate.connection.username" value="xxxxxx" />
        <property name="hibernate.connection.password" value="xxxxx" />

        <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
        <property name="hibernate.c3p0.acquire_increment" value="1"/>
        <property name="hibernate.c3p0.max_size" value="15"/>
        <!-- it must be set to LESS than the wait_timout setting for the mysql server (this setting defaults to 28800 secs (8 hours)) -->
        <property name="hibernate.c3p0.idle_test_period" value="28680" />
        <property name="hibernate.c3p0.preferredTestQuery" value="select 1;" />
        <property name="hibernate.c3p0.timeout" value="60000"/>
        <property name="hibernate.connection.zeroDateTimeBehavior" value="convertToNull"/>
        <property name="hibernate.c3p0.debugUnreturnedConnectionStackTraces " value="true"/>
        <property name="debugUnreturnedConnectionStackTraces " value="true"/>

And replace it with:

<jta-data-source>jdbc/moviesdb</jta-data-source>

Finally, if it's not completely necessary to use Hibernate, I would recommend switching to EclipseLink which has a significantly smaller footprint in memory, CPU, and performance.

Cheers, and good luck

References:

http://tomee.apache.org/containers-and-resources.html#ContainersandResources-Resources