Настройка Hibernate 3 java

Сидя на прошлой линуксовке рядом с Mabel'ом он спросил после 8 кружки Пива что такое Hibernate? Я как смог объяснил :) Этот разговор натолкнул меня на мысль что в русском сегменте интернета нет практически полных статей на тему что такое  Hibernate и как его настроить и использовать, по этому я Начинаю ряд статей посвяшенных Hibernate 3 версии.

Нам потребуется:
1. jdk 1.6
2. ant 1.6.5
3. mysql 5
4. hibernate-3.2.0
5  mysql-connector-java-3.1.13-bin.jar

Что такое Hibernate - это object relational mapping (ORM). Коротко ORM - это отображение(mapping) структуры данных(полей) таблицы Базы Данных - на
POJO-объект. POJO-объект - это Java Bean компонент который не наследует(extend) ни каких классов. Объясню все на примере пусть у нас существует таблица:

CREATE TABLE `persons` (
  `id` int(11) NOT NULL auto_increment, -- уникальный номер
  `firstName` varchar(20) default NULL, -- имя
  `lastName` varchar(20) default NULL,  -- фамилия
  `BirthDate` date default NULL,        -- дата рождения
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

Нам надо отобразить поля таблицы на POJO-объект, описываем переменные и  get- и set- методы доступа к ним, то есть одна запись из Базы данных будет
соответствовать 1   POJO-объекту.

package org.vit.domain;

import java.util.Date;

public class Person {
    private Integer id;       //уникальный номер
    private String firstName; //имя
    private String lastName;  //фамилия
    private Date birthDate;   //дата рождения

    public Person() { //
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public Date getBirthDate() {
        return birthDate;
    }

    public void setBirthDate(Date birthDate) {
        this.birthDate = birthDate;
    }
}

Далее нам надо настроить hibernate что бы мы могли оперировать POJO-объектами как записями в БД. Настроить его можно ч\з 2 файла hibernate.cfg.xml или
hibernate.properties. Я использую hibernate.cfg.xml:

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD//EN"
    "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <!-- configure JDBC connection -->
        <property name="connection.useUnicode">true</property>
        <property name="connection.characterEncoding">UTF-8</property>
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.url">jdbc:mysql://localhost:3306/test</property>
        <property name="connection.username">root</property>
        <property name="connection.password">xor21</property>

        <!-- configure hibernate -->
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="current_session_context_class">thread</property>
    <property name="hibernate.transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>
    <!-- "Import" the mapping resources here -->
        <mapping resource="org/vit/domain/Person.hbm.xml"/>
    </session-factory>
</hibernate-configuration>

В секции <!-- configure JDBC connection --> я настраиваю подключение по JDBC драйверу к БД mysql
В секции <!-- configure hibernate --> настройки самого hibernate
Строчка <property name="dialect">org.hibernate.dialect.MySQLDialect</property> говорит hibernate что мы будем работать с БД mysql. Полный перечень поддерживаемых БД можно посмотреть в документации.
Следующие 2 строчки настраиваю поведение транзакции в hibernate
<property name="current_session_context_class">thread</property>  - стратегия управления транзакцией
<property name="hibernate.transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>
- Класс доступа к Transaction API hibernat'a
В секции <!-- "Import" the mapping resources here --> указываем файлы mapping, файлы которые связывают поля таблицы БД с полями PoJO-объекта. Имя файла состоит из имени Класса Person + расширение .hbm.xml (hbm - hibernate mapping):

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE
   hibernate-mapping
   PUBLIC
   "-//Hibernate/Hibernate Mapping DTD//EN"
   "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping >
   <!-- связываем класс org.vit.domain.Person  с таблицей Persons-->
   <class name="org.vit.domain.Person" table="Persons">
      <!-- связываем поле id Person-класса(name) с полем
      id(column) таблицы Persons при этом указав тип данных int,
      тег <id> - соответствует уникальному ключу по которому должен
      определяться каждый pojo-объект - это особенность hibernate т.е.
      каждая таблица должна иметь primary key (тип целое число) -->
      <id name="id" type="int" column="id">
         <!-- как генерируется id в POJO-объекте  Person,
         native - Базой Данных а именно по отношению к mysql -
         работает auto_increment поля id-->
         <generator class="native"/>
      </id>
      <!-- property
       firstName полю класса org.vit.domain.Person(name="firstName") сопоставляем
       из таблицы Persons колонку firstName(column="firstName") тип type="string"
       2 следующие property описываются аналогично :)
       -->
      <property name="firstName" type="string" column="firstName"/>
      <property name="lastName"  type="string" column="lastName"/>
      <property name="birthDate" type="date" column="BirthDate"/>
   </class>
</hibernate-mapping>

Основной рабочей единицей hibernate является сессия Session. Для того чтобы получить session надо настроить и создать объект SessionFactory. SessionFactory - должен быть Singelton-ом (настоятельная рекомендация разработчиков hibernate). Я пользуюсь классом HibernateUtil (взято из документации hibernat'a):

package org.hibernate.tutorial.util;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {
    private static final SessionFactory sessionFactory = buildSessionFactory();

    private static SessionFactory buildSessionFactory() {
        try {
// Создаем SessionFactory с настройками из файла hibernate.cfg.xml
            return new Configuration().
                    configure("hibernate.cfg.xml").buildSessionFactory();
        }
        catch (Throwable ex) {
// Make sure you log the exception, as it might be swallowed
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory() {
    // возвращаем сессию
        return sessionFactory;
    }
}

и вот после всех настроек мы можем пользоваться hibernate в нашей программе:

package org.vit;

import org.hibernate.tutorial.util.HibernateUtil;
import org.hibernate.Session;
import org.vit.domain.Person;

import java.util.Date;
import java.util.Calendar;

public class Vit {
    public static void main(String[] args) {
        // получаем сессию
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        try {
            // начинаем транзакцию
            session.beginTransaction();
            //создаем pojo-объек
            Person person = new Person();
            //заполняем его данными
            person.setFirstName("Vit");
            person.setLastName("Lo");
            Calendar c =Calendar.getInstance();
            c.set(2009, 11, 4);
            person.setBirthDate(c.getTime());//new Date(2009, 11, 3));
            //сохраняем в сессии и в БД применяем транзакцию
            session.save(person);
            session.getTransaction().commit();
        } finally {
            //если открыта сессия закрываем её
            if (session.isOpen()) session.close();
        }
    }
}

Какие мы библиотеки должны положить в classpath - всё это написано в файле ./hibernate-3.2.0/lib/README.txt пробегаемся по библиотекам и:

commons-logging-1.0.4.jar (1.0.4)
- Commons Logging
- runtime, required

- runtime, required - говорит что необходима при выполнении (НУЖНО ВСЕГДА)

c3p0-0.9.0.jar (0.9.0)
- C3P0 JDBC connection pool
- runtime, optional

- runtime, optional - говорит что необходима, если настроили hibernate c C3P0 JDBC pool'om при выполнении можно не включать(ЕСЛИ НАСТРОИЛИ Кинуть в classpath)

checkstyle-all.jar (unknown)
- Checkstyle
- buildtime

- buildtime  - необходима при компиляции библиотек hibernat'a (сборка из исходников)
 (НЕ НУЖНО)

+ нужно кинуть драйверок mysql-connector-java-3.1.13-bin.jar.

Скачиваем архив, Собираем проект и запускаем на выполнение:

# ant
....
     [echo] If you see this, it works!!!

BUILD SUCCESSFUL
Total time: 3 seconds

Лезем в БД и видим запись:
1    Vit    Lo    4.12.2009

ЗЫ ВАЖНО уточните пользователя, пароль и путь к вашей БД, скачав исходник в папку lib -  положите все  необходимые библиотеки  hibernate-3.2.0 +  mysql-connector-java-3.1.13-bin.jar

ВложениеРазмер
hibernat3_1.zip11.28 кб

Супер! Наконец-то кто-то

Супер! Наконец-то кто-то внятно объяснил. Спасибо, vit. А как оно по скорости по сравнению с обычными SQL-запросами? Если, например, надо обрабатывать в единицу времени огромное количество запросов насколько Hibernate уступает стандартному PreparedStatement?

не пойму что с сайтом по 1

не пойму что с сайтом по 1 недели доступа нет :) :)  :)  Hebernate - это обертка над JDBC соответственно она чуть медленей работает! попробуй тест какой нибудь прогнать  допустим 10 000 записей считать :)  Для сайтов самое то, но если быстродействие нужно всетаки JDBC - побыстрее будет :)

  сохраняются связанные

 

сохраняются связанные обекты без транзакций

Здравствуйте!
Не могли бы Вы мне помочь
У меня следующая проблема:
я не использую транзакции в хибернейте,и, как следствие, часть методов действительно не пишет в базу, но есть методы, которые сохраняют объекты в базу вопреки логике

есть три бина
Section:Worker=one-to-many
 

 

section

@Entity
@Table(name = "sectionTable")
public class Section {
 @Id
 @GeneratedValue(strategy = GenerationType.IDENTITY)
 @Column(name = "section_id")
 private int sectionId;

 @Column(name = "section_name")
 private String sectionName;

 @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "section")
 private List<Worker> workers;

 public Section() {
 }

 public Section(int sectionId) {
  this.sectionId = sectionId;
 }

 getters,setters...
}

worker

@Entity
@Table(name = "workerTable")
public class Worker {

 @Id
 @GeneratedValue(strategy = GenerationType.AUTO)
 @Column(name = "worker_id")
 private int workerId;

 @Column(name = "firstname")
 private String firstName;

 @Column(name = "lastname")
 private String lastName;

 @Column(name = "salary")
 private String salary;

 @Column(name = "birthDate")
 private String birthDate;

 @Column(name = "active")
 private String active;

 @ManyToOne(cascade = { CascadeType.PERSIST }, fetch = FetchType.LAZY)
 @JoinColumn(name = "section_id")
 private Section section;

 public Worker() {
  this.firstName = "";
  this.lastName = "";
  this.birthDate = "";
  this.active = "false";
  this.salary = "0.00";
  this.section = null;
 }
getters,setters...
}

user

и есть бин, ни с кем не связанный
@Entity
@Table(name = "user")
public class User{

 @Id
 @Column(name = "login)
 private String login;

 @Column(name = "pass")
 private String pass;

 public User() {
 }
getters,setters...
}
 

dao

public class DAO extends HibernateDaoSupport{
...
public void addSection(String sectionName) {
  session = getSession();
  Section section = new Section();
  section.setSectionName(sectionName);
  try {
  session.save(section);  
  } catch (Exception e) {
  log.error(e);
  }
  releaseSession(session);
 };

//section сохраняется в базу, не смотря на отсутствие транзакций

public void addUser(String login, String password) {
  session = getSession();
  User user = new User();
  user.setLogin(login);
  user.setPass(password);
  try {
  session.save(user);  
  } catch (Exception e) {
  log.error(e);
  }
  releaseSession(session);
 };
//а вот этот метод не сохраняет в базу usera, потому что нет транзакции
}
//и все это в одном классе

мой applicationContext
<?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:aop="http://www.springframework.org/schema/aop"
  xmlns:tx="http://www.springframework.org/schema/tx"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
  http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">

   
 <tx:annotation-driven transaction-manager="txManager"/>
 
 
 
 <bean id="myTxManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
  <property name="sessionFactory" ref="sessionFactory"/>
  </bean>

  <bean id="dao" class="dataBase.DAO" lazy-init="true" scope="singleton">
  <property name="sessionFactory" ref="sessionFactory"/>
  <property name="init" value="true"/>
 </bean> 
 <bean id="page" class="web.pages.Page">
  <property name="dao" ref="dao"/>
 </bean>  
  <bean id="workerList" class="web.pages.WorkerList"/>
  <bean id="workerEditor" class="web.pages.WorkerEditor"/>
  <bean id="sectionList" class="web.pages.SectionList"/>
  <bean id="sectionEditor" class="web.pages.SectionEditor"/>
  <bean id="aboutWorker" class="web.pages.AboutWorker"/>
  <bean id="register" class="web.pages.Register"/>
   
  <bean id="interceptor" class="web.Interceptor"/>

  <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
  <property name="interceptors">
  <list>
  <ref bean="interceptor"/>
  </list>
  </property>
  <property name="mappings">
  <props>
  mappings
  </props>
  </property>
  </bean>  
   
  
  <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
  <property name="prefix" value="/jsp/"/>
  <property name="suffix" value=".jsp"/>
  </bean>
   
  <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" lazy-init="true" scope="singleton">
  <property name="driverClassName" value="org.gjt.mm.mysql.Driver"/>
  <property name="url" value="jdbc:mysql://127.0.0.1:3306/webproject"/>
  <property name="username" value="${login}"/>  
  <property name="password" value="${pass}"/>  
 </bean>

  <bean id="sessionFactory" 
  class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" lazy-init="true" scope="singleton">
  <property name="dataSource" ref="dataSource"/>
  <property name="annotatedClasses">
  <list>
  <value>dataBase.beans.Section</value>
  <value>dataBase.beans.User</value>
  <value>dataBase.beans.Worker</value>
  </list>
  </property>  

  <property name="hibernateProperties">
  <props>
  <prop key="hibernate.hbm2ddl.auto">update</prop>
  <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
  <prop key="hibernate.transaction.flush_before_completion">true</prop>
  <prop key="hibernate.transaction.auto_close_session">true</prop>
  </props>
  </property>  
 </bean>  
</beans>

Словом, почему в случае с несвязанным бином отсутствие транзакции срабатывает, а в случае связи не работает?.. Можете помочь? Спасибо! 

P.S. с section delete и update не работают(как и должно быть без транзакций)

 

Что за метод releaseSession

Что за метод releaseSession ?
Делается ли session.flush(); ?

Отправить комментарий

КАПЧА
Этот вопрос задается для того, чтобы выяснить, являетесь ли Вы человеком или представляете из себя автоматическую спам-рассылку.
CAPTCHA на основе изображений
Enter the characters shown in the image.