Синопсис
В этом посте создадим простое приложение подобное тому, которое было в двух предыдущих постах Hibernate (конфигурация в стиле xml) и Hibernate (конфигурация в стиле аннотации), только теперь хибернейт конфигурироваться будет спрингом. В этом случае у нас сразу уйдут два класса, это HibernateUtil.java так как теперь хибернейтовская сессия будет подниматься спрингом, и фэктори класс Factory.java, так как все dao-классы у нас становятся бинами и, соответственно, мэнэджеться будут спрингом. Описывать проект я здесь не буду, он такой же как в посте Работа с базой данных через JDBC
Проект можно взять с гитхаба: https://github.com/dev-blogs/spring-hibernate
Похожие посты
Структура проекта
spring-hibernate ├──src │ ├─main │ │ └─java │ │ └─com │ │ └─devblogs │ │ ├─dao │ │ │ ├─ItemDao.java │ │ │ ├─ProviderDao.java │ │ │ ├─WarehouseDao.java │ │ │ └─impl │ │ │ ├─ItemDaoImpl.java │ │ │ ├─ProviderDaoImpl.java │ │ │ └─WarehouseDaoImpl.java │ │ └─model │ │ ├─Item.java │ │ ├─Provider.java │ │ └─Warehouse.java │ ├─resources │ │ ├─context.xml │ │ └─scripts │ │ ├─create-data-model.sql │ │ └─fill-database.sql │ └─test │ └─java │ └─com │ └─devblogs │ └─test │ ├─TestItem.java │ ├─TestProvider.java │ └─TestWarehouse.java └──pom.xml
DB скрипты
Скрипты create-data-model.sql и fill-database.sql можно взять в посте Работа с базой данных через JDBC
Так как в этом посте будет встроенная база данных H2, то из тех скриптов нужно будет выкинуть строчки:
CREATE DATABASE warehouse CHARACTER SET utf8; USE warehouse;
из скрипта create-data-model.sql и строчку:
USE warehouse;
из скрипта fill-database.sql
Доменные классы
Item.java
package com.devblogs.model; import java.util.HashSet; import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; import javax.persistence.ManyToOne; import javax.persistence.Table; @Entity @Table(name = "items") public class Item { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "id") private Long id; @Column(name = "name") private String name; @ManyToMany(fetch = FetchType.EAGER, cascade = {CascadeType.ALL}) @JoinTable(name = "items_providers", joinColumns={@JoinColumn(name = "item_id")}, inverseJoinColumns={@JoinColumn(name = "provider_id")}) private Set<Provider> providers = new HashSet<Provider>(); @ManyToOne @JoinColumn(name = "warehouse_id") private Warehouse warehouse; public Item() { } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Set<Provider> getProviders() { return providers; } public void setProviders(Set<Provider> providers) { this.providers = providers; } public Warehouse getWarehouse() { return warehouse; } public void setWarehouse(Warehouse warehouse) { this.warehouse = warehouse; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null || getClass() != obj.getClass()) return false; Item that = (Item) obj; if (!name.equals(that.name)) return false; return true; } @Override public String toString() { return "[id=" + this.id + ", name=" + this.name + "]"; } }
Provider.java
package com.devblogs.model; import java.util.HashSet; import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; import javax.persistence.Table; @Entity @Table(name = "providers") public class Provider { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "id") private Long id; @Column(name = "name") private String name; @ManyToMany(fetch = FetchType.EAGER, cascade = {CascadeType.ALL}) @JoinTable(name = "items_providers", joinColumns={@JoinColumn(name = "provider_id")}, inverseJoinColumns={@JoinColumn(name = "item_id")}) private Set<Item> items = new HashSet<Item>(); public Provider() { } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Set<Item> getItems() { return items; } public void setItems(Set<Item> items) { this.items = items; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null || getClass() != obj.getClass()) return false; Provider that = (Provider) obj; if (!name.equals(that.name)) return false; return true; } @Override public String toString() { return "[id=" + this.id + ", name=" + this.name + "]"; } }
Warehouse.java
package com.devblogs.model; import java.util.HashSet; import java.util.Set; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.OneToMany; import javax.persistence.Table; @Entity @Table(name = "warehouses") public class Warehouse { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "id") private Long id; @Column(name = "address") private String address; @OneToMany(fetch = FetchType.LAZY, mappedBy = "warehouse") private Set<Item> items = new HashSet<Item>(); public Warehouse() { } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public Set<Item> getItems() { return items; } public void setItems(Set<Item> items) { this.items = items; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null || getClass() != obj.getClass()) return false; Warehouse that = (Warehouse) obj; if (!address.equals(that.address)) return false; return true; } @Override public String toString() { return "[id=" + this.id + ", address=" + this.address + "]"; } }
DAO слой
ItemDao.java
package com.devblogs.dao; import java.sql.SQLException; import java.util.Collection; import com.devblogs.model.Item; public interface ItemDao { public Item addItem(Item item) throws SQLException, Exception; public void updateItem(Item item) throws SQLException, Exception; public Item getItemById(Long id) throws SQLException, Exception; public Collection<Item> getAllItems() throws SQLException, Exception; public void deleteItem(Item item) throws SQLException, Exception; }
ProviderDao.java
package com.devblogs.dao; import java.sql.SQLException; import java.util.Collection; import com.devblogs.model.Provider; public interface ProviderDao { public Provider addProvider(Provider provider) throws SQLException, Exception; public void updateProvider(Provider provider) throws SQLException, Exception; public Provider getProviderById(Long id) throws SQLException, Exception; public Collection<Provider> getAllProviders() throws SQLException, Exception; public void deleteProvider(Provider provider) throws SQLException, Exception; }
WarehouseDao.java
package com.devblogs.dao; import java.sql.SQLException; import java.util.Collection; import com.devblogs.model.Warehouse; public interface WarehouseDao { public Warehouse addWarehouse(Warehouse warehouse) throws SQLException, Exception; public void updateWarehouse(Warehouse warehouse) throws SQLException, Exception; public Warehouse getWarehouseById(Long id) throws SQLException, Exception; public Collection<Warehouse> getAllWarehouses() throws SQLException, Exception; public void deleteWarehouse(Warehouse warehouse) throws SQLException, Exception; }
В реализации dao-слоя обратим внимание на методы addItem, addProvider и addWarehouse на то как происходит извлечение ключа, сгенерированного базой данных. Когда мы работаем с базой данных через JDBC, для того, чтобы извлечь ключ, нам нужно создать объект KeyHolder и передать его вместе с запросом, а потом, после выполнения вставки, извлечь из него ключ. Фреймворк хибернейт сам извлечет сгенерированный ключ и просетит его в объект предметной области, поэтому нам все что надо сделать это после оператора вставки save передать объект предметной области обратной вызывающему методу.
ItemDaoImpl.java
package com.devblogs.dao.impl; import java.sql.SQLException; import java.util.Collection; import org.hibernate.SessionFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import com.devblogs.dao.ItemDao; import com.devblogs.model.Item; @Component public class ItemDaoImpl implements ItemDao { @Autowired private SessionFactory sessionFactory; @Transactional(readOnly = false) public Item addItem(Item item) throws SQLException, Exception { sessionFactory.getCurrentSession().save(item); return item; } @Transactional(readOnly = false) public void updateItem(Item item) throws SQLException, Exception { sessionFactory.getCurrentSession().update(item); } @Transactional(readOnly = true) public Item getItemById(Long id) throws SQLException, Exception { return (Item) sessionFactory.getCurrentSession().createQuery("from Item where id = " + id).uniqueResult(); } @Transactional(readOnly = true) public Collection<Item> getAllItems() throws SQLException, Exception { return sessionFactory.getCurrentSession().createQuery("from Item i").list(); } @Transactional(readOnly = false) public void deleteItem(Item item) throws SQLException, Exception { sessionFactory.getCurrentSession().delete(item); } }
ProviderDaoImpl.java
package com.devblogs.dao.impl; import java.sql.SQLException; import java.util.Collection; import org.hibernate.SessionFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import com.devblogs.dao.ProviderDao; import com.devblogs.model.Provider; @Component public class ProviderDaoImpl implements ProviderDao { @Autowired private SessionFactory sessionFactory; @Transactional(readOnly = false) public Provider addProvider(Provider provider) throws SQLException, Exception { sessionFactory.getCurrentSession().save(provider); return provider; } @Transactional(readOnly = false) public void updateProvider(Provider provider) throws SQLException, Exception { sessionFactory.getCurrentSession().update(provider); } @Transactional(readOnly = true) public Provider getProviderById(Long id) throws SQLException, Exception { return (Provider) sessionFactory.getCurrentSession().createQuery("from Provider where id = " + id).uniqueResult(); } @Transactional(readOnly = true) public Collection<Provider> getAllProviders() throws SQLException, Exception { return sessionFactory.getCurrentSession().createQuery("from Provider p").list(); } @Transactional(readOnly = false) public void deleteProvider(Provider provider) throws SQLException, Exception { sessionFactory.getCurrentSession().delete(provider); } }
WarehouseDaoImpl.java
package com.devblogs.dao.impl; import java.sql.SQLException; import java.util.Collection; import org.hibernate.SessionFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import com.devblogs.dao.WarehouseDao; import com.devblogs.model.Warehouse; @Component public class WarehouseDaoImpl implements WarehouseDao { @Autowired private SessionFactory sessionFactory; @Transactional(readOnly = false) public Warehouse addWarehouse(Warehouse warehouse) throws SQLException, Exception { sessionFactory.getCurrentSession().save(warehouse); return warehouse; } @Transactional(readOnly = false) public void updateWarehouse(Warehouse warehouse) throws SQLException, Exception { sessionFactory.getCurrentSession().update(warehouse); } @Transactional(readOnly = true) public Warehouse getWarehouseById(Long id) throws SQLException, Exception { return (Warehouse) sessionFactory.getCurrentSession().createQuery("from Warehouse where id = " + id).uniqueResult(); } @Transactional(readOnly = true) public Collection<Warehouse> getAllWarehouses() throws SQLException, Exception { return sessionFactory.getCurrentSession().createQuery("from Warehouse w").list(); } @Transactional(readOnly = false) public void deleteWarehouse(Warehouse warehouse) throws SQLException, Exception { sessionFactory.getCurrentSession().delete(warehouse); } }
Тесты
TestItem.java
package com.devblogs.test; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests; import com.devblogs.dao.ItemDao; import com.devblogs.model.Item; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; @ContextConfiguration("classpath:context.xml") public class TestItem extends AbstractJUnit4SpringContextTests { @Autowired private ItemDao itemDao; @Test public void testInsertFind() { // Создать тестовый объект Item item = new Item(); item.setName("zheka"); try { // Сохранить тестовый объект в базе данных Item i = itemDao.addItem(item); // Вытащить тестовый объект из базы данных Item itemFromDb = itemDao.getItemById(i.getId()); // Сравнить вытащенный объект из базы данных с тестовым объектом assertEquals(item, itemFromDb); // Удалить тестовый объект из базы данных itemDao.deleteItem(itemFromDb); } catch (Exception e) { e.printStackTrace(); } } @Test public void testInsertFindUpdate() { // Создать тестовый объект Item item = new Item(); item.setName("zheka"); try { // Сохранить тестовый объект в базе данных Item i = itemDao.addItem(item); // Вытащить тестовый объект из базы данных Item itemFromDb = itemDao.getItemById(i.getId()); // Обновить в вытащенном объекте поле name itemFromDb.setName("vasya"); // Записать обновленый тестовый объект в базу данных itemDao.updateItem(itemFromDb); // После обновления повторно вытащить тестовый объект из базы данных Item updatedItemFromDb = itemDao.getItemById(itemFromDb.getId()); // Сравнить тестовый обновленный объект с повторно вытащенным assertEquals(itemFromDb, updatedItemFromDb); // Удалить тестовый объект из базы данных itemDao.deleteItem(updatedItemFromDb); } catch (Exception e) { e.printStackTrace(); } } @Test public void testDelete() { // Создать тестовый объект Item item = new Item(); item.setName("test message"); try { // Сохранить тестовый объект в базе данных Item i = itemDao.addItem(item); // Вытащить тестовый объект из базы данных Item itemToDelete = itemDao.getItemById(i.getId()); // Удалить тестовый объект из базы данных itemDao.deleteItem(itemToDelete); // Найти удаленный объект в базе данных Item itemAfterDeleting = itemDao.getItemById(i.getId()); // Сравнить вытащенный объект после удаления из базы данных на null assertNull(itemAfterDeleting); } catch (Exception e) { e.printStackTrace(); } } }
TestProvider.java
package com.devblogs.test; import java.util.HashSet; import java.util.Set; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests; import com.devblogs.dao.ItemDao; import com.devblogs.dao.ProviderDao; import com.devblogs.model.Item; import com.devblogs.model.Provider; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; @ContextConfiguration("classpath:context.xml") public class TestProvider extends AbstractJUnit4SpringContextTests { @Autowired private ProviderDao providerDao; @Autowired private ItemDao itemDao; @Test public void testInsertProviderWithItems() { // Создать тестовый объект Provider Provider provider = new Provider(); provider.setName("test provider"); // Создать тестовый объекты Item Set<Item> items = new HashSet<Item>(); Item item1 = new Item(); item1.setName("item1"); Item item2 = new Item(); item2.setName("item2"); Item item3 = new Item(); item3.setName("item3"); Item item4 = new Item(); item4.setName("item4"); Item item5 = new Item(); item5.setName("item5"); items.add(item1); items.add(item2); items.add(item3); items.add(item4); items.add(item5); provider.setItems(items); try { // Сохранить тестовый объект Provider в базе данных Provider p = providerDao.addProvider(provider); // Вытащить тестовый объект из базы данных Provider providerFromDb = providerDao.getProviderById(p.getId()); // Сравнить вытащенный объект из базы данных с тестовым объектом assertEquals(provider, providerFromDb); // Вытащить из вытащенного объекта Provider набор объектов Item Set<Item> itemsFromDb = provider.getItems(); // Пройти по каждому объекту Item и сравнить с исходными for (Item itemFromDb : itemsFromDb) { // Проверить входит ли вытащенный объект item из базы данных в // набор items тестового объекта Provider assertEquals(items.contains(itemFromDb), true); } // Удалить тестовый объект Provider из базы данных providerDao.deleteProvider(providerFromDb); } catch (Exception e) { e.printStackTrace(); } } @Test public void testInsertFind() { // Создать тестовый объект Provider provider = new Provider(); provider.setName("test provider"); try { // Сохранить тестовый объект в базе данных Provider p = providerDao.addProvider(provider); // Вытащить тестовый объект из базы данных Provider providerFromDb = providerDao.getProviderById(p.getId()); // Сравнить вытащенный объект из базы данных с тестовым объектом assertEquals(provider, providerFromDb); // Удалить тестовый объект из базы данных providerDao.deleteProvider(providerFromDb); } catch (Exception e) { e.printStackTrace(); } } @Test public void testInsertFindUpdate() { // Создать тестовый объект Provider provider = new Provider(); provider.setName("test provider"); try { // Сохранить тестовый объект в базе данных Provider p = providerDao.addProvider(provider); // Вытащить тестовый объект из базы данных Provider providerFromDb = providerDao.getProviderById(p.getId()); // Обновить в вытащенном объекте поле name providerFromDb.setName("other provider"); // Записать обновленый тестовый объект в базу данных providerDao.updateProvider(providerFromDb); // После обновления повторно вытащить тестовый объект из базы данных Provider updatedProviderFromDb = providerDao.getProviderById(providerFromDb.getId()); // Сравнить тестовый обновленный объект с повторно вытащенным assertEquals(providerFromDb, updatedProviderFromDb); // Удалить тестовый объект из базы данных providerDao.deleteProvider(updatedProviderFromDb); } catch (Exception e) { e.printStackTrace(); } } @Test public void testDelete() { // Создать тестовый объект Provider provider = new Provider(); provider.setName("test provider"); try { // Сохранить тестовый объект в базе данных Provider p = providerDao.addProvider(provider); // Вытащить тестовый объект из базы данных Provider providerFromDb = providerDao.getProviderById(p.getId()); // Удалить тестовый объект из базы данных providerDao.deleteProvider(providerFromDb); // Найти удаленный объект в базе данных Provider providerAfterDeleting = providerDao.getProviderById(providerFromDb.getId()); // Сравнить вытащенный объект после удаления из базы данных на null assertNull(providerAfterDeleting); } catch (Exception e) { e.printStackTrace(); } } }
TestWarehouse.java
package com.devblogs.test; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests; import com.devblogs.dao.WarehouseDao; import com.devblogs.model.Warehouse; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; @ContextConfiguration("classpath:context.xml") public class TestWarehouse extends AbstractJUnit4SpringContextTests { @Autowired private WarehouseDao warehouseDao; @Test public void testInsertFind() { // Создать тестовый объект Warehouse warehouse = new Warehouse(); warehouse.setAddress("ul. Moskovskaya, 1"); try { // Сохранить тестовый объект в базе данных Warehouse w = warehouseDao.addWarehouse(warehouse); // Вытащить тестовый объект из базы данных Warehouse warehouseFromDb = warehouseDao.getWarehouseById(w.getId()); // Сравнить вытащенный объект из базы данных с тестовым объектом assertEquals(warehouse, warehouseFromDb); // Удалить тестовый объект из базы данных warehouseDao.deleteWarehouse(warehouseFromDb); } catch (Exception e) { e.printStackTrace(); } } @Test public void testInsertFindUpdateDelete() { // Создать тестовый объект Warehouse warehouse = new Warehouse(); warehouse.setAddress("ul. Moskovskaya, 1"); try { // Сохранить тестовый объект в базе данных Warehouse w = warehouseDao.addWarehouse(warehouse); // Вытащить тестовый объект из базы данных Warehouse warehouseFromDb = warehouseDao.getWarehouseById(w.getId()); //Обновить в вытащенном объекте поле address warehouseFromDb.setAddress("ul. Leningradskaya, 4"); // Записать обновленый тестовый объект в базу данных warehouseDao.updateWarehouse(warehouseFromDb); // После обновления повторно вытащить тестовый объект из базы данных Warehouse updatedWarehouseFromDb = warehouseDao.getWarehouseById(warehouseFromDb.getId()); // Сравнить тестовый обновленный объект с повторно вытащенным assertEquals(warehouseFromDb, updatedWarehouseFromDb); // Удалить тестовый объект из базы данных warehouseDao.deleteWarehouse(updatedWarehouseFromDb); } catch (Exception e) { e.printStackTrace(); } } @Test public void testInsertFindDelete() { // Создать тестовый объект Warehouse warehouse = new Warehouse(); warehouse.setAddress("test message"); try { // Сохранить тестовый объект в базе данных Warehouse w = warehouseDao.addWarehouse(warehouse); // Вытащить тестовый объект из базы данных Warehouse warehouseToDelete = warehouseDao.getWarehouseById(w.getId()); // Удалить тестовый объект из базы данных warehouseDao.deleteWarehouse(warehouseToDelete); // Найти удаленный объект в базе данных Warehouse warehouseAfterDeleting = warehouseDao.getWarehouseById(w.getId()); // Сравнить вытащенный объект после удаления из базы данных на null assertNull(warehouseAfterDeleting); } catch (Exception e) { e.printStackTrace(); } } }
Спринговая конфигурация
Этот пост отличается от двух предыдущих тем, что мы конфигурируем объекты с помощью спринга. По мимо объектов предметной области, то есть собственно с чем мы работаем, нам нужны еще вспомогательные объекты, которые предоставляют способ работы с объектами предметной области. Hiberante с базой работает через объект Session, а объект Session получаем из объекта SessionFactory, но для того, чтобы объект SessionFactory возвращал нам объект Session, нам нужно объект SessionFacotory настроить. В предыдущих постах мы это делали в контексте самого приложения, сначала создавали файл хибернейтовской конфигурации hibernate.cfg.xml в каталоге resources который ищется по класспасу, а в коде выполнялась такая строчка: new Configuration().configure().buildSessionFactory(), она находит файл конфигурации hibernate.cfg.xml и поднимает объект SessionFactory. Так было в прошлых постах, в этом посте всю хибернейтовскую конфигурацию засунем в спринговый конфигурационный файл, а объект SessionFactory будет подниматься уже из спринга. В Spring существует несколько классов, которые позволяют создать объект SessionFactory в нашем примере это org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean который работает с аннотациями, для него мы пропишем всю необходимую конфигурацию в спринговом конфигурационном файле:
context.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" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xsi:schemaLocation=" http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd"> <jdbc:embedded-database id="dataSource" type="H2"> <jdbc:script location="classpath:scripts/create-data-model.sql"/> <jdbc:script location="classpath:scripts/fill-database.sql"/> </jdbc:embedded-database> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"/> </bean> <tx:annotation-driven/> <context:component-scan base-package="com.devblogs" /> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="packagesToScan" value="com.devblogs.model"/> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.H2Dialect</prop> <prop key="hibernate.max_fetch_depth">3</prop> <prop key="hibernate.jdbc.fetch_size">50</prop> <prop key="hibernate.jdbc.batch_size">10</prop> <prop key="hibernate.show_sql">false</prop> </props> </property> </bean> </beans>
Помчик
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>com.devblogs</groupId> <artifactId>spring-hibernate</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>spring-hibernate</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <spring.version>3.2.7.RELEASE</spring.version> </properties> <dependencies> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>3.6.7.Final</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>3.6.3.Final</version> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <version>1.3.160</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> </dependencies> </project>
Компиляция и запуск
Для проверки работоспособности приложения запустим мавенские тесты командой mvn test:
mvn test [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building spring-hibernate 0.0.1-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ spring-hibernate --- [INFO] Using 'UTF-8' encoding to copy filtered resources. [INFO] Copying 3 resources [INFO] [INFO] --- maven-compiler-plugin:2.5.1:compile (default-compile) @ spring-hibernate --- [INFO] Nothing to compile - all classes are up to date [INFO] [INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ spring-hibernate --- [INFO] Using 'UTF-8' encoding to copy filtered resources. [INFO] skip non existing resourceDirectory E:\practice\spring\test\spring-hibernate\src\test\resources [INFO] [INFO] --- maven-compiler-plugin:2.5.1:testCompile (default-testCompile) @ spring-hibernate --- [INFO] Nothing to compile - all classes are up to date [INFO] [INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ spring-hibernate --- [INFO] Surefire report directory: E:\practice\spring\test\spring-hibernate\target\surefire-reports ------------------------------------------------------- T E S T S ------------------------------------------------------- Running com.devblogs.test.TestItem Apr 26, 2016 1:51:05 PM org.springframework.test.context.TestContextManager retrieveTestExecutionListeners INFO: Could not instantiate TestExecutionListener class [org.springframework.test.context.web.ServletTestExecutionListener]. Specify custom listener classes or make the default listener classes (and their dependencies) available. Apr 26, 2016 1:51:05 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions INFO: Loading XML bean definitions from class path resource [context.xml] Apr 26, 2016 1:51:05 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh INFO: Refreshing org.springframework.context.support.GenericApplicationContext@48778a5d: startup date [Tue Apr 26 13:51:05 EEST 2016]; root of context hierarchy Apr 26, 2016 1:51:05 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@17e4a077: defining beans [dataSource,transactionManager,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0,org.springframework.transaction.interceptor.TransactionInterceptor#0,org.springframework.transaction.config.internalTransactionAdvisor,itemDaoImpl,providerDaoImpl,warehouseDaoImpl,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,sessionFactory,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor]; root of factory hierarchy Apr 26, 2016 1:51:05 PM org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseFactory initDatabase INFO: Creating embedded database 'dataSource' Apr 26, 2016 1:51:05 PM org.springframework.jdbc.datasource.init.ResourceDatabasePopulator executeSqlScript INFO: Executing SQL script from class path resource [scripts/create-data-model.sql] Apr 26, 2016 1:51:06 PM org.springframework.jdbc.datasource.init.ResourceDatabasePopulator executeSqlScript INFO: Done executing SQL script from class path resource [scripts/create-data-model.sql] in 119 ms. Apr 26, 2016 1:51:06 PM org.springframework.jdbc.datasource.init.ResourceDatabasePopulator executeSqlScript INFO: Executing SQL script from class path resource [scripts/fill-database.sql] Apr 26, 2016 1:51:06 PM org.springframework.jdbc.datasource.init.ResourceDatabasePopulator executeSqlScript INFO: Done executing SQL script from class path resource [scripts/fill-database.sql] in 14 ms. SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details. Apr 26, 2016 1:51:06 PM org.springframework.orm.hibernate3.LocalSessionFactoryBean buildSessionFactory INFO: Building new Hibernate SessionFactory Apr 26, 2016 1:51:06 PM org.springframework.orm.hibernate3.HibernateTransactionManager afterPropertiesSet INFO: Using DataSource [org.springframework.jdbc.datasource.SimpleDriverDataSource@5720be65] of Hibernate SessionFactory for HibernateTransactionManager Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.944 sec Running com.devblogs.test.TestProvider Apr 26, 2016 1:51:07 PM org.springframework.test.context.TestContextManager retrieveTestExecutionListeners INFO: Could not instantiate TestExecutionListener class [org.springframework.test.context.web.ServletTestExecutionListener]. Specify custom listener classes or make the default listener classes (and their dependencies) available. Tests run: 4, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.037 sec Running com.devblogs.test.TestWarehouse Apr 26, 2016 1:51:07 PM org.springframework.test.context.TestContextManager retrieveTestExecutionListeners INFO: Could not instantiate TestExecutionListener class [org.springframework.test.context.web.ServletTestExecutionListener]. Specify custom listener classes or make the default listener classes (and their dependencies) available. Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.021 sec Results : Tests run: 10, Failures: 0, Errors: 0, Skipped: 0 [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 3.953s [INFO] Finished at: Tue Apr 26 13:51:07 EEST 2016 [INFO] Final Memory: 7M/244M [INFO] ------------------------------------------------------------------------
Спецификация JPA, частичной реализацией которой является Hibernate, требует наличия файла persistence. Само имя может быть произвольным, только оно должно совпадать с тем, что написано в настройках Spring.