Tag Archives: mysql

Unit Testing Using In-Memory MySQL Database On Spring

Well the title lied, there’s no such thing as in-memory MySQL database (or at least I won’t be using it for this article). Instead I will use H2 in-memory database setup to run in “MySQL mode”


  
  

(thanks to joensson for sharing this technique on SO)

If your app just uses plain jdbc then adding above datasource to your test context would be sufficient, but if you use JPA/Hibernate the cost of table setup, scanning etc could be quite significant.

To overcome this you can split the test context using y annotation.

In the example below I have unit tests for two DAOs: AccountDAOTest and CustomerDAOTest:

y({
  ation("/test-root-context.xml"),
  ation("AccountDAOTest-context.xml")
})
(SpringJUnit4ClassRunner.class)
public class AccountDAOTest {
}
y({
  ation("/test-root-context.xml"),
  ation("CustomerDAOTest-context.xml")
})
(SpringJUnit4ClassRunner.class)
public class CustomerDAOTest {
}

By doing this Spring test-root-context.xml will be setup once and reused accross all unit tests. Only put components common to all tests in test-root-context.xml. In my case I put the following:

  • DataSource
  • EntityManagerFactory
  • TransactionManager


  
  





  
  




  

All test specific components go into their respective context.

Don’t forget to add if your DAO uses it. This can’t be placed on test-root-context.xml because I don’t scan all my DAOs there.

And lastly — ofcourse — you need to make sure your pom.xml has dependency to spring-test, junit and h2



  com.h2database
  h2
  1.3.176
  test



  org.springframework
  spring-test
  ${org.springframework-version}
  test



  junit
  junit
  4.7
  test

Creating a Minimal Spring MVC, JPA / Hibernate and MySQL Project

The goal of this article is to create a bare minimum Spring MVC project with JPA (with Hibernate provider) as persistence provider and MySQL as the DBMS. To test everything works I’ll also add a form page allowing you to list all entities and add a new one.

Environment:

  • jdk 6
  • Spring 3.2.8.RELEASE
  • Hibernate 4.3.3.Final
  • STS 3.4.0.RELEASE
  • MySQL database running on localhost port 3306. The database name is hello with username root and no password.

Steps:

  1. From STS, create a new Maven Project. Since we’re starting from scratch, tick Create a simple project (skip archetype selection). Hit Next.
    jpaminimal0
  2. On the next New Maven Project dialog that comes up, give it a group id, artifact id and set the packaging to war. A minimal maven project will be setup for you when you hit Finish
  3. The default maven project is setup to use jdk 1.5, to switch it to 1.6, open pom.xml and add following xml section under the element.
    
      
        
          maven-compiler-plugin
          
            1.6
            1.6
          
        
      
    
    

    Right click the project on Package Explorer -> Maven -> Update Project.. once this is done to update the eclipse build path into jdk 1.6

  4. Add maven dependencies for Spring, JPA, Hibernate, Java EE, MySQL and other supporting jars. Again this goes to your pom.xml

    
      
      
        org.springframework
        spring-context
        3.2.8.RELEASE
      
    
      
        org.springframework
        spring-webmvc
        3.2.8.RELEASE
      
    
      
        org.springframework
        spring-orm
        3.2.8.RELEASE
      
    
      
      
        org.hibernate
        hibernate-core
        4.3.3.Final
      
    
      
        org.hibernate
        hibernate-entitymanager
        4.3.3.Final
      
    
      
      
        javax.servlet
        servlet-api
        2.5
        provided
      
    
      
        javax.servlet.jsp
        jsp-api
        2.1
        provided
      
    
      
        javax.servlet
        jstl
        1.2
      
    
      
      
        mysql
        mysql-connector-java
        5.1.29
      
    
      
        commons-dbcp
        commons-dbcp
        1.4
      
    
      
        xerces
        xercesImpl
        2.11.0
      
    
    
  5. Create the web deployment descriptor src/main/webapp/WEB-INF/web.xml. We will setup Spring MVC here with bean context configuration xml file set to /WEB-INF/spring-context.xml
    
    
      
      
        appServlet
        org.springframework.web.servlet.DispatcherServlet
        
          contextConfigLocation
          /WEB-INF/spring-context.xml
        
        1
      
      
      
        appServlet
        /
      
    
    
  6. Create a Spring Bean Configuration File placed on src/main/webapp/spring-context.xml. There are plenty important setups here including annotation-based MVC controller, view resolver, transaction config, data source, entityManagerFactory and transaction manager.
    
    
    
      
      
      
      
      
      
      
      
        
        
      
      
      
      
        
        
        
        
      
      
      
      
        
        
      
      
      
      
        
      
      
      
      
    
    
    
  7. Create src/main/resources/META-INF/persistence.xml. This is the persistence unit configuration. It tells JPA what provider will be used, persistence unit type and hibernate configs.
    
    
    
      org.hibernate.ejb.HibernatePersistence
        
            
            
            
            
        
      
    
    
  8. Create a simple entity class to test our setup. Let’s call this entity Person. It has an id and name field.

    package hello;
    
    
    (name = "person")
    public class Person {
    
      @Id
      
      private int id;
    
      private String name;
      
      /* getters & setters */
    
    }
    
  9. And setup mysql database and table to store this entity. The table columns correspond to the Person class fields above. Also note we inform JPA of mysql AUTO_INCREMENT by using annotation:

    CREATE DATABASE IF NOT EXISTS hello;
    
    USE hello;
    
    CREATE TABLE person (
      id INT PRIMARY KEY AUTO_INCREMENT,
      name VARCHAR(50)
    );
    
  10. Create a simple service to list all and add a Person entity

    package hello;
    
    
    public class PersonService {
      
      // An EntityManager will be automatically injected from EntityManagerFactory setup on
      // spring-context.xml
      ext
      private EntityManager em;
      
      // Since we've setup  and transaction manager on spring-context.xml,
      // any bean method annotated with  will cause Spring to magically call
      // begin() and commit() at the start/end of the method. If exception occurs it will also
      // call rollback()
      
      public List getAll() {
        List result = em.createQuery("SELECT p FROM Person p", Person.class).getResultList();
        return result;
      }
      
      
      public void add(Person p) {
        em.persist(p);
      }
    }
    
  11. Create a HomeController class to map HTTP requests. The package name I used is hello:
    package hello;
    
    
    ("/")
    public class HomeController {
    
       private PersonService personSvc;
      
      /**
       * Requests to http://localhost:8080/hello will be mapped here.
       * Everytime invoked, we pass list of all persons to view
       */
      (method = RequestMethod.GET)
      public String listAll(Model model) {
        model.addAttribute("persons", personSvc.getAll());
        return "home";
      }
      
      /**
       * POST requests to http://localhost:8080/hello/addPerson goes here.
       * The new person data is passed from HTML from and bound into the
       * Person object.
       */
      (value = "/addPerson", method = RequestMethod.POST)
      public String addPerson( Person person) {
        personSvc.add(person);
        return "redirect:/";
      }
    }
    
  12. Finally add the form jsp file located on src/main/webapp/WEB-INF/home.jsp
    <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    
    
    
    
    Hello
    
    
      

    All Persons

    Id: ${p.id} Name: ${p.name}

    Add New

    Name:

    This is a simple form which will list all persons and allow you to add one

    Screen Shot 2014-03-03 at 9.51.39 pm

Check Out The Source

You can browse / clone the source code of this article on github. To run this on STS:

  1. Clone it using git
    git clone :gerrytan/jpaminimal.git
  2. On STS, do File > Import > Existing Maven Projects
  3. Create run configuration (Run > Run Configurations…) like this
    mvn-run-config
  4. Make sure the project is selected on the project explorer and run it. This will fire up in-memory tomcat7 server at http://localhost:8080

Backing Up and Restoring MySQL Database Using mysqldump

Although not always the most efficient, mysqldump is a handy way to migrate your MySQL server — particularly if you don’t have many schemas and the size of data is small.

To create backup, first list all schemas on the server using

SHOW DATABASES;

I normally avoid backing up performance_schema, information_schema and mysql schema. They contain database configuration, user settings etc. This would mean you have to reconfigure all your settings on the new server

Then take the dump of all schema using this command:

mysqldump -u***** -p***** --databases  > mybackup_20131107_1223.sql

Then compress, transfer and inflate the sql file into the new server’s host. When you’re ready to restore, just do

mysql -u***** -p***** < mybackup_20131107_1223.sql

VirtualBox, Ubuntu and LAMP Stack

Came accross VirtualBox, a free & excellent virtual machine software. I decided to take it for a spin creating a Ubuntu virtual machine LAMP stack on it..

Here We Go

  1. Download and install VirtualBox
  2. Download latest Ubuntu iso installation file
  3. From VirtualBox create a new Virtual Machine. Select type: Linux and version: Ubuntu. On the next step you will be prompted with dvd drive containing the installaion disk, but instead just select the iso downloaded on step 2
  4. Go through the Ubuntu installation steps
  5. It’s also very helpful to install ssh server so you can ssh into your VM later on: sudo apt-get install openssh-server

Voila! You have ubuntu running on your Windows PC

Host and Guest

In virtualization realm, host indicates your physical PC (Windows 7 in my case), and guest is the virtual machine (Ubuntu). Most of virtual machine software documentation uses host and guest terminology heavily so make sure you’re familiar with it

Networking

This is where things get tricky. Virtual machine comes with virtual network adapters, and you have to do few configuration to setup connectivity between your virtual and physical adapters.

By default VirtualBox allows the guest machine to connect to the internet through NAT, so you can download data, browse internet etc. However if you want to run servers from the guest, it won’t be discoverable by the host or other PC in the host’s network immediately.

One approach to make them discoverable is by setting up port forwarding. You get here by going to networking section on the machine’s setting on Virtual Box

portforwarding

Note that setting port forwarding requires the port is actually free on your host machine. Hence I find it very useful to add an IP to your host’s network interface specifically for the VM so you don’t have port conflicts. In this example I added the IP on my interface:

addip

The “AMP”

So there’s the “L – Linux” done. Now for the Apache, Mysql and Php, it can simply be done by using Ubuntu’s apt-get package manager:

  1. Open a terminal / SSH session to your Ubuntu machine
  2. Elevate into root using sudo su root
  3. apt-get install apache2
  4. apt-get install php5
  5. apt-get install mysql-server mysql-client

Few helpful notes:

  • Default doc root is /var/www
  • To start / stop apache: sudo service apache2 stopsudo service apache2 start
  • To start / stop mysql: sudo service mysql stop / sudo service mysql start

Tomcat 7 JDBC Session Persistence

The default Tomcat session management strategy is in-memory session persisted into file when the server is shutdown gracefully. If the server dies in a cold fashion (eg: kill -9 or power outage), session data might be lost. One approach to mitigate this is to store session data into database using JDBC, aka JDBC Session Persistence.

JDBC Session Persistence can also aid load balancer failover scenario. I’d say this is an alternative to setting up (often cumbersome) TCP session replication. Note that if you have multiple cloud servers like Amazon EC2 it doesn’t come with TCP multicast feature — TCP session replication sounds like a nightmare to setup.

The Steps

  1. Ensure org.apache.catalina.session.StandardSession.ACTIVITY_CHECK or org.apache.catalina.STRICT_SERVLET_COMPLIANCE is set to true. Add line similar to following into your Tomcat’s startup.sh (if you’re on UNIX)
    export CATALINA_OPTS="-Dorg.apache.catalina.session.StandardSession.ACTIVITY_CHECK=true"

    Tomcat System Property Reference will explain what do each property means if you’re curious

  2. Create following SQL table (yes you need a database to store the session data)
    create table tomcat_sessions (
      session_id     varchar(100) not null primary key,
      valid_session  char(1) not null,
      max_inactive   int not null,
      last_access    bigint not null,
      app_name       varchar(255),
      session_data   mediumblob,
      KEY kapp_name(app_name)
    );
    
  3. Place a copy of mysql-connector-java.jar (or your DB’s JDBC driver) into $CATALINA_HOME/lib
  4. In your web app, add a META-INF/context.xml file. If you use standard maven layout you have to place it on src/main/webapp/META-INF/context.xml. You can copy the file from $CATALINA_HOME/conf/context.xml as a starting point. Then under element add following element
    
      
    
    

    Notice how the SQL column name corresponds to some of the settings above. In this configuration I used mysql database on localhost with database name “mytomcat” and username “root”. maxIdleBackup=”10″ specifies number of seconds before the in-memory session data is persisted into database.

    There are many other settings you can tweak, have a look at the Tomcat Manager Component Reference.

Fine Prints

This article is tested against Tomcat 7.0.39 but I guess it should also work with Tomcat 6. If you’ve jumped the ship from relational to MongoDB, . I haven’t got a chance to try it but it looks awesome.

Hibernate One To Many Relationship

Continuing from my post Spring MVC + Hibernate + MySQL Quick Start From Scratch, here is how to setup one to many relationship on Hibernate.

Let’s assume you want to add a new table called topping, each pizza can have several toppings (one to many relationship).

Pizza table
pizzatable

Topping table
topping table

First code the Topping entity class:


(name = "topping")
public class Topping {
  @Id
  
  private long id;
  
  private String name;
  
  
  (name = "pizza_id", referencedColumnName = "id")
  private Pizza pizza;

  // getters & setters..
}

Notice the usage of and annotation. This allows the owning Pizza to be queried from the Topping. This also says “in order to find pizza that owns this topping, have a look at pizza_id column on topping table, match it with id column on pizza table”

And let’s have a look at our modified Pizza entity class:


(name = "pizza")
public class Pizza {
  @Id  private long id;
  private String name;
  private double price;
  
  (mappedBy = "pizza", fetch = FetchType.LAZY)
  private List toppings;

  // getters & setters
}

This setups a bi-directional relationship where you can obtain list of toppings from a Pizza object, and the owning Pizza from a Topping object. The mappedBy attribute refers to the java property name of Pizza reference on the Topping class.

The FetchType.LAZY setting tells Hibernate not to bother populating the toppings unless we ask it to (this is handy to conserve memory if you have a long chains of relationships with thousands of objects on it).

Next if I want to list my pizzas with its topping, I can write following method on my DAO class:


public List findAllWithToppings() {
  Session session = sessionFactory.getCurrentSession();
  List pizzas = session.createQuery("select distinct p from Pizza as p left join fetch p.toppings").list();
  return pizzas;
}

The above hibernate query will roughly translate into following SQL:

select * from pizza p left outer join topping t on p.id = t.pizza_id;

Download the source code

git clone https:///gerrytan/pizzashop.git -b one_to_many

Spring MVC + Hibernate + MySQL Quick Start From Scratch

This is a tutorial to build a very simple pizzashop Spring MVC, Hibernate and MySQL application. The main page shows all pizza rows stored on a database table:

03

Technology in Java world moves very fast. Using straight Hibernate might no longer be preferable since Java EE 5 introduces JPA (Java Persistence API) but it’s still good to learn anyway. Spring MVC and Hibernate is one of the most popular Java libraries used out there.

Tools / Environment Required
If you’re just starting fresh and don’t have most of the tools below just install JDK, STS (Springsource Tools Suite) and MySQL server, everything else is bundled within them.

Project Setup and Boilerplate

  1. First, create new Maven project on STS. Skip archetype selection. Pick maven group id, artifact id and select packaging to war.01 02

  2. By default Maven will use JDK 1.5, re-configure it to use 1.6. Add following maven-compiler-plugin section to pom.xml under element. Ensure the change takes effect by updating maven project settings (right click on project -> Maven -> Update project…).
    
      
        
          org.apache.maven.plugins
          maven-compiler-plugin
          3.1
          
            1.6
            1.6
          
        
      
    
    

  3. Add Spring, Hibernate, Java EE and MySQL maven dependencies to pom.xml. Place following under element.
    
      3.2.3.RELEASE
      4.2.2.Final
    
    
    
      
      
        org.springframework
        spring-context
        ${spring.version}
      
      
        org.springframework
        spring-webmvc
        ${spring.version}
      
      
        org.springframework
        spring-orm
        ${spring.version}
      
      
      
      
        org.hibernate
        hibernate-core
        ${hibernate.version}
      
      
      
      
        javax.servlet
        servlet-api
        2.5
        provided
      
      
        jstl
        jstl
        1.2
      
      
      
      
        commons-dbcp
        commons-dbcp
        1.4
      
      
        mysql
        mysql-connector-java
        5.1.25
      
      
    
    

  4. Create a web.xml descriptor file with Spring MVC servlet setup on it, place it on src/main/webapp/WEB-INF
    
    
    
      
        appServlet
        org.springframework.web.servlet.DispatcherServlet
        
          contextConfigLocation
          /WEB-INF/servlet-context.xml
        
        1
      
       
      
        appServlet
        /
      
      
    
    

  5. Create src/main/webapp/WEB-INF/servlet-context.xml Spring bean config file for dispatcher servlet. We configure few important stuffs in here:
    
    
    
      
      
    
      
      
        
        
      
      
      
      
      
      
      
        
        
        
        
        
      
      
      
      
        
        
          
            com.gerrytan.pizzashop
          
        
        
          
            hibernate.dialect=org.hibernate.dialect.MySQLDialect
          
        
      
      
      
      
        
      
      
      
      
    
    
    


The Business Functionality

  1. Now all the boilerplate code done, we can start coding the business functionality. For this simple app we will have a pizza database table with just id, name and price column. Create the Pizza entity class representing the table
    package com.gerrytan.pizzashop;
    // imports ..
    
    
    (name = "pizza")
    public class Pizza {
      @Id  private long id;
      private String name;
      private double price;
      /* getters & setters */
    }
    

  2. Create a DAO class to obtain Pizza entity persisted on database. Note that we won’t create service layer classes for the sake of simplicity (on real-life complex business application adding service layer is a good practice).
    package com.gerrytan.pizzashop;
    // imports..
    
    
    s({"unchecked", "rawtypes"})
    public class PizzaDAO {
       private SessionFactory sessionFactory;
      
      /**
       *  annotation below will trigger Spring Hibernate transaction manager to automatically create
       * a hibernate session. See src/main/webapp/WEB-INF/servlet-context.xml
       */
      
      public List findAll() {
        Session session = sessionFactory.getCurrentSession();
        List pizzas = session.createQuery("from Pizza").list();
        return pizzas;
      }
    }
    

  3. Create a Spring MVC controller to handle request from the main page. Note that PizzaDAO reference is injected, and after collection of Pizza entity objects are obtained it’s passed to the view using Model object.
    package com.gerrytan.pizzashop;
    // imports..
    
    
    ("/")
    public class PizzaController {
      
       private PizzaDAO pizzaDAO;
      
      /**
       * This handler method is invoked when
       * http://localhost:8080/pizzashop is requested.
       * The method returns view name "index"
       * which will be resolved into /WEB-INF/index.jsp.
       *  See src/main/webapp/WEB-INF/servlet-context.xml
       */
      (method = RequestMethod.GET)
      public String list(Model model) {
        List pizzas = pizzaDAO.findAll();
        model.addAttribute("pizzas", pizzas);
        return "index";
      }
    }
    

  4. Add a JSP view to list all the pizza entities passed by the controller
    src/main/webapp/WEB-INF/index.jsp

    <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    
    
    
    
    Pizzashop
    
    
            

    List of All Pizzas

    • ${p.id} - ${p.name} - ${p.price}

  5. And finally prepare MySQL pizzashop database schema:
    CREATE SCHEMA `pizzashop`;

    And pizza table:

    CREATE  TABLE `pizzashop`.`pizza` (
      `id` BIGINT NOT NULL AUTO_INCREMENT ,
      `name` VARCHAR(45) NULL ,
      `price` DOUBLE NULL ,
      PRIMARY KEY (`id`) );
    

    And insert some data into it

    INSERT INTO `pizzashop`.`pizza` (`id`, `name`, `price`) VALUES ('I', 'Italian', '7.5');
    INSERT INTO `pizzashop`.`pizza` (`id`, `name`, `price`) VALUES ('2', 'Thin Crust', '6');
    INSERT INTO `pizzashop`.`pizza` (`id`, `name`, `price`) VALUES ('3', 'Pepperoni', '6.2');
    

    It is assumed you have MySQL server running on your local machine (localhost) on the default port 3306. The name of the schema is pizzashop and table pizza. Have a look at Spring beans configuration section above to reconfigure this.

Running The Code

  1. The easiest way to run your code is using in-memory Maven Tomcat plugin. It will launch on-the-fly Tomcat server with your code deployed. Make sure your project is selected on the project exploded and setup a maven run configuration on STS. Go to Run -> Run Configurations.. and create a new maven build entry like this:
    maven goal
  2. Click Run and navigate your browser to http://localhost:8080/pizzashop

Download The Source Code

Source code for this demonstration can be obtained using git:

git clone https://bitbucket.org/gerrytan/pizzashop.git -b basic

Congratz!

Well done on making it this far. Hopefully that was a quick and nice introduction to Spring MVC + Hibernate + MySQL and you can see how the tedious database to java class mapping is now simplified. You might have lots of questions in your mind by now — feel free to ask in the comment section below. Following are few official references and community article links you can browse around:

See Also