Wednesday, November 6, 2013

A quick introduction to Hibernate using Maven

Create the project

  1. Run mvn archetype:generate
  2. Select default archetype (maven-archetype-quickstart)
  3. Select the latest version of the archetype (1.1 at the time of making this tuto)
  4. Enter the groupId (I’ll use com.mycompany).
  5. Enter the artifactId (I’ll use hibernate-basic).
  6. Leave the default version (1.0-SNAPSHOT for me).
  7. Leave the default package (same as groupId).
  8. Confirm properties.
  9. Run cd hibernate-basic.


You will end up with the following project structure:


Import into eclipse

  1. Go to File –> Import and select Existing Maven Projects:
    Note: do NOT run the command mvn eclipse:eclipse
  2. Select the root directory of your Maven project:
  3. Hit Finish.
  4. You’ll get a nice looking project: 

Add dependencies

  1. Open your pom file and add these two dependencies:
    <dependency>
     <groupId>org.hibernate</groupId>
     <artifactId>hibernate-entitymanager</artifactId>
     <version>4.2.7.Final</version>
    </dependency>
    <dependency>
     <groupId>com.h2database</groupId>
     <artifactId>h2</artifactId>
     <version>1.2.145</version>
    </dependency>
    We’ll need the hibernate-entitymanager library to be able to use hibernate in our project (EntityManagerFactory, EntityManager, annotations, etc). It depends on other libraries such as hibernate-core and hibernate-commons-annotations, but Maven will automatically handle that for us.
    The h2 library will give us the ability to persist our entities to an in-memory database called H2.
  2. We need to create the folder src/main/resources/META-INF, since it will hold our JPA persistence descriptor:

Add persistence.xml

  1. Right click your META-INF folder and add a new XML file called persistence.xml:
  2. Copy the following code into persistence.xml:
    <persistence xmlns="http://java.sun.com/xml/ns/persistence"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
     version="2.0">
    
     <persistence-unit name="myPersistenceUnit">
      <description>My persistence unit</description>
    
      <class>com.mycompany.Employee</class>
    
      <properties>
        <property name="javax.persistence.jdbc.driver" value="org.h2.Driver" />
       <property name="javax.persistence.jdbc.url" value="jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE" />
       <property name="javax.persistence.jdbc.user" value="sa" />
       <property name="javax.persistence.jdbc.password" value="" />
    
       <property name="hibernate.show_sql" value="false" />
       <property name="hibernate.hbm2ddl.auto" value="create" />
      </properties>
    
     </persistence-unit>
    
    </persistence>
  3. You can give the persistence-unit any name you want, but take note of it. In our case it is myPersistenceUnit.
  4. Give it a description.
  5. The class section tells hibernate which class (or classes) we want to persist. Right now we still haven’t created this class, but that will be our next step.

Add an entity

  1. Add a class called Employee to the package com.mycompany
  2. Give the class 3 private properties, and generate their respective getters and setters:
    • id : long
    • name : String
    • age : int
  3. We have two ways of mapping our Employee class to the database.
    • The hibernate-specific way is using a mapping file for each persisted class, named <class-name>.hbm.xml, in our case it would be Employee.hbm.xml. There is also the posibility to use one single mapping file for all the persisted classes.
    • The JPA compliant way is using annotations inside each of our classes.
    We will go with the JPA compliant option.
  4. Add the following annotations to the class definition:
    @Entity
    @Table (name = "employees")
  5. Add the following annotations to the getId() method:
    @Id
    @GeneratedValue(generator="increment")
    @GenericGenerator(name="increment", strategy = "increment")
  6. For our annotations to work, we need to import the following libraries:
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    import javax.persistence.Table;
    
    import org.hibernate.annotations.GenericGenerator;
    employee annotations
  7. Let’s add two constructors to our Employee class: a default one, required by hibernate, and one for us to use:
    public Employee(){
    }
    
    public Employee(String name, int age){
     this.name = name;
     this.age = age;
    }

Test

  1. Add the following code inside the main method of our App class:
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("myPersistenceUnit");
    EntityManager em = emf.createEntityManager();
    em.getTransaction().begin();
    em.persist(new Employee("John Doe", 24));
    em.persist(new Employee("Homer Simpson", 43));
    em.getTransaction().commit();
    
    em.getTransaction().begin();
      List<Employee> result = em.createQuery( "from Employee", Employee.class ).getResultList();
    for (Employee employee : result) {
     System.out.println( "Employee " + employee.getName() + " is " + employee.getAge() );
    }
    em.getTransaction().commit();
    em.close();
    Note: The method Persistence.createEntityManagerFactory() should receive the name of the persistence unit we specified in our persistence.xml.
  2. We need to import the following libraries:
    import java.util.List;
    
    import javax.persistence.EntityManager;
    import javax.persistence.EntityManagerFactory;
    import javax.persistence.Persistence;
  3. We have 3 ways or running our app:
    1. Right click App.java and select Run As –> Java Application:

    1. In a command prompt, go to the root of our project and run:
      mvn compile
      mvn exec:java -Dexec.mainClass="com.mycompany.App"
    2. In a command prompt, go to the root of our project and run:
      mvn dependency:copy-dependencies
      mvn compile
      java -cp target\classes;target\dependency\* com.mycompany.App
      Note: mvn dependency:copy-dependencies will copy all the required jars inside target\dependency.
    Note: If you want to get rid of all that output hibernate produces, turn of the logging level by importing java.util.logging.Level and adding this at the beggining of our main method:
    java.util.logging.Logger.getLogger("org.hibernate").setLevel(Level.OFF);

Tuesday, November 5, 2013

A quick introduction to Maven

What is Maven?

Not very long ago, when you had to compile your single-file project you only had to:
 gcc hello.c -o hello
 ./hello
That was easy, but when you had to compile a big project that included lots of libraries and lots of source files under different directories, it could become quite a headache.
So the all-shiny Make came into existence, to keep track of all those source files, under their respective directory and give you an easy way to recompile outdated source files and generate your program. It used a text file, commonly named makefile, to specify all your project’s stuff. Example makefile:
 all: hello  

 hello: main.o factorial.o hello.o
  g++ main.o factorial.o hello.o -o hello

 main.o: main.cpp
  g++ -c main.cpp

 factorial.o: factorial.cpp
  g++ -c factorial.cpp

 hello.o: hello.cpp
  g++ -c hello.cpp

 clean:
  rm -rf *o hello
you just had to run:
 make
 ./hello
and voilĂ , Make compiled all your sources and created your executable file. You could also run single tasks specifying them after the make command:
 make hello
 make clean
and Make would search for your desired task and execure all its steps. For example, with the previous makefile, if you run make clean Make would run rm -rf *o hello.
But it still had some problems. If you had a java project, Make would run a javac command for each .java file, which would make it quite slow for big projects. It would do:
 javac Class1.java
 javac Class2.java
 javac Class3.java
 ...
instead of the more resource-efficient:
 javac Class1.java Class2.java Class3.java
So Maven came into existence, which would solve problems like this and add some other nice features, like dependency management and project management. We’ll get into that later.

Setting up Maven on win 7

  • Download maven from here
  • Extract under C:\Program Files\Apache Software Foundation
  • Add the M2_HOME environment variable with the value C:\Program Files\Apache Software Foundation\apache-maven-3.1.1 (change the version number of apache-maven-x.x.x to your own).
  • Add the M2 environment variable with the value %M2_HOME%\bin.
  • Open a new command prompt and run mvn --version to verify your installation:
    C:\Users\user>mvn --version
    Apache Maven 3.1.1 (0728685237757ffbf44136acec0402957f723d9a; 2013-09-17 10:22:22-0500)
    Maven home: C:\Program Files\Apache Software Foundation\apache-maven-3.1.1
    Java version: 1.6.0_35, vendor: Sun Microsystems Inc.
    Java home: C:\Program Files\Java\jdk1.6.0_35\jre
    Default locale: es_CO, platform encoding: Cp1252
    OS name: "windows 7", version: "6.1", arch: "amd64", family: "windows"

Project Management

You can create your project structure using maven:
 mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
This will create the following structure for your project:
 my-app
 |-- pom.xml
 `-- src
     |-- main
     |   `-- java
     |       `-- com
     |           `-- mycompany
     |               `-- app
     |                   `-- App.java
     `-- test
         `-- java
             `-- com
                 `-- mycompany
                     `-- app
                         `-- AppTest.java
and you can run it with:
 cd myapp
 mvn compile
 java -cp target\classes com.mycompany.app.App

Dependency Management

Maven uses the file pom.xml to keep your project configuration and other stuff. It also helps you manage dependencies. No more downloading xxxxx.jar files from many different sites and manually puting them in your project. you can specify a required library in your pom.xlm, by telling maven the groupId, artifactId and version:
 <dependencies>
  <dependency>
   <groupId>junit</groupId>
   <artifactId>junit</artifactId>
   <version>3.8.1</version>
   <scope>test</scope>
  </dependency>
  <dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-entitymanager</artifactId>
   <version>4.2.7.Final</version>
  </dependency>
 </dependencies>
This tells maven to download the required jar files for Junit version 3.8.1 and Hibernate Annotations version 4.2.7.Final and include them in my projects.

Eclipse integration

  1. Go to File –> Import and select Existing Maven Projects:
    Note: You do not need to run the command mvn
     
  2. Select the root directory of your Maven project:
  3. Hit Finish.

Maven archetype:generate

An excelent explanation about the command mvn archetype:generate, found on http://stackoverflow.com/a/8205447/965342:
mvn archetype:generate command is used to create a project from an existing template. There are several archetype’s defined by many developers and project groups. When you run the command, maven does following things:
  1. Downloads maven-archetype-plugin’s latest version.
  2. Lists all archetype’s that can be used to create a project from. If you defined an archetype while calling the command, maven jumps to step 6.
  3. By default, maven chooses maven-archetype-quickstart archetype which basically creates a maven Hello World project with source and test classes. If you want to create a simple project, you can just press enter to continue. If you want to create a specific type of application, you should find the archetype matching your needs and enter the number of that archetype, then press enter. E.g. If you want to create a webapp project, you can enter 155 (this is the current number for this archetype, it can change in time.)
  4. Since archetypes are templates and they intend to reflect current best practices, they can evolve in time, thus they have their own versions. Maven will ask you which version of the archetype you want to use. By default, maven chooses latest version for you. so if you agree to use the latest version of an archetype, just press Enter at this step;
  5. Every maven project (and module) has its groupId, artifactId and version. Maven will then ask these to you in three steps.
  6. Finally, maven will ask you the package structure for your code. A best practice is to create your folder structure that reflects the groupId, thus Maven sets this as default but you are free to change this.
  7. After entering this information, Maven will show you all the information you entered and ask you to verify project creation. If you press Y and then enter, voilĂ  your project is created with the artifact and settings you chose.