Showing posts with label Hibernate. Show all posts
Showing posts with label Hibernate. Show all posts

Wednesday, April 27, 2016

Spring Transaction Isolation Level

Spring Transaction Isolation Level

The standard levels are 2,3,4,5, the higher level, the poorer concurrency/effi
  1. ISOLATION_DEFAULT (Spring)
    This is a PlatformTransactionManager Default isolation level, using Default Database transaction level. The other 4 are correspond to JDBC isolation level
  2. ISOLATION_READ_UNCOMMITTED
    Lowest isolation level. Allow other transaction to see the data from this transaction. This level can cause dirty read, non-repeatable read, and illusion read
  3. ISOLATION_READ_COMMITTED (normally used)
    Promise other transaction can read data until this transaction committed.
  4. ISOLATION_REPEATABLE_READ
    Prevent dirty read, non-repeatable read. But can illusion read.
  5. ISOLATION_SERIALIZABLE
    This is most expensive level, but most reliable. It promise Sequence. Prevent dirty read, non-repeatable read, and illusion read

Transaction Definition

Transaction Definition

  1. PROPAGATION_REQUIRED (normally used)
    If transaction existed, use it, otherwise open a new transaction
  2. PROPAGATION_SUPPORTS
    If transaction existed, use it, otherwise run as non-transaction
  3. PROPAGATION_MANDATORY
    If transaction existed, use it, otherwise throw Exception
  4. PROPAGATION_REQUIRES_NEW
    Always open a new transaction, if transaction existed, hang up the existed transaction
  5. PROPAGATION_NOT_SUPPORTED
    Always run without transaction, if transaction existed, hang up the existed transaction
  6. PROPAGATION_NEVER
    Always run without transaction, if transaction existed, throw Exception
  7. PROPAGATION_NESTED (in Spring)
    If transaction existed, run nested transaction inside the existed transaction.
    If no transaction existed, run as PROPAGATION_REQUIRED

PropagationT1 NoneT1 Existed
REQUIREDT2=>newT1
SUPPORTST2 NoneT1
MANDATORYT2 ExceptionT1
REQUIRES_NEWT2=>newT2=>new
NOT_SUPPORTEDNoneHang up T1
NEVERNoneT2 Exception
NESTEDAs REQUIREDNested

Saturday, April 9, 2016

Spring 3 Hibernate 4 Struts 1.3 Maven

The example project is here:
https://github.com/ylu999/myssh6


1. New Maven Project
groupId: com.gvace
Archetype: org.apache.maven.archetypes
packaging:war

I faced some memory size issue when selecting Archetype, so I increased it in eclipse.ini.

  • -Xms512m
  • -Xmx1024m

2. Project Structure

3. pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>com.gvace</groupId>
 <artifactId>myssh6</artifactId>
 <packaging>war</packaging>
 <version>0.0.1-SNAPSHOT</version>
 <name>myssh6 Maven Webapp</name>
 <url>http://maven.apache.org</url>
 <properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <project.build.mainClass>com.gvace.main</project.build.mainClass>
  <java.version>1.7</java.version>
  <spring.version>3.2.16.RELEASE</spring.version>
  <hibernate.version>4.1.7.Final</hibernate.version>
 </properties>
 <dependencies>
  <dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>servlet-api</artifactId>
   <version>2.5</version>
   <scope>provided</scope>
  </dependency>
  <dependency>
   <groupId>javax.annotation</groupId>
   <artifactId>javax.annotation-api</artifactId>
   <version>1.2</version>
  </dependency>
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-context</artifactId>
   <version>${spring.version}</version>
  </dependency>

  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-orm</artifactId>
   <version>${spring.version}</version>
  </dependency>

  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-aop</artifactId>
   <version>${spring.version}</version>
  </dependency>
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-context-support</artifactId>
   <version>${spring.version}</version>
  </dependency>
  <!-- Spring Struts -->
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-struts</artifactId>
   <version>${spring.version}</version>
  </dependency>

  <!--@Transactional -->
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-tx</artifactId>
   <version>${spring.version}</version>
  </dependency>
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-web</artifactId>
   <version>${spring.version}</version>
  </dependency>

  <dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-entitymanager</artifactId>
   <version>${hibernate.version}</version>
  </dependency>
  <!-- <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-search</artifactId> 
   <version>4.1.1.Final</version> </dependency> -->
  <dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-ehcache</artifactId>
   <version>${hibernate.version}</version>
  </dependency>
  <dependency>
   <groupId>net.sf.ehcache</groupId>
   <artifactId>ehcache-core</artifactId>
   <version>2.6.5</version>
  </dependency>
  <!-- connection pooling with c3p0 -->
  <dependency>
   <groupId>c3p0</groupId>
   <artifactId>c3p0</artifactId>
   <version>0.9.1.2</version>
  </dependency>

  <dependency>
   <groupId>log4j</groupId>
   <artifactId>log4j</artifactId>
   <version>1.2.17</version>
  </dependency>

  <dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
   <version>5.1.38</version>
  </dependency>

  <dependency>
   <groupId>junit</groupId>
   <artifactId>junit</artifactId>
   <version>4.12</version>
   <scope>test</scope>
  </dependency>

  <dependency>
   <groupId>cglib</groupId>
   <artifactId>cglib</artifactId>
   <version>3.1</version>
  </dependency>

  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-test</artifactId>
   <version>${spring.version}</version>
   <scope>test</scope>
  </dependency>
  <dependency>
   <groupId>org.slf4j</groupId>
   <artifactId>slf4j-api</artifactId>
   <version>1.7.20</version>
  </dependency>
  <dependency>
   <groupId>org.slf4j</groupId>
   <artifactId>slf4j-simple</artifactId>
   <version>1.7.20</version>
  </dependency>

  <!-- Struts 1.3 -->
  <dependency>
   <groupId>antlr</groupId>
   <artifactId>antlr</artifactId>
   <version>2.7.7</version>
  </dependency>
  <dependency>
   <groupId>bsf</groupId>
   <artifactId>bsf</artifactId>
   <version>2.3.0</version>
  </dependency>
  <dependency>
   <groupId>commons-beanutils</groupId>
   <artifactId>commons-beanutils</artifactId>
   <version>1.9.2</version>
  </dependency>
  <dependency>
   <groupId>commons-chain</groupId>
   <artifactId>commons-chain</artifactId>
   <version>1.2</version>
  </dependency>
  <dependency>
   <groupId>commons-digester</groupId>
   <artifactId>commons-digester</artifactId>
   <version>1.8.1</version>
  </dependency>
  <dependency>
   <groupId>commons-fileupload</groupId>
   <artifactId>commons-fileupload</artifactId>
   <version>1.1.1</version>
  </dependency>
  <dependency>
   <groupId>commons-io</groupId>
   <artifactId>commons-io</artifactId>
   <version>1.1</version>
  </dependency>
  <dependency>
   <groupId>commons-logging</groupId>
   <artifactId>commons-logging</artifactId>
   <version>1.0.4</version>
  </dependency>
  <dependency>
   <groupId>commons-validator</groupId>
   <artifactId>commons-validator</artifactId>
   <version>1.3.1</version>
  </dependency>
  <dependency>
   <groupId>commons-dbcp</groupId>
   <artifactId>commons-dbcp</artifactId>
   <version>1.2.2</version>
  </dependency>

  <dependency>
   <groupId>oro</groupId>
   <artifactId>oro</artifactId>
   <version>2.0.8</version>
  </dependency>
  <dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>jstl</artifactId>
   <version>1.2</version>
  </dependency>
  <dependency>
   <groupId>org.apache.taglibs</groupId>
   <artifactId>taglibs-standard-impl</artifactId>
   <version>1.2.5</version>
  </dependency>
  <dependency>
   <groupId>org.apache.struts</groupId>
   <artifactId>struts-core</artifactId>
   <version>1.3.10</version>
  </dependency>
  <dependency>
   <groupId>org.apache.struts</groupId>
   <artifactId>struts-el</artifactId>
   <version>1.3.10</version>
  </dependency>
  <dependency>
   <groupId>org.apache.struts</groupId>
   <artifactId>struts-extras</artifactId>
   <version>1.3.10</version>
  </dependency>
  <dependency>
   <groupId>org.apache.struts</groupId>
   <artifactId>struts-faces</artifactId>
   <version>1.3.10</version>
  </dependency>
  <dependency>
   <groupId>org.apache.struts</groupId>
   <artifactId>struts-mailreader-dao</artifactId>
   <version>1.3.10</version>
  </dependency>
  <dependency>
   <groupId>org.apache.struts</groupId>
   <artifactId>struts-scripting</artifactId>
   <version>1.3.10</version>
  </dependency>
  <dependency>
   <groupId>org.apache.struts</groupId>
   <artifactId>struts-taglib</artifactId>
   <version>1.3.10</version>
  </dependency>
  <dependency>
   <groupId>org.apache.struts</groupId>
   <artifactId>struts-tiles</artifactId>
   <version>1.3.10</version>
  </dependency>
  <!-- -->
 </dependencies>
 <build>
  <finalName>myssh6</finalName>
 </build>
</project>





4. web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
 id="WebApp_ID" version="3.0">
 <display-name>myssh6</display-name>
 <welcome-file-list>
  <welcome-file>index.html</welcome-file>
  <welcome-file>index.htm</welcome-file>
  <welcome-file>index.jsp</welcome-file>
  <welcome-file>default.html</welcome-file>
  <welcome-file>default.htm</welcome-file>
  <welcome-file>default.jsp</welcome-file>
 </welcome-file-list>
 
 <!-- Spring config
  classpath: starts from src folder
  -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <!-- <param-value>/WEB-INF/applicationContext.xml</param-value> -->
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
    <!-- Initialize Spring Container -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    
    <!-- Struts -->
 <servlet>
  <servlet-name>struts</servlet-name>
  <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
  <load-on-startup>2</load-on-startup>
 </servlet>
 <servlet-mapping>
  <servlet-name>struts</servlet-name>
  <url-pattern>*.do</url-pattern>
 </servlet-mapping>
 <!-- Encoding with spring filter -->
 <filter>
  <filter-name>encoding</filter-name>
  <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
  <init-param>
   <param-name>encoding</param-name>
   <param-value>UTF-8</param-value>
  </init-param>
 </filter>
 <filter-mapping>
  <filter-name>encoding</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>
</web-app>


5. applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
 xmlns:tx="http://www.springframework.org/schema/tx"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"
 >
 <!-- Enable Annotation -->
 <context:annotation-config/>
 <!-- Data Source -->
 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
  <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/myssh"/>
  <property name="username" value="root"/>
    <property name="password" value="root"/>
    <property name="initialSize" value="3"/>
    <property name="maxActive" value="500"/>
    <property name="maxIdle" value="2"/>
    <property name="minIdle" value="1"/>
 </bean>
 
 <!--Spring Cache--> 
 <!-- 
    <bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
        <property name="caches">
            <set>
                <bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" />
            </set>
        </property>
    </bean>
    -->
 <!-- Local Session Factory Bean -->
 <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
  <property name="dataSource" ref="dataSource"/>
  <property name="mappingResources">
   <list>
    <value>hbm/Employee.hbm.xml</value>
    <value>hbm/Department.hbm.xml</value>
   </list>
  </property>
  <property name="hibernateProperties">
   <value>
    hibernate.hbm2ddl.auto=update
    
    hibernate.dialect=org.hibernate.dialect.MySQLDialect
    hibernate.show_sql=true
    hibernate.format_sql=true
    
    hibernate.connection.CharSet=utf8
    hibernate.connection.characterEncoding=utf8
    hibernate.connection.useUnicode=true
    
    hibernate.generate_statistics=true
    hibernate.cache.use_structured_entries=true
    hibernate.cache.use_second_level_cache=true
    hibernate.cache.use_query_cache=true   
    hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory
    net.sf.ehcache.configurationResourceName=/ehcache.xml
   </value>
  </property>
 </bean>
 <!-- Spring Transaction Manager -->
 <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
  <property name="sessionFactory" ref="sessionFactory"></property>
 </bean>
 <!-- Start Transaction Annotation -->
 <tx:annotation-driven transaction-manager="transactionManager"/>
 
 <!-- Service Beans -->
 <bean id="employeeService" class="com.gvace.service.impl.EmployeeService">
  <!-- try annotation @Resource instead of here -->
  <!-- <property name="sessionFactory" ref="sessionFactory"/> -->
 </bean>
 <!-- Action
  set name with the action->path configured in struts-config.xml
  then you can delete the type property configured in struts-config.xml for this Action
  because we already set the class here
 -->
 <bean name="/login" class="com.gvace.web.action.LoginAction">
  <!-- add dependency of employeeServiceInterface -->
  <!-- try annotation @Resource instead of here -->
  <!-- <property name="employeeService" ref="employeeService"></property> -->
 </bean>
</beans>









6. struts-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
       "http://struts.apache.org/dtds/struts-config_1_3.dtd">
<struts-config>
 <form-beans>
  <form-bean name="loginForm" type="com.gvace.web.form.LoginForm"></form-bean>
 </form-beans>
 <action-mappings>
  <!-- localhost:8080/webapp/login.do, action path is the requested url path -->
  <!-- form-bean connect to the action identified by name -->
  <action path="/login" parameter="r" scope="request" name="loginForm"><!-- deleted type property since we have spring -->
   <!-- action choose which forward to go by forward name -->
   <forward name="ok" path="/WEB-INF/main.jsp"></forward>
   <forward name="err" path="/WEB-INF/err.jsp"></forward>
  </action>
 </action-mappings>
 <!-- set Proxy for the request control: DelegatingRequestProcessor -->
 <controller>
  <set-property property="processorClass" value="org.springframework.web.struts.DelegatingRequestProcessor"/>
 </controller>
</struts-config>


7. ehcache.xml

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true"
    monitoring="autodetect" dynamicConfig="true">
 
    <diskStore path="java.io.tmpdir/ehcache" />
 
    <defaultCache maxEntriesLocalHeap="10000" eternal="false"
        timeToIdleSeconds="120" timeToLiveSeconds="120" diskSpoolBufferSizeMB="30"
        maxEntriesLocalDisk="10000000" diskExpiryThreadIntervalSeconds="120"
        memoryStoreEvictionPolicy="LRU" statistics="true">
        <persistence strategy="localTempSwap" />
    </defaultCache>
 <!-- 
    <cache name="employee" maxEntriesLocalHeap="10000" eternal="false"
        timeToIdleSeconds="5" timeToLiveSeconds="10">
        <persistence strategy="localTempSwap" />
    </cache>
  -->
    <cache name="org.hibernate.cache.internal.StandardQueryCache"
        maxEntriesLocalHeap="5" eternal="false" timeToLiveSeconds="120">
        <persistence strategy="localTempSwap" />
    </cache>
 
    <cache name="org.hibernate.cache.spi.UpdateTimestampsCache"
        maxEntriesLocalHeap="5000" eternal="true">
        <persistence strategy="localTempSwap" />
    </cache>
</ehcache>


8. log4j.properties
# Root logger option
log4j.rootLogger=INFO, file, stdout

# Direct log messages to a log file
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=/home/yushan/javalog/logging.log
log4j.appender.file.MaxFileSize=10MB
log4j.appender.file.MaxBackupIndex=10
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
 
# 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{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n





Without config To get spring application context(Useless):

WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(this.getServlet().getServletContext());

































































































































































Sunday, April 3, 2016

Spring 3 + Hibernate 4 config


I faced some dependency issue:

Could not load requested class : org.hibernate.cache.ehcache.EhCacheRegionFactory

Thanks to
http://stackoverflow.com/questions/11905722/java-lang-noclassdeffounderror-org-hibernate-cache-entityregion-configuring-ehc
and its reference
http://web.archive.org/web/20130117102553/http://www.javacraft.org/2012/03/migrate-to-hibernate-4-ehcache.html

pom.xml


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>myssh</groupId>
 <artifactId>myssh</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <packaging>war</packaging>
 <properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <project.build.mainClass>com.gvace.main</project.build.mainClass>
  <java.version>1.7</java.version>
  <spring.version>3.2.16.RELEASE</spring.version>
  <hibernate.version>4.1.7.Final</hibernate.version>

 </properties>
 <dependencies>

  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-context</artifactId>
   <version>${spring.version}</version>
  </dependency>

  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-orm</artifactId>
   <version>${spring.version}</version>
  </dependency>

  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-aop</artifactId>
   <version>${spring.version}</version>
  </dependency>
  <!--@Transactional -->
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-tx</artifactId>
   <version>${spring.version}</version>
  </dependency>

  <dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-entitymanager</artifactId>
   <version>${hibernate.version}</version>
  </dependency>
  <!-- 
  <dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-search</artifactId>
   <version>4.1.1.Final</version>
  </dependency>
   -->
     <dependency>
       <groupId>org.hibernate</groupId>
       <artifactId>hibernate-ehcache</artifactId>
       <version>${hibernate.version}</version>
     </dependency>
  <!-- connection pooling with c3p0 -->
  <dependency>
   <groupId>c3p0</groupId>
   <artifactId>c3p0</artifactId>
   <version>0.9.1.2</version>
  </dependency>

  <dependency>
   <groupId>log4j</groupId>
   <artifactId>log4j</artifactId>
   <version>1.2.17</version>
  </dependency>

  <dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
   <version>5.1.38</version>
  </dependency>

  <dependency>
   <groupId>junit</groupId>
   <artifactId>junit</artifactId>
   <version>4.12</version>
   <scope>test</scope>
  </dependency>

  <dependency>
   <groupId>cglib</groupId>
   <artifactId>cglib</artifactId>
   <version>3.1</version>
  </dependency>

  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-test</artifactId>
   <version>${spring.version}</version>
   <scope>test</scope>
  </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.20</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-simple</artifactId>
        <version>1.7.20</version>
    </dependency>
 </dependencies>
</project>


applicationContext.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
 xmlns:tx="http://www.springframework.org/schema/tx"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"
 >
 <!-- Data Source -->
 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
  <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/myssh"/>
  <property name="username" value="root"/>
    <property name="password" value="root"/>
    <property name="initialSize" value="3"/>
    <property name="maxActive" value="500"/>
    <property name="maxIdle" value="2"/>
    <property name="minIdle" value="1"/>
 </bean>
 
 <!--Spring Cache--><!-- 
    <bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
        <property name="caches">
            <set>
                <bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" />
            </set>
        </property>
    </bean>
-->    
 <!-- Local Session Factory Bean -->
 <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
  <property name="dataSource" ref="dataSource"/>
  <property name="mappingResources">
   <list>
    <value>com/gvace/domain/Employee.hbm.xml</value>
   </list>
  </property>
  <property name="hibernateProperties">
   <value>
    hibernate.hbm2ddl.auto=update
    
    hibernate.dialect=org.hibernate.dialect.MySQLDialect
    hibernate.show_sql=true
    hibernate.format_sql=true
    
    hibernate.connection.CharSet=utf8
    hibernate.connection.characterEncoding=utf8
    hibernate.connection.useUnicode=true
    
    hibernate.generate_statistics=true
    hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory
    hibernate.cache.use_structured_entries=true
    hibernate.cache.use_second_level_cache=true
    hibernate.cache.use_query_cache=true   
   </value>
  </property>
 </bean>
 <!-- Spring Transaction Manager -->
 <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
  <property name="sessionFactory" ref="sessionFactory"></property>
 </bean>
 <!-- Start Transaction Annotation -->
 <tx:annotation-driven transaction-manager="transactionManager"/>
 
 <!-- Service Beans -->
 <bean id="employeeService" class="com.gvace.service.impl.EmployeeService">
  <property name="sessionFactory" ref="sessionFactory"/>
 </bean>
</beans>












































Sunday, March 20, 2016

Hibernate Cache

Session Cache(1st Level Cache)

1st Level Cache will be pushed during the following functions:
save, update, saveOrUpdate, load, get, list, iterate, lock

1st Level Cache will be loaded during the following functions:
get, load


1st Level Cache cleanning
default enabled, will not auto clean, so do cleaning manually

Example:
session.evict(student); //remove this instance from 1st level cache
session.clear(); //completely clear all instances from the session

Cache Life cycle

All instances will be purged when session closed.


SessionFactory Cache(2st Level Cache)


Stay with SessionFactory, so it's longer than 1st Level.

Has different third-party implementations.

Cache name
Cache Type Provider class
Hashtable
Memory Org.hibernate.cache.HashtableCacheProvider
EHCache
Memory, hard drive Org.hibernate.cache.EhCacheProvider
OSCache(out of maintain)
Memory, hard drive Org.hibernate.cache.OSCacheProvider
SwarmCache
distributed
(no distributed transaction)
Org.hibernate.cache.SwarmCacheProvider
JBoss Cache 1.x
distributed
(distributed transaction)
Org.hibernate.cache.TreeCacheProvider
JBoss Cache 2
distributed
(distributed transaction)
Org.hibernate.cache.JBossCacheRegionFactory


Four usage
1. Use in hibernate.cfg.xml: <class-cache usage="read-write">
2. Use in each *.hbm.xml <cache usage="read-write">

read-only
read-write
nonstrict-read-write
transactional


EHCache Example

hibernate.cfg.xml
  
  <property name="hibernate.generate_statistics">true</property>
  <property name="hibernate.cache.use_structured_entries">true</property>
  <property name="hibernate.cache.use_second_level_cache">true</property>
  <property name="hibernate.cache.use_query_cache">true</property>
  <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
  
  <mapping resource="com/gvace/notebook/domain/User.hbm.xml"/>
  <mapping resource="com/gvace/notebook/domain/Message.hbm.xml"/>
  
  <class-cache usage="read-write" class="com.gvace.notebook.domain.User"/>
  <class-cache usage="read-write" class="com.gvace.notebook.domain.Message"/>
-----------------------------------------------------

ehcache.xml

Optional, customize configs for each model/POJO/domain


2nd Level Cache Statistics

To generate statistics of cache for 2nd Level Cache
  <property name="hibernate.generate_statistics">true</property>

Get statics like follows:

SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
System.out.println("AAa"+sessionFactory.getStatistics());

Useful statistics

second level cache puts=10
second level cache hits=0
second level cache misses=0







Friday, March 18, 2016

Hibernate Lazy

Lazy: load on demand

Return proxy instead of target object, so load query when you call get functions.

Proxy example:

One-to-one object: HibernateProxy
Set: PersistentSet

So object MUST NOT set as final.


Hibernate default is lazy="true", this will cause error when you use related object when session is already closed.
If set a lot lazy="false", a lot unnecessary query will run, which cause a waste.

Solutions:
  1. Hibernate.initialize
  2. config in hbm.xml, lazy=false
  3. Web filter, openSessionInView
openSessionInView is better than others, since you don't know if you really loading related object or not. All we do just extend life cycle of session.

1. call getXX() function during the session

2. Hibernate.initialize during the session.


Hibernate.initialize(xxx);
//xxx is the property: obj.getXXX()


3. Config hbm.xml

In many-to-one(many side), if set the class to lazy="false"
Hibernate will use left outer join to load related data with the original data in one time.

In one-to-many(one side), if set the set to lazy="false"
Hibernate will first load the object list, then load ALL related objects from separate query for each object.




4. openSessionInView
Set lazy="true"(or just do not set lazy mode)
Make the query session alive, starts from the web filter, until jump out from the web filter.
All hibernate usage then REQUIRED to use getCurrentSession!
And also DONOT close session other than in this filter
This will make session stay open for longer time.

Filter:
for Spring, use Spring provided OpenSessionInViewFilter:

 <!-- OpenSessionInView with spring filter -->
 <filter>
  <filter-name>openSessionInViewFilter</filter-name>
  <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
 </filter>
 <filter-mapping>
  <filter-name>openSessionInViewFilter</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>


Or make filter your self:

public class HibernateSessionFilter extends HttpServlet implements Filter {

 @Override
 public void doFilter(ServletRequest request, ServletResponse response,
   FilterChain chain) throws IOException, ServletException {
  Session session = null;
  Transaction tx = null;
  try {
   session = HibernateUtil.getCurrentSession();
   tx = session.beginTransaction();
   chain.doFilter(request, response);
   tx.commit();
  } catch (Exception e) {
   if(tx!=null)tx.rollback();
   throw new RuntimeException(e.getMessage());
  } finally {
   HibernateUtil.closeCurrentSession();
  }

 }

 @Override
 public void init(FilterConfig filterConfig) throws ServletException {

 }

}



Issues for 1 and 2
hard to know when to pre-load, and when to not-pre-load.
If set to pre-load: may waste unnecessary querys
If set to not-pre-load: will cause error when getting related property


Wednesday, March 9, 2016

Hibernate Cascade

Transitive Persistence

Normally used to <one-to-many> and <one-to-one>: "one" side
Not suggest for <many-to-one> and <many-to-many>: "many" side


  1. Can used in <Set> and also <Property>
  2. Used in <one-to-many>, "one" side
  3. Used in <one-to-one>, primary object side
Cascade options:

none
all
save-update: 
delete
lock
refresh
evict
replicate
persist
merge
delete-orphan(one-to-many)


Examples: 
cascade="all"
cascade="persist,merge,save-update"
cascade="delete"

Example:(one-to-many)

Auto delete students when delete a department.

in Department.hbm.xml
<set name="students" cascade="delete">
<key column="dept_id"/>
<one-to-many class="student" />
</set>

when doing delete a department, all students in its <set> will be deleted


Example:(one-to-many)

Auto add/update students when save a department.

in Department.hbm.xml
<set name="students" cascade="save-update">
<key column="dept_id"/>
<one-to-many class="student" />
</set>

When save a department, all students in its <set> will be saved/updated


Example:(many-to-one)

Auto add/update department when save a student

in Student.hbm.xml
<many-to-one name="department" column="dept_id" cascade="save-update">
<key column="dept_id"/>
<one-to-many class="student" />
</set>

When saving/updating a student, its department will also be saved/updated







Sunday, March 6, 2016

Hibernate Object Relationships

one-to-one

1: based on Primary key one-to-one

Two tables, A and B.
B's foreign id is A's id.

Student obj: {id,name,idCard}

<one-to-one name="idCard"/>


IdCard obj: {id,expdate,student}

Generate primary id by a foreign key

<!-- set id as foreign key -->
<id name="id">
  <generator class="foreign">
  <param name="property">student</param>
  </generator>
</id>
<one-to-one name="student" constrained="true">

In <one-to-one>
constriained="true": copy target id as self id, and make as foreign key relationship in table
constriained="false": simply copy target id as self id


2: based on Foreign key one-to-one

To make a one-to-one relationship based on Foreign key:
simply use <many-to-one> and set unique="true"

In IdCard.hbm.xml

<many-to-one name="student" unique="true" />




many-to-one

Student to Department

<hibernate-mapping package="com.gvace.domain">
 <class name="Student">
  <id name="id" type="java.lang.Integer">
   <generator class="increment"></generator>
  </id>
  <property name="name" type="java.lang.String">
   <column name="name" length="64" not-null="true"/>
  </property>
        <many-to-one name="department" column="dept_id" />
        <!-- 
         "name": property name
         "column": column name in this table
          -->
 </class>
</hibernate-mapping>


Issue: in lazy mode, after session closed, the foreign property still not load.
Solution:

  1. Hibernate.initialize(student.getDepartment()); //initialize proxy
  2. <class name="Department" lazy="false"> //disable lazy mode
  3. Filter(web project): openinSessionInView

one-to-many

Get all students from a department

private Set students = new HashSet(0); //can be any collection

In hbm.xml, use <set> to represent one-to-many property

<hibernate-mapping package="com.gvace.domain">
 <class name="Department" lazy="false">
  <id name="id" type="java.lang.Integer">
   <generator class="increment"></generator>
  </id>
  <property name="name" type="java.lang.String">
   <column name="name" length="64" not-null="true"/>
  </property>
  <!-- One to Many -->
  <set name="students" >
   <key column="dept_id"></key>
   <one-to-many class="Student"/>
  </set>
 </class>
</hibernate-mapping>


cascade="save-update"
In <set>: If we want automatically save each record in <set> property, use cascade="save-update"


many-to-many


Normally we CONVERT many-to-many relationship to two one-to-many, and one many-to-one
We create a new table for only relationship mapping


Student obj: {id, name, Set<StudentCourse> studentCourses}
Course obj: {id, name,  Set<StudentCourse> studentCourses}
StudentCourse obj: {id, Student, Course, grade}

Target Student table: {id, name}
Target Course table: {id, name}
Target StudentCourse table: {id, student_id, course_id, grade}

Student.hbm.xml

<set name="studentCourses">
  <key column="student_id" />
  <one-to-many class="StudentCourse" />
</set>

Course.hbm.xml

<set name="studentCourses">
  <key column="course_id" />
  <one-to-many class="StudentCourse" />
</set>


StudentCourse.hbm.xml

<many-to-one name="course" column="course_id" />
<many-to-one name="student" column="student_id" />




Hibernate Domain/Model/POJO



  1. Default constructor
  2. Has an id(primary key) for identity only, no content meaning for this id
  3. getter/setter

Session methods


  • close()
  • clear(): Completely clear the session
  • connection(): get JDBC connection
  • delete(Object object): Remove a persistent instance from the database
  • evict(Object object): Remove instance from the session cache
  • flush(): force session to flush



Transient state
Object does NOT match any data in the db table
NO session is related to this object
If exceed scope, JVM will do garbage collection.

Normally to be the object has been created but not related to any session nor db record.

Persistent state
Object has matched data in the db table
Object also related to a session
Session is not closed
Transaction is not committed.

If persistent state object changes, the db record will be changed when transaction commited.

employee.setName("abc");
transaction.commit();
//do update db immediately


Detached state
Object has matched data in the db table
Object is NOT related to any session

If detached state object changes, hibernate will not notice that, and db will not change








Thursday, March 3, 2016

HQL and Criteria

HQL: Hibernate Query Language

HQL:

  • Case sensitive for Java class and field
  • HQL query is to object, not table
  • support polymorphism
Query q = session.createQuery(hql);


  • from Person
  • from User user where user.name=:name
  • from User user where user.name=name and user.birthday <:birthday
Table primary key: better not to be business logic


Generating domain file and *.hbm.xml file: if we have primary key and foreign key, first generate for primary table, then generate foreign table

session.delete
session.save
session.persist
session.update
session.load
session.get

Examples


1. select all field from table
The result can be as List<Student>
//hql: get all field from table

List<Student> list1 = session.createQuery("from Student where id<10").list();
//"Student" is class name, not table name
//"from Student" default as "select *"

2. select part of fields from table(more than one column)
The result can NOT be List<Student>, it is List<Object[]>
 //hql: get part of fields from table
 List<Object[]> list1 = session.createQuery("select name,department from Student").list();
 //"Student" is class name
 //only returns List<Object[]>
//Also can do query like distinct, between and, in(), count,avg, having,max,min,sum etc..
List<Object[]> list2 = session.createQuery("select distinct age,gender from Student where age between 10 and 30").list();

like
List<Object[]> list3 = session.createQuery("from Student where name like '%Cat%'").list();


from Student where name like "%Cat%"

3. select only one column from table
The result is List<Object>, NOT List<Object[]>


4. Foreign key: foreign key is already transformed to class on the field, so calling id name directly in hql will cause exception, we have to check class field to match hql columns

List<Object[]> list1 = session.createQuery("select id,course.id,grade from Stucourse").list();

5. uniqueResult(): select unique record from table
Must make sure it has only one or no record
returns null if no record
Throws exception if multiple record found, so setMaxResults(1) can make sure it has only one record
Student s = (Student)session.createQuery("from Student where id<10").setMaxResults(1).uniqueResult();

6. setFirstResult(int): starting record from query, default start from 0

7. setMaxResults(int): retrieve only certain amount of records or less
Pagination will be used by setFirstResult(int) and setMaxResults(int)


8. Parameters in Query
Two styles

  • "?", starts from 0
    Query query = session.createQuery("from Student where department=? and age>?");query.setString(0, "计算机系");
    query.setInteger(1, 20);
    List<Student> list1 = query.list();
  • ":"
    Query query = session.createQuery("from Student where department=:dept and age>:age"); query.setString("dept", "计算机系");
    query.setInteger("age", 20);
    List<Student> list1 = query.list();


Criteria

Criteria cri = session.createCriteria(Student.class);
cri.add(Restrictions.gt("age", 10));












Sunday, February 28, 2016

hibernate.cfg.xml

Basic setup

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
  "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
  "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
     <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
     <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
     <property name="connection.username">root</property>
     <property name="connection.password">root</property>
     <property name="connection.url">jdbc:mysql://192.168.56.101:3306/hibernate</property>
     <mapping resource="com/gvace/domain/Employee.hbm.xml"/>
    </session-factory>
</hibernate-configuration>

<mapping resource="com/gvace/domain/Employee.hbm.xml"/> for mapping to each *.hbm.xml file



Output query for debug: 
 <property name="show_sql">true</property>
<property name="format_sql">true</property>

  <property name="hbm2ddl.auto">

<property name="hbm2ddl.auto">update</property>
Variable values: validate | update | create | create-drop
So the list of possible options are,
  • validate: validate the schema, makes no changes to the database.
  • update: update the schema, alter or add column, never delete column
  • create: creates the schema, destroying previous data, every time when app loads
  • create-drop: drop the schema when session factory closed.


Session Range
<property name="hibernate.current_session_context_class"> thread</property>
hibernate.current_session_context_class: jta, thread, managed, custom.Class
jta: cross databases/hosts, remote server database
thread: local events only, for one single database


Character Encoding
  <property name="hibernate.connection.CharSet">utf8</property>
  <property name="hibernate.connection.characterEncoding">utf8</property>

  <property name="hibernate.connection.useUnicode">true</property>

Saturday, February 27, 2016

Hibernate

Core Classes and Interfaces






Hibernate API

ORM(Object Relation Mapping)


pojo: plain ordinary java object

A pojo object
  1. Has at least a primary key field
  2. other fields
  3. public get/set functions
  4. a non-parameter construct function(for hibernate reflection use)

Configuration :
Load hibernate.cfg.xml
Manage ORM files
Load driver, url, login
Manage hibernate configs

SessionFactory :
Get session instance from SessionFactory
Initialized when application starts
Occupied large memory, only need one instance for each database, so use singleton for each database
Cache sql statements and some data (session level cache)


Session : generated from sessionFactory
http://gvace.blogspot.com/2015/12/hibernate-session.html

Transaction : transaction is required, so remember to commit

Example 

Employee pojo -> employee table

hibernate.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
  "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
  "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
     <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
     <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
     <property name="connection.username">root</property>
     <property name="connection.password">root</property>
     <property name="connection.url">jdbc:mysql://192.168.56.101:3306/hibernate</property>
     <property name="show_sql">true</property>
     <mapping resource="com/gvace/domain/Employee.hbm.xml"/>
    </session-factory>
</hibernate-configuration>


Employee.hmb.xml

hmb.xml file: manage relationship between a pojo class and a table

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated Feb 26, 2016 10:59:22 PM by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
    <class name="com.gvace.domain.Employee" table="employee">
        <id name="id" type="java.lang.Integer">
            <column name="ID" />
            <generator class="increment" />
        </id>
        <property name="name" type="java.lang.String">
            <column name="NAME" not-null="true"/>
        </property>
        <property name="email" type="java.lang.String">
            <column name="EMAIL" not-null="true" />
        </property>
        <property name="hiredate" type="java.util.Date" >
            <column name="HIREDATE" not-null="true"/>
        </property>
    </class>
</hibernate-mapping>




Employee.java

pojo class, require serialize

package com.gvace.domain;

public class Employee implements Serializable{
 private static final long serialVersionUID = -3742562662542696434L;
 private Integer id;
 private String name;
 private String email;
 private java.util.Date hiredate;
 public Integer getId() {
  return id;
 }
 public void setId(Integer id) {
  this.id = id;
 }
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public String getEmail() {
  return email;
 }
 public void setEmail(String email) {
  this.email = email;
 }
 public java.util.Date getHiredate() {
  return hiredate;
 }
 public void setHiredate(java.util.Date hiredate) {
  this.hiredate = hiredate;
 }
 public Employee() {
 }
}


Example of using the pojo

 @Test
 public void test(){
  //1. Initiate config, load config file
  Configuration configuration = new Configuration().configure("hibernate.cfg.xml");
  //2. Create SessionFactory, normally use singleton
  ServiceRegistry serviceRegistry;
  serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
  SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);
  //3. Create session
  Session session = sessionFactory.openSession();
  //4. Start a transaction
  Transaction transaction = session.beginTransaction();
  
  //5. Add an employee
  Employee employee = new Employee();
  
  employee.setName("abc");
  employee.setEmail("abc@abc.com");
  employee.setHiredate(new Date());
  
  //6. Save
  session.save(employee);
  
  //7. Commit
  transaction.commit();
  
  //8. Close session
  session.close();
 }




Wednesday, December 23, 2015

Hibernate Session

Hibernate Session Definition: 


An instance which represents a set of operations(crud) on database
A persist related interface


factory.openSession VS factory.getCurrentSession




factory.openSessionfactory.getCurrentSession
ThreadNot relatedUsing ThreadLocal, bind to current thread
When closerequire manual closeauto close after commit or rollback
When to useno thread relatedwant operation in same thread
Transactionnot requiredrequire transaction commit
Confignot required<property name="hibernate.current_session_context_class"> thread</property>


Session Range
<property name="hibernate.current_session_context_class"> thread</property>

hibernate.current_session_context_class: jta, thread, managed, custom.Class
jta: cross databases/hosts, remote server database
thread: local events only, for one single database


Session states: (to be introduced...)

Transient
Persistent
Detached


Functions


save
merge
persist
saveOrUpdate
lock


get
load


update



delete





session.get VS session.load




Session.getSession.load
Return ObjectReturn target objectReturn a proxy of object
If result not foundReturn nullThrow ObjectNotFoundException
When to useIf the result may be nullIf the result is sure not be null
Cache looking sequenceSession cache(1st level)
2nd level cache
SQL
return
Session cache(1st level)
2nd level cache
return object proxy(lazy)
when use object during session: SQL & return
when use object out of session: throw Exception




Session.load is using Lazy fetching mode, if hbm configures lazy to false, session.load will be the same as session.get

2nd level cache needs configuration to enable

If the same result has been checked more frequently, hibernate will move cache from 2nd level to session cache(1st level)

To cancel Lazy fetching mode, config *.hmb.xml, set <class> tag: lazy="false"