W dzisiejszym poście zaprezentujemy jak stworzyć projekt, który może stanowić wejście dla przyszłych projektów wykorzystujących Hibernate oraz Mavena. Do zamockowania bazy danych posłużymy się wbudowaną (embeded) bazą danych – Derby.
##Nowy projekt
Nalezy utworzyć nowy projekt za pomoca polecenia:
mvn -DarchetypeGroupId=org.apache.maven.archetypes
-DarchetypeArtifactId=maven-archetype-quickstart
-DarchetypeVersion=1.1
-DarchetypeRepository=http://repo1.maven.org/maven2
-DgroupId=pl.xperios
-DartifactId=HibernateMavenStarter
-Dversion=1.0-SNAPSHOT
-Dpackage=pl.xperios.HibernateMavenStarter
-Dbasedir=C:\\Projects\\Starters
-Darchetype.interactive=false –batch-mode archetype:generate
##Konfiguracja zależności
Po stworzeniu struktury projektu należy dodać zależności Hibernate. Ponieważ nie występują w repozytorium centralnym najpierw należy dodać odpowiednie repozytoria do pliku pom.xml:
<repositories>
<repository>
<id>sonatype-snapshots</id>
<name>Sonatype Snapshots</name>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<url>http://download.java.net/maven/2/</url>
<id>download.java.net</id>
<layout>default</layout>
<name>Hibernate support</name>
</repository>
</repositories>
Od tej pory do projektu możemy dołączać również zależności, które nie znajdują się w repozytorium centralnym:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.5.6</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate</artifactId>
<version>3.2.5.ga</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>3.3.2.GA</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.1.0.Final</version>
</dependency>
<dependency>
<groupId>javax.sql</groupId>
<artifactId>jdbc-stdext</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>jta</artifactId>
<version>1.0.1B</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>ejb3-persistence</artifactId>
<version>1.0.1.GA</version>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derbyclient</artifactId>
<version>10.8.1.2</version>
</dependency>
</dependencies>
Po zapisaniu projektu i pierwszej kompilacji zostaną pobrane zależności do lokalnego repozytorium. W tym celu należy wydać polecenie:
mvn clean install
##Klasa pomocnicza HibernateUtil
Pracę zaczynamy od stworzenia specjalnej klasy narzędziowej, która inicjuje konfigurację oraz pozwala na dostęp do usług Hibernate poprzez metody statyczne:
package pl.xperios.hibernatestarter;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.SessionFactory;
public class HibernateUtil {
private static final SessionFactory sessionFactory;
static {
try {
sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
} catch (Throwable ex) {
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}
##Konfiguracja Hibernate
Powyższa klasa inicjuje konfigurację opartą na anotacjach a następnie odczytuje konfiguracje z jednego z możliwych źródeł. My posłużymy się plikiem konfiguracyjnym zawartym w pliku xml. W tym celu należy stworzyć plik hibernate.cfg.xml w folderze src/main/resources o następującej treści:
<?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.DerbyDialect</property>
<property name="hibernate.connection.driver_class">org.apache.derby.jdbc.ClientDriver</property>
<property name="hibernate.connection.url">jdbc:derby://localhost:1527/sample</property>
<property name="hibernate.connection.username">app</property>
<property name="hibernate.connection.password">app</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.hbm2ddl.auto">create-drop</property>
<property name="hibernate.current_session_context_class">thread</property>
<property name="hibernate.transaction.auto_close_session">true</property>
</session-factory>
</hibernate-configuration>
Powyższy plik definiuje między innymi:
- połączenie z bazą danych:
- sterownik
hibernate.connection.driver_class
- url
hibernate.connection.url
- login
hibernate.connection.username
- hasło
hibernate.connection.password
- dialekt
hibernate.dialect
- pokazywanie w konsoli wykonywanych zapytań do bazy
hibernate.show_sql
- kontekst aplikacji
hibernate.current_session_context_class
- automatyczne zamykanie transakcji
hibernate.transaction.auto_close_session
, które upraszcza obsługę transakcji - strategia zarządzania strukturą w bazie danych
hibernate.hbm2ddl.auto
#Tworzenie pierwszej encji
W celu przetestowania poprawności konfiguracji stworzymy i zarejestrujemy prostą encję użytkownika naszej aplikacji. W tym celu stworzymy prostą klasę encji:
package pl.xperios.hibernatestarter.model;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class UserData implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
Long userId;
String name;
String fullName;
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
@Override
public String toString() {
return "UserData{" + "userId=" + userId + ", name=" + name + ", fullName=" + fullName + '}';
}
}
Powyższa encja została oznaczona za pomocą anotacji @Entity
, dzięki czemu Hibernate będzie stworzononą klasę traktował jako encję.
niektóre właściwości również posiadają anotacje i tak pole userId zostało opatrzone anotacją ID, które przekłada się na to że pole to traktowane jest jako klucz główny wraz ze strategią generowania identyfikatorów w sposób automatyczny.
Powyższą encję należy zarejestrować w pliku konfiguracyjnym Hibernate (hibernate.cfg.xml
):
...
<property name="hibernate.transaction.auto_close_session">true</property>
<mapping class="pl.xperios.hibernatestarter.model.UserData"/>
</session-factory>
...
##Test
Mając wszystkie elementy tworzymy test, który doda parę rekordów do bazy a następnie pobierze je i wyświetli w konsoli:
package pl.xperios.hibernatestarter;
import java.util.List;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.hibernate.Transaction;
import org.hibernate.classic.Session;
import pl.xperios.hibernatestarter.HibernateUtil;
import pl.xperios.hibernatestarter.model.UserData;
public class AppTest extends TestCase {
public AppTest(String testName) {
super(testName);
}
public static Test suite() {
return new TestSuite(AppTest.class);
}
public void testApp() {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
Transaction transaction = session.beginTransaction();
UserData data = new UserData();
data.setFullName("FullName1");
data.setName("Name1");
session.save(data);
data = new UserData();
data.setFullName("FullName2");
data.setName("Name3");
session.save(data);
transaction.commit();
session = HibernateUtil.getSessionFactory().getCurrentSession();
transaction = session.beginTransaction();
List output = session.createCriteria(UserData.class).list();
System.out.println("Size: " + output.size());
System.out.println("Size: " + output);
transaction.commit();
}
}
W konsoli powinno zostać wyświetlony następujący wynik:
Hibernate: insert into UserData (fullName, name, userId) values (?, ?, ?)
Hibernate: insert into UserData (fullName, name, userId) values (?, ?, ?)
Hibernate: select this_.userId as userId0_0_, this_.fullName as fullName0_0_, this_.name as name0_0_ from UserData this_
Size: 2
Size: [UserData{userId=1, name=Name1, fullName=FullName1}, UserData{userId=2, name=Name3, fullName=FullName2}]