2016-06-26 2 views
5

Я нашел несколько руководств по созданию Hibernate DAO с дженериками, но все они используют EntityManager вместо SessionFactory. Мой вопрос заключается в том, как создать DAO с помощью дженериков с использованием SessionFactory. У меня есть ниже до сих пор:Как реализовать Hibernate DAO с generics

Интерфейс:

public interface GenericDao<T> { 

    public void save(T obj); 
    public void update(T obj); 
    public void delete(T obj); 
    public T findById(long id); 
} 

Класс:

@Repository 
public class GenericDaoImpl<T> implements GenericDao<T> { 

    @Autowired 
    private SessionFactory sessionFactory; 

    public void save(T obj) { 
     Session session = sessionFactory.openSession(); 
     Transaction tx = null; 
     try { 
      tx = session.beginTransaction(); 
      session.save(obj); 
      tx.commit(); 
     } catch (HibernateException e) { 
      if(tx != null) 
       tx.rollback(); 
      e.printStackTrace(); 
     } finally { 
      session.close(); 
     } 

    } 

    public void update(T obj) { 
     Session session = sessionFactory.openSession(); 
     Transaction tx = null; 
     try { 
      tx = session.beginTransaction(); 
      session.update(obj); 
      tx.commit(); 
     } catch (HibernateException e) { 
      if(tx != null) 
       tx.rollback(); 
      e.printStackTrace(); 
     } finally { 
      session.close(); 
     } 

    } 

    public void delete(T obj) { 
     Session session = sessionFactory.openSession(); 
     Transaction tx = null; 
     try { 
      tx = session.beginTransaction(); 
      session.delete(obj); 
      tx.commit(); 
     } catch (HibernateException e) { 
      if(tx != null) 
       tx.rollback(); 
      e.printStackTrace(); 
     } finally { 
      session.close(); 
     } 

    } 

    public T findById(long id) { 
     // ?? 
     return null; 
    } 

Я не уверен, как идти о findById с использованием дженериков. Я считаю, что другие методы правильные, но исправьте меня, если я ошибаюсь.

БОЛЬШОЙ ВОПРОС: Использует EntityManager более полезный, чем использование SessionFactory? Я видел несколько сообщений по этому вопросу, но хотел бы еще несколько мнений.

+0

В Java генерические средства реализуются путем стирания, а ваш формальный параметр 'T' становится' Object' во время выполнения. Другими словами, во время выполнения тип 'T' не существует. Любой общий метод, который возвращает новый чеканный экземпляр 'T', поэтому потребует маркер типа времени выполнения, который метод может использовать, чтобы отразить тип экземпляра, который он должен будет создать. Более практичная подпись для 'findById (...)' поэтому 'public T findById (класс класс, long id)'. – scottb

+0

@scottb, так что токен класса будет использоваться для определения того, какой тип объекта должен возвращать метод? Как бы я это сделал?С примерами 'EntityManager' я увидел' entityManager.find (type.class, id); ', но я не уверен, как это сделать с помощью' SessionFactory'. –

+0

Если тип, который вам нужно вернуть, имеет конструктор без аргументов, тогда самый простой способ динамически отличить новый экземпляр произвольного типа 'T' должен был бы использовать метод' newInstance() 'класса ', например. 'T myObj = class.newInstance();'. В противном случае вам может понадобиться использовать отражение через объект 'Class ' для вызова соответствующего конструктора с аргументами. В таком методе «класс» в классе Class класс' играет роль маркера типа * времени выполнения *. В Java это иногда необходимо именно потому, что общие типы не существуют во время выполнения. – scottb

ответ

5

У вас должен быть доступ к Class<T> из этого метода. У вас есть два варианта, вы можете передать Class<T> в метод:

public T findById(long id, Class<T> clazz) { 
    // method implementation 
} 

Или вы можете передать Class<T> в конструктор класса для использования в методе:

@Repository 
public class GenericDaoImpl<T> implements GenericDao<T> { 

    private Class<T> clazz; 

    protected GenericDaoImpl(Class<T> clazz) { 
     this.clazz = clazz; 
    } 

    // other methods omitted 

    public T findById(long id) { 
     // method implementation 
    } 
} 

И подклассы пройдет их класс в суперкласс:

public class UserDao extends GenericDaoImpl<User> { 
    public UserDao() { 
     super(User.class); 
    } 
} 

Затем, используя ваш clazz экземпляр вы можете получить объект в вашем универсальном методе с использованием Session#get метод:

T entity = session.get(clazz, id); 

Смотрите следующие вопросы для получения дополнительной информации:


Что касается стороны вопроса, EntityManager является частью JPA (Ja va API устойчивости). Разработка вашего приложения с использованием спецификации Java API вместо Hibernate API позволяет вашему приложению не становиться зависимым от Hibernate. Это позволяет переключаться между популярными реализациями JPA, такими как Hibernate, OpenJPA или TopLink, без внесения изменений в ваш код.

This question имеет больше информации о различии.

+0

Спасибо! Другой вопрос - есть ли причина использовать 'EntityManager' над' SessionFactory' и наоборот? Или они оба делают в первую очередь одно и то же? –

+0

Не нужно добавлять строку 'super (User.class);'. Абстрактный общий класс может узнать аргумент типа своих дочерних классов, как показано здесь: https://github.com/acdcjunior/acdcjunior-github-io-example-projects/blob/master/spring-mvc-jpa-mockito -piloto/src/main/java/net/acdcjunior/piloto/infrastructure/jpa/JpaAbstractRepository.java # L43 – acdcjunior

+0

@JakeMiller 'EntityManager' является JPA,' SessionFactory' является спящим (реализация JPA). Это не одно и то же. 'EntityManager' (JPA) относится к' Session' (Hibernate), поскольку 'EntityManagerFactory' (JPA) относится к' SessionFactory' (Hibernate). Обычно мы предпочитаем JPA. Но если вы не планируете когда-либо изменять реализацию из Hibernate в другую (например, TopLink), это не имеет значения (я имею в виду, в этом случае используйте все, что вы предпочитаете). – acdcjunior

 Смежные вопросы

  • Нет связанных вопросов^_^