Когда я только начал изучать Hibernate я делал на каждую свою сущность отдельный DAO. Вскоре я наткнулся на популярную в сети статью "Не повторяйте DAO", которая используя Spring и дженерики создает обобщенный типизированный DAO. И через некоторое время данный подход возродился в некий фреймворк, который может работать с любой сущностью или коллекцией сущностей. Но смысла нету показывать мои костыли, если есть Hibernate Generic D.A.O. Framework, про который можно прочитать здесь, а я постараюсь показать пример его использования. Правда DAO нужно будет всеравно создавать для каждой сущности, но зато мы получим общие методы и интересный подход к составлению запросов в БД.
Я не буду описывать что такое Spring и Hibernate и как их первоначально добавить в проект и настроить, так что этот пост предозначен для тех, что уже ознакомился с этими фреймворками. Если же кому не довелось с ними столкнутся, то в интернете статей на эту тему больше чем достаточно (можно начать с http://habrahabr.ru/blogs/java/111102/ )
1. Для начала добавим фреймворк в проект.
Сделать это можно подложив скачанные здесь jar'ы в проект или используя maven, добавить след. зависимости
Я использую hibernate-annotation. Кому по душе писать xml-маппинги, я думаю будет не сложно понять по коду структуру сущности.
Опишем DataSource и SessionFactory.
Для того, чтобы получить прелести этого фреймворка мы для интерфейса наследуем GenericDAO с коробки и для класса - GenericDAOImpl
Теперь наш UserDAO имеет стандартные методы получения и модификации объекта в БД.
Но на этом возможности фреймворка не заканчиваются. В нем есть интересный подход к постоению запросов с помощью класса Search.
Добавим в наш DAO несколько методов.
Я не буду описывать что такое Spring и Hibernate и как их первоначально добавить в проект и настроить, так что этот пост предозначен для тех, что уже ознакомился с этими фреймворками. Если же кому не довелось с ними столкнутся, то в интернете статей на эту тему больше чем достаточно (можно начать с http://habrahabr.ru/blogs/java/111102/ )
1. Для начала добавим фреймворк в проект.
Сделать это можно подложив скачанные здесь jar'ы в проект или используя maven, добавить след. зависимости
<dependency>
<groupId>com.googlecode.genericdao</groupId>
<artifactId>dao-hibernate</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.googlecode.genericdao</groupId>
<artifactId>search-jpa-hibernate</artifactId>
<version>1.0.0</version>
</dependency>
2. Создадим класс сущность.Я использую hibernate-annotation. Кому по душе писать xml-маппинги, я думаю будет не сложно понять по коду структуру сущности.
@Entity
@Table(name = "user", uniqueConstraints = @UniqueConstraint(columnNames = "account"))
public class User implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
@Column(name = "account", unique = true, nullable = false, length = 64)
private String account;
@Column(name = "is_active", nullable = false)
private boolean isActive;
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public boolean isIsActive() {
return isActive;
}
public void setIsActive(boolean isActive) {
this.isActive = isActive;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
3. Конфигурим в контексте Spring'aОпишем DataSource и SessionFactory.
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost/test?useUnicode=true&characterEncoding=UTF-8" />
<property name="username" value="test" />
<property name="password" value="test" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>net.dirong.hgs.demo.entity.User</value>
</list>
</property>
<property name="annotatedPackages">
<list>
<value>net.dirong.hgs.demo.entity</value>
</list>
</property>
<property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />
<property name="hibernateProperties">
<props>
..........................................................
</props>
</property>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
4. Создадим DAO.Для того, чтобы получить прелести этого фреймворка мы для интерфейса наследуем GenericDAO с коробки и для класса - GenericDAOImpl
public interface UserDAO extends GenericDAO<User, Long> {
}
public class UserDAOImpl extends GenericDAOImpl<User, Long> implements UserDAO{
}
И добавим его в контекст Spring'a
<bean id="userDAO" class="net.dirong.hgs.demo.UserDAOImpl">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
5. ИспользованиеТеперь наш UserDAO имеет стандартные методы получения и модификации объекта в БД.
Но на этом возможности фреймворка не заканчиваются. В нем есть интересный подход к постоению запросов с помощью класса Search.
Добавим в наш DAO несколько методов.
public class UserDAOImpl extends GenericDAOImpl<User, Long> implements UserDAO{
public User searchByAccount(String account) throws Exception{
Search search = new Search();
search.addFilterEqual("account", account);
return searchUnique(search);
}
public List<User> getActiveUsers(){
Search search = new Search();
search.addFilterEqual("isActive", true);
search.addFilterNotNull("createDate");
search.addSortDesc("firstName");
return search(search);
}
@Override
public boolean save(User entity) {
if(entity.getId()==null){
entity.setCreateDate(new Date());
}
return super.save(entity);
}
}
Вот так вот легко можно строить запросы. Но если нам нужно, как в большенстве случаев, использовать несколько сущностей в запросе, то на помощь приходит SearchFacade
<bean id="searchFacade" class="com.trg.search.hibernate.HibernateSearchFacade">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
И теперь его можно использовать в своих бинах.
@Autowired
private SearchFacade searchFacade;
@Transactional
public List<Role> getRolesByUser(User user) {
Search search = new Search(Role.class);
search.addFilterEqual("user", user);
search.addField("role");
search.addSort("role.name", false);
return searchFacade.search(search);
}
Надеюсь пост будет полезен. Если что-то не понятно описал, то сорри, могу позже описать некоторые детали более подробно. Кому стало интерестно, то на вики фреймворка описано более подробно.
@Override
ОтветитьУдалитьpublic boolean save(User entity) {
if(entity.getId()==null){
entity.setCreateDate(new Date());
}
return super.save(entity);
}
госпади,что это за копипаста?)