Pages

How Java Class is loaded into JVM


How Java Class is loaded into JVM


Java ClassLoader loads the classes at runtime. Class Loader in java works on three principle: Delegation, Visibility and Uniqueness .

1. Delegation: Delegation forward the incoming request of a class loading to a parent ClassLoader and only loads the class.

2. Visibility : Visibility allows child ClassLoader to see or check whether all classes is loaded by the parent ClassLoader but parent  ClassLoader can not check whether all classes loaded by the child ClassLoader.

3. Uniqueness: uniqueness allows to load a class exactly once. Which is basically achieved by the delegation and ensure that child ClassLoader doesn’t reload the class already loaded by the parent.

Note : One java class couldn’t loaded by two different ClassLoader.

ClassLoader in Java is a class which is used to load the class files in java. Java code is complied using javac complier and JVM executes the java program by running the byte code from the class file. ClassLoader is responsible to load the class from the file system, network or any other sources.

There are three type of ClassLoader in java and every ClassLoader has predefined location from where they loads the classes. 

      1.  BootStrap ClassLoader  Or Primordial ClassLoader  (JRE/lib/rt.jar)
      2.  Extension ClassLoader  (JRE/lib/ext or any directory denoted by java.ext.dirs)
      3. Application ClassLoader  (ClassPath, environment variable, -classpath, -cp option, ClassPath attribute                             in Manifest inside a JAR)







BootStrap ClassLoader is parent of all the ClassLoader in java, If you call String.class.getClassLoader() it will return null. Extension ClassLoader delegates request to parent ClassLoader (Bootstrap), If it fails to find the class than Extension ClassLoader loads the class from JRE/lib/ext or JRE/ext/dirs (System Property). Extension ClassLoader in JVM is implemented by sun.misc.Launcher$ExtClassLoader

Third default ClassLoader  used by JVM is System or Application ClassLoader. It loads the classes from classpath, -cp command line option, Class-Path attribute of Manifest file inside JAR
Application ClassLoader is the child of Extension ClassLoader and implemented by sun.misc.Launcher$AppClassLoader class. Bootstrap ClassLoader is basically implemented in native language like C. All java class loaders are implemented  using java.lang.ClassLoader.






Delegation Principles : A class is loaded in java when it needs or requires. Suppose you have an application specific class called Employee.class, first request of loading this class will come to Application ClassLoader which will delegates request to Extension ClassLoader which further delegates it to Bootstrap ClassLoader. Bootstrap or Primordial ClassLoader will check this class in JRE/lib/rt.jar and since this class is not there, request comes to Extension ClassLoader which looks this class in JRE/lib/ext or JRE/ext/dirs directory and tries to locate this class there. If class is found there than Extension ClassLoader will load that class and Application ClassLoader will never load this class But if its not loaded by Extension ClassLoader than Application ClassLoader load this class from classpath in java.

Note: classpath is used to load  class files while PATH is used to executable like javac or java command.

Visibility Prinicples : Child ClassLoader can see or check classes loaded by parent ClassLoader but it’s vice versa not true. Which mean if Employee class is loaded by Application ClassLoader than trying to load this class explicly using Extension ClassLoader will throw java.lang.ClassNotFoundException.

Uniqueness Principles : According to this principle a class loaded by Parent should not be loaded by Child ClassLoader again. Though its completely possible to write class loader which violates Delegation and Uniqueness principles and loads class by itself, its not something which is beneficial. You should follow all  class loader principle while writing your own ClassLoader.


How to load class explicitly in java :

Java provides API to explicitly load a class by Class.forName(classname) and Class.forName(classname, initialized, classloader),  As shown in below example you can pass name of ClassLoader which should be used to load that particular class along with binary name of class. Class is loaded by calling loadClass() method of java.lang.ClassLoader class which calls findClass() method to locate bytecodes for corresponding class. In this example Extension ClassLoader uses java.net.URLClassLoader which search for class files and resources in JAR and directories. any search path which is ended using "/" is considered directory. If findClass() does not found the class than it throws java.lang.ClassNotFoundException and if it finds it calls defineClass() to convert bytecodes into a .class instance which is returned to the caller.


Where to use ClassLoader in Java :

ClassLoader in Java is a powerful concept and used at many places. One of the popular example of ClassLoader is AppletClassLoader which is used to load class by Applet, since Applets are mostly loaded from internet rather than local file system, By using separate ClassLoader you can also loads same class from multiple sources and they will be treated as different class in JVM. J2EE uses multiple class loaders to load class from different location like classes from WAR file will be loaded by Web-app ClassLoader while classes bundled in EJB-JAR is loaded by another class loader. Some web server also supports hot deploy functionality which is implemented using ClassLoader. You can also use ClassLoader to load classes from database or any other persistent store.

import java.util.logging.Level;
import 
java.util.logging.Logger;

/**
 * Java program that define How ClassLoader works in Java,
 * in particular about visibility principle of ClassLoader.
 *
 * @author Anuj Verma
 */


public class ClassLoaderTest 
{

    public static 
void main(String args[]) {
        try 
{       
            
//printing ClassLoader of this class
            System.
out.println("ClassLoaderTest.getClass().getClassLoader() : "
                                 + ClassLoaderTest.class.getClassLoader());


       
            
//trying to explicitly load this class again using Extension class loader
            Class.
forName("test.ClassLoaderTest"true 
                            ,  ClassLoaderTest.class.getClassLoader().getParent());

        
} catch (ClassNotFoundException ex) {
            Logger.
getLogger(ClassLoaderTest.class.getName()).log(Level.SEVEREnull, ex);
        
}
    
}

}

Output:
ClassLoaderTest.
getClass().getClassLoader() : sun.misc.Launcher$AppClassLoader@601bb1
16/08/2012 2:43:48 AM test.ClassLoaderTest
 main
SEVERE: 
null
java.
lang.ClassNotFoundException: test.ClassLoaderTest
        at java.
net.URLClassLoader$1.run(URLClassLoader.java:202)
        at java.
security.AccessController.doPrivileged(Native Method)
        at java.
net.URLClassLoader.findClass(URLClassLoader.java:190)
        at sun.
misc.Launcher$ExtClassLoader.findClass(Launcher.java:229)
        at java.
lang.ClassLoader.loadClass(ClassLoader.java:306)
        at java.
lang.ClassLoader.loadClass(ClassLoader.java:247)
        at java.
lang.Class.forName0(Native Method)
        at java.
lang.Class.forName(Class.java:247)
        at test.
ClassLoaderTest.main(ClassLoaderTest.java:29)



Integration of Spring MVC with JSR 303 Validation

Spring supports JSR-303 validation Specification with Spring mvc. You can enable <mvc:annotation-driven /> to support JSR-303 validation.

To integrate JSR-303 bean validation, these are following steps to enable bean validation.

Step 1: Insert following dependency for apache tiles 3 and Spring MVC in pom.xml.
    
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>4.2.0.Final</version>
        </dependency> 


Step 2: Make a entry in root-servlet.xml file for loading the properties file using Spring's ReloadableResourceBundleMessage class.

     <mvc:annotation-driven />  
    <bean id="messageSource"
        class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <property name="basename" value="classpath:message_en" />
  </bean>


Note: define only properties's filename for value attribute, we put properties file at the classpath.

Step 3: we configured Controller class for JSR-303 validation by using @Valid annotation. This annotation automatically validate the fomBean if validation fails it returns to the same view and display the proper error message from the properties file at the classpath.

package controller;

import javax.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import formbean.TestForm;

@Controller
@RequestMapping("/login")
public class TestController {
   
    @RequestMapping(value={"/index","/"})
    public ModelAndView  index(){
        ModelAndView modelAndView = new ModelAndView("index");
        modelAndView.addObject("testForm", new TestForm());
        return modelAndView;
    }

    @RequestMapping(value = "/submit", method=RequestMethod.POST)
    public ModelAndView submit(@Valid TestForm testForm, BindingResult result) {
        ModelAndView modelAndView ;
        if(result.hasErrors()) {
            modelAndView = new ModelAndView("welcome");
        } else {
            modelAndView = new ModelAndView("home");
        }
        modelAndView.addObject(testForm);
        return modelAndView;
    }
   
    @RequestMapping("/layout")
    public ModelAndView welcomePage() {
        ModelAndView modelAndView = new ModelAndView("welcome");
        modelAndView.addObject("testForm", new TestForm());
        return modelAndView;
    }
   
    @RequestMapping(method=RequestMethod.GET)
    public String createLoginForm(@RequestParam String user1, Model model) {
        model.addAttribute(new TestForm());
        return "welcome";
    }   
}


Step 4: declare the JSR-303 annotation on required properties in form bean for JSR-303 validation. we didn't declare the custom message in each property instead we keep all message in the message_en.properties file at the classpath.

package formbean;

import javax.validation.constraints.Size;
import org.hibernate.validator.constraints.NotEmpty;

public class TestForm {
   
    @NotEmpty
    @Size(min=3, max=6)

    private String firstName;
   
    @NotEmpty
    @Size(min=3, max=6)

    private String lastName;
   
    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    public String getLastName() {
        return lastName;
    }
    public void setLa/stName(String lastName) {
        this.lastName = lastName;
    }
}


Step 5 : declare the all error message in message_en.properties file under at src/main/resources/message_en.properties.

NotEmpty.testForm.firstName=first name is required
Size.testForm.firstName=first name must be between 3 and 6 characters long
Size.testForm.lastName=last name must be between 3 and 6 characters long

Step 6: Bind the error message in jsp file as below.

<%@ page contentType="text/html; charset=ISO-8859-1" %>

<%@ taglib prefix="spring" uri="http://www.springframework.org/tags/form" %>

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Welcome Page</title>
</head>
<body>

<spring:form commandName="testForm" action="/login/submit" method="POST">
    <table>
        <tr> <td>First Name :: </td>
            <td><spring:input path="firstName" /><br>
                <font color="red"><spring:errors path="firstName"/></font>
            </td>       
        </tr>
        <tr> <td>Last Name :: </td>
            <td><spring:input path="lastName" /><br>
                <font color="red"><spring:errors path="lastName"/></font>
            </td>       
        </tr>
        <tr>
            <td><input type="submit" value="submit" /></td>       
        </tr>
    </table>
</spring:form>
</body>
</html>




Note: By default, if validation failed.
  1. @NotEmpty will display “may not be empty”
  2. @Range will display “must be between 1 and 150″
You can override it easily, create a properties with “key” and message. To know which @annotation bind to which key, just debug it and view value inside BindingResult result“. Normally, the key is “@Annotation Name.object.fieldname“.





Integration of Spring mvc with Apache tiles 3.0.

Apache Tiles3 is a templating framework for laying out pieces of a page as fragments that are assembled into a full page at runtime. It provides a nice look and feel to a web application. 

To integrate Apache Tiles 3.0 with Spring MVC with maven, You should follow these steps for integrations.

Step 1 : Insert following dependency for apache tiles 3 and Spring MVC in pom.xml.

<properties>
    <java-version>1.7</java-version>
    <org.springframework-version>3.2.2.RELEASE</org.springframework-version>
    <org.aspectj-version>1.6.9</org.aspectj-version>
    <org.slf4j-version>1.5.10</org.slf4j-version>
</properties>

 <dependencies>
                <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>${org.springframework-version}</version>
</dependency>
 
<dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${org.springframework-version}</version>
</dependency>
   
<dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-web</artifactId>
   <version>${org.springframework-version}</version>
</dependency>
<dependency>
   <groupId>org.apache.tiles</groupId>
   <artifactId>tiles-extras</artifactId>
   <version>3.0.0</version>
</dependency>
<dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.5.2</version>
                </dependency>

<dependency>
     <groupId>jstl</groupId>
     <artifactId>jstl</artifactId>
     <version>1.2</version>
</dependency>
  </dependencies>

Step 2: Make a configuration in web.xml for Spring Dispatcher Servlet and Url Mapping under /WEB-INF/.

<?xml version="1.0" encoding="UTF-8"?>

<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

     <servlet>
             <servlet-name>root</servlet-name>
             <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param>
                    <param-name>contextConfigLocation</param-name>
                    <param-value>classpath:/root-servlet.xml</param-value>
           </init-param>
           <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
            <servlet-name>root</servlet-name>
            <url-pattern>/</url-pattern>
    </servlet-mapping>
    <welcome-file-list>
            <welcome-file>/WEB-INF/views/index.html</welcome-file>
    </welcome-file-list>
</web-app>

Step 3: create a root-servlet.xml file for Spring application context under src/main/resources/.

<?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:mvc="http://www.springframework.org/schema/mvc"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
 
    <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
 
    <!-- Scans within the base package of the application for @Components to configure as beans -->
    <!-- @Controller, @Service, @Configuration, etc. -->
    <context:component-scan base-package="controller" />
 
    <!-- Enables the Spring MVC @Controller programming model -->
    <mvc:annotation-driven />
    
    <mvc:resources location="/img/" mapping="/img/**"/>
    
    <bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles3.TilesConfigurer" >
         <property name="definitions">
             <value>/WEB-INF/tiles/tiles.xml</value>
         </property>
    </bean>

    <bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">
     <!--Don't add suffix or prefix like you do with .jsp files-->
   <property name="viewClass" value="org.springframework.web.servlet.view.tiles3.TilesView"/>
    </bean>
</beans>

Step 4: Declare a tiles.xml file under /WEB-INF/tiles/ folder in project.

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE tiles-definitions PUBLIC "-//Apache Software Foundation//DTD Tiles Configuration 3.0//EN" "http://tiles.apache.org/dtds/tiles-config_3_0.dtd">

<tiles-definitions>
          <definition name="baseLayout" template="/WEB-INF/layout/layout.jsp">
                 <put-attribute name="header" value="/WEB-INF/layout/header.jsp" />
                 <put-attribute name="menu" value="/WEB-INF/layout/menu.jsp"/>
                 <put-attribute name="body" value="" />
          </definition>
          <definition name="welcome" extends="baseLayout">
                 <put-attribute name="body" value="/WEB-INF/views/index.jsp"/>
          </definition>
          <definition name="home" extends="baseLayout">
                 <put-attribute name="body" value="/WEB-INF/views/home.jsp"/>
          </definition>
</tiles-definitions>

Step 5: create a TestController to handle the Http Request under the src/main/java/controller package.

package controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import formbean.TestForm;

@Controller
public class TestController {
public TestController() {System.out.println("In TestController ::");}
@RequestMapping(value={"/index","/"})
public ModelAndView  index(){
System.out.println("In Index method");
ModelAndView modelAndView = new ModelAndView("index");
modelAndView.addObject("testForm", new TestForm()); 
return modelAndView;
}

@RequestMapping(value = "/submit", method=RequestMethod.POST)
    public ModelAndView submit(TestForm testForm) {
        System.out.println("In Submit(): get All value from method body...");
        
        ModelAndView modelAndView = new ModelAndView("home");
        modelAndView.addObject(testForm);
        
        return modelAndView;
    }
@RequestMapping("/layout")
public ModelAndView welcomePage() {
ModelAndView modelAndView = new ModelAndView("welcome");
modelAndView.addObject("testForm", new TestForm()); 
return modelAndView;
}
}

Step 6: create a layout.jsp, header.jsp and menu.jsp page under /WEB-INF/layout/ folder.

1. layout.jsp :

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>

<%@ taglib prefix="tiles" uri="http://tiles.apache.org/tags-tiles" %>

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Main Page</title>
</head>
<body>
<table border="1" width="100%" height="15%">
<tr bordercolor="yellow" height="2%">
<td colspan="2">
<tiles:insertAttribute name="header"/>
</td>
</tr>
<tr height="10%">
<td width="10%" align="center" bordercolor="yellow">
<tiles:insertAttribute name="menu"/>
</td>
<td width="90%" align="center" bordercolor="yellow">
<tiles:insertAttribute name="body"/>
</td>
</tr>
</table>
</body>
</html>

2. header.jsp :

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
</head>
<body>
<img alt="image" src="img/clg.jpg">
</body>
</html>

3 menu.jsp : I keep blank this menu.jsp page, you can keep some content in this section as you like.

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
</head>
<body>
</body>
</html>

create a index.jsp and home.jsp under /WEB-INF/views/ folder.

1. index.jsp :

<%@ page contentType="text/html; charset=ISO-8859-1" %>

<%@ taglib prefix="spring" uri="http://www.springframework.org/tags/form" %>

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Welcome Page</title>
</head>
<body>

<spring:form commandName="testForm" action="/submit">
<table>
<tr> <td>First Name :: </td>
<td><spring:input path="firstName" /></td>
</tr>
<tr> <td>Last Name :: </td>
<td><spring:input path="lastName" /></td>
</tr>
<tr>
<td><input type="submit" value="submit" /></td>
</tr>
</table>
</spring:form> 

</body>
</html>

2: home.jsp

<%@ page contentType="text/html; charset=ISO-8859-1" language="java" %> 

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Home Page</title>
</head>

<body>
<form:form commandName="testForm">
<table>
<tr> <td>First Name :: </td>
<td><h4>${testForm.firstName}</h4></td>
</tr>
<tr> <td>Last Name :: </td>
<td><h4>${testForm.lastName}</h4></td>
</tr>
<tr><td><a href="layout.html">Go Back</a></td></tr>
</table>
</form:form>
</body>
</html>

Step 7: create a form bean under src/main/java/formbean package and name is TestForm.java

package formbean;

public class TestForm {
private String firstName;
private String lastName;
// getter setters ... 
}

Now, hit this URL http://localhost:8084/Test/layout 
















Mapping of collection and entity associations

Mapping of collection and entity associations

Whenever you have a collection of objects (value type) in a entity class that time you need one collection table to map the collection of objects (value types) . Value type classes in the collection does not have an identifier property, So lifespan of value type instances is bounded by the owning entity.

Hibernate supports most of the JDK type collection interface like Set, SortedSet, List, Collection, Map,Sorted Map. Hibernate only wraps the collection objects which we initializes on declaration of the field. 
In JPA, collection properties hold references of the  entity object,collection of value type instances are not standardized.

Hibernate have the correct implementation for above declared interfaces. if you maps a collection but hibernate does not have a correct implementation of it,That time you have to tell the hibernate about its semantics. The extension point in hibernate is called PersistentCollection, you extend one of the existing classes (PersistentSet, PersistentBag or PersistentList).

how to map a collection (like set, list, map) in hibernate?
let's suppose we have collection of String (like image-name) in the item class and one item will have only image (so you won't duplicate images for one item) So in that case, we define Item class that will have set of String for images,


public class Item {

private Long itemId;
private String itemName;
private Double itemAmount;
private Date createdDate;
private Date modifiedDate;
private Set<String>  images = new HashSet<String>();

// generate getter's and setters method 
}


Now, we will map set of images to collection table ,  look at XML mapping meta data file carefully.


<hibernate-mapping package="mapping.a.set" default-access="property">
    
    <class name="Item" table="ITEM" dynamic-insert="true" dynamic-update="true">
<id name="itemId" column="ITEM_ID">
<generator class="increment"/>
</id>
<property name="itemAmount" column="ITEM_AMOUNT"/>
<property name="itemName" column="ITEM_NAME"/>
<property name="createdDate" column="CREATED_DATE"/>
<property name="modifiedDate" column="MODIFIED_DATE"/>
<set name="images" table="ITEM_IMAGES">
<key column="ITEM_ID"/>
<element column="IMAGE_FILE" type="string" not-null="true"/>
</set>
</class>
</hibernate-mapping>


<element > tag in the mapping file declares set of images as a values type instances. Now, if you try to run the main method, it will save the image name in the collection table.


public static void main(String[] args) {
LOGGER.info("starting of main method");
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction txn = session.beginTransaction();

Item item = new Item();
item.setItemName("Samsung");
item.setItemAmount(38000D);
item.setCreatedDate(new Date());
item.setModifiedDate(new Date());
item.getImages().add("A.jpg");

LOGGER.info("before save or update");
session.saveOrUpdate(item);

                 txn.commit();
session.close();
HibernateUtil.shutDown();

}


see the hibernate generated comment on console.

........

Oct 25, 2012 11:00:47 AM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing foreign key constraints
Oct 25, 2012 11:00:47 AM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing extends queue
Oct 25, 2012 11:00:47 AM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing collection mappings
Oct 25, 2012 11:00:47 AM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing association property references
Oct 25, 2012 11:00:47 AM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing foreign key constraints
Oct 25, 2012 11:00:47 AM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: Running hbm2ddl schema export
Oct 25, 2012 11:00:47 AM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: exporting generated schema to database
Oct 25, 2012 11:00:47 AM org.hibernate.connection.C3P0ConnectionProvider configure
INFO: C3P0 using driver: null at URL: jdbc:mysql://localhost:3306/HibernateTest
Oct 25, 2012 11:00:47 AM org.hibernate.connection.C3P0ConnectionProvider configure
INFO: Connection properties: {autocommit=true, user=root, password=****}
Oct 25, 2012 11:00:47 AM org.hibernate.connection.C3P0ConnectionProvider configure
INFO: autocommit mode: true
Oct 25, 2012 11:00:47 AM org.hibernate.connection.C3P0ConnectionProvider configure
WARNING: No JDBC Driver class was specified by property hibernate.connection.driver_class
11:00:47,806 INFO AbstractPoolBackedDataSource:462 - Initializing c3p0 pool... com.mchange.v2.c3p0.PoolBackedDataSource@e8d20194 [ connectionPoolDataSource -> com.mchange.v2.c3p0.WrapperConnectionPoolDataSource@475c0595 [ acquireIncrement -> 1, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, debugUnreturnedConnectionStackTraces -> false, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> 1bs1yqt8q15qbf2ecvl29|114a0de, idleConnectionTestPeriod -> 3000, initialPoolSize -> 5, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 300, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 20, maxStatements -> 100, maxStatementsPerConnection -> 0, minPoolSize -> 5, nestedDataSource -> com.mchange.v2.c3p0.DriverManagerDataSource@44e5bd7f [ description -> null, driverClass -> null, factoryClassLocation -> null, identityToken -> 1bs1yqt8q15qbf2ecvl29|11b8a4c, jdbcUrl -> jdbc:mysql://localhost:3306/HibernateTest, properties -> {autocommit=true, user=******, password=******} ], preferredTestQuery -> null, propertyCycle -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false; userOverrides: {} ], dataSourceName -> null, factoryClassLocation -> null, identityToken -> 1bs1yqt8q15qbf2ecvl29|ed8181, numHelperThreads -> 3 ]
Oct 25, 2012 11:00:48 AM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: schema export complete
Oct 25, 2012 11:00:48 AM org.hibernate.impl.SessionFactoryImpl checkNamedQueries
INFO: Checking 0 named queries
11:00:48,236 INFO HibernateTest:32 - before save or update
Hibernate: insert into CE_ITEM (ITEM_AMOUNT, ITEM_NAME, CREATED_DATE, MODIFIED_DATE, ITEM_ID) values (?, ?, ?, ?, ?)
Hibernate: insert into CE_ITEM_IMAGES (ITEM_ID, IMAGE_FILE) values (?, ?)
Oct 25, 2012 11:00:48 AM org.hibernate.impl.SessionFactoryImpl close
INFO: closing

Mapping an identifier bag :

This is used to map an unordered collection that allows duplicates element in collection. here, only we have to change two things: one is , change in item class, replace set of collection to Collection interface and initialise it with Array List and other is, change in XML mapping meta data, see the updates XML mapping file.

<hibernate-mapping package="mapping.a.set" default-access="property">
    
    <class name="Item" table="ITEM" dynamic-insert="true" dynamic-update="true">
<id name="itemId" column="ITEM_ID">
<generator class="increment"/>
</id>
<property name="itemAmount" column="ITEM_AMOUNT"/>
<property name="itemName" column="ITEM_NAME"/>
<property name="createdDate" column="CREATED_DATE"/>
<property name="modifiedDate" column="MODIFIED_DATE"/>
<bag name="images" table="ITEM_IMAGES">
<key column="ITEM_ID" />
<element column="IMAGE_FILE" not-null="true" type="string"/>
</bag>
</class>
</hibernate-mapping>

Now you can save multiple images for one item in the database but it do not have ordering of images for one item.

Mapping a list :

This is used to map an ordered collection that allows duplicates element in collection. here, only we have to change two things: one is , change in item class, replace set of collection to List interface and initialise it with Array List and other is, change in XML mapping meta data, see the updates XML mapping file.

<hibernate-mapping package="mapping.a.set" default-access="property">
    
    <class name="Item" table="ITEM" dynamic-insert="true" dynamic-update="true">
<id name="itemId" column="ITEM_ID">
<generator class="increment"/>
</id>
<property name="itemAmount" column="ITEM_AMOUNT"/>
<property name="itemName" column="ITEM_NAME"/>
<property name="createdDate" column="CREATED_DATE"/>
<property name="modifiedDate" column="MODIFIED_DATE"/>
<list name="images" table="ITEM_IMAGES"> <key column="ITEM_ID"/> 
                       <!--<index  column="ITEM_INDEX" type="string"/>-->
                       <list-index column="ITEM_INDEX"/> <element column="IMAGE_FILE" not-null="true"              
                        type="string"/>
              </list>
</class>
</hibernate-mapping>

Now you can save multiple images for one item in the database, ordering is maintained by ITEM_INDEX column in the ITEM_IMAGE table. indexing starts with 0. you can change it with <list-index base="1"> element in your mapping file.
Note: hibernate add null elements to your java.util.list if index number in the database are not continuous.

Mapping a map :


This is used to map an un ordered collection that allows duplicates element in collection. here, only we have to change two things: one is , change in item class, replace set of collection to Map interface and initialise it with Hash Map and other is, change in XML mapping meta data, see the updates XML mapping file.

<hibernate-mapping package="mapping.a.set" default-access="property">
    
    <class name="Item" table="ITEM" dynamic-insert="true" dynamic-update="true">
<id name="itemId" column="ITEM_ID">
<generator class="increment"/>
</id>
<property name="itemAmount" column="ITEM_AMOUNT"/>
<property name="itemName" column="ITEM_NAME"/>
<property name="createdDate" column="CREATED_DATE"/>
<property name="modifiedDate" column="MODIFIED_DATE"/>
<map name="images" table="ITEM_IMAGES"> 
                      <key column="itemId"/>
                      <map-key column="IMAGE_NAME" type="string" />
                      <element column="IMAGE_FILE" type="string" not-null="true"/> 
               </map>
</class>
</hibernate-mapping>