2016-06-26 28 views
5

Generics ile bir Hazırda Bekletme DAO'sunun nasıl oluşturulacağına ilişkin birkaç eğitici buldum, ancak hepsi SessionFactory yerine EntityManager kullanıyor. Sorum şu: SessionFactory kullanarak jeneriklerle DAO nasıl kurulur. Bugüne kadar aşağıda var:Generics ile Hazırda Beklet DAO nasıl uygulanır

Arayüz:

public interface GenericDao<T> { 

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

Sınıf:

@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; 
    } 

Ben yaklaşık findById kullanarak jeneriği gitmek nasıl emin değilim. Diğer yöntemlerin doğru olduğuna inanıyorum ama yanılıyorsam beni düzelt.

YAN SORU:SessionFactory kullanmaktan daha yararlı EntityManager kullanıyor mu? Konuyla ilgili birkaç yazı gördüm, ancak birkaç fikir daha istiyorum.

+0

Java'da, jenerikler silme işlemi ile uygulanır ve "T" biçiminiz, çalışma zamanında 'T' nesnesi olur. Diğer bir deyişle, çalışma zamanında "T" tipi mevcut değildir. Yeni basılan bir "T" örneğini döndüren herhangi bir genel yöntem, bu nedenle, yöntemin, oluşturması gereken örnek türünü yansıtmak üzere kullanabileceği bir çalışma zamanı türü belirtecini gerektirir. 'FindById (...)' için daha pratik bir imza bu nedenle 'public T findById (Sınıf sınıfı, uzun kimlik)' dir. – scottb

+0

@scottb bu yüzden Class belirteci, yöntemin hangi tür nesnenin geri dönmesi gerektiğini belirlemek için kullanılacaktır? Bu konuda tam olarak nasıl giderim?EntityManager örnekleri ile entityManager.find (type.class, id) 'yi gördüm, ancak bunu SessionFactory ile nasıl yapacağımı bilmiyorum. –

+0

Geri dönmeniz gereken türün argüman içermeyen bir kurgulayıcısına sahip olması durumunda, rasgele bir tür olan "T" nin yeni bir örneğini dinamik olarak karıştırmanın en kolay yolu, " Sınıfının" newInstance() yöntemini kullanmaktır. " Örneğin. T myObj = class.newInstance(); '. Aksi takdirde, argümanlarla uygun bir yapıcıyı çağırmak için 'Class ' nesnesi aracılığıyla yansımayı kullanmanız gerekebilir. Böyle bir yöntemde, "Sınıf Sınıfında" sınıfı, * çalışma zamanı türü belirtecinin * rolünü oynar. Java'da, bazen tam olarak gerekli çünkü jenerik türleri çalışma zamanında mevcut değildir. – scottb

cevap

5

Bu yöntem içinden Class<T> erişiminiz olması gerekir.

@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 
    } 
} 

Ve alt sınıfları geçerdi:

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

Yoksa yönteminde kullanılmak üzere sınıfın yapıcı içine Class<T> geçebilir: Eğer yöntem haline Class<T> geçebilir, iki seçeneğiniz vardır üst sınıf içine kendi sınıfı:

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

Ardından, clazz örneğini kullanarak kullanarak jenerik yöntemde varlık alabilirsiniz Session#get yöntemi:

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

fazla bilgi için aşağıdaki sorulara göz atın:


Bildiğim kadarıyla yan soru olarak, EntityManager parçasıdır JPA (Ja va Persistence API'si). Uygulamanızı, Hazırda Bekletme API'sı yerine Java API belirtimini kullanarak geliştirmek, uygulamanızın Hazırda Bekleme'ye bağımlı olmamasına olanak tanır. Bu, kodunuzu yapmadan ve değiştirmeden, Hazırda Beklet, OpenJPA veya TopLink gibi popüler JPA uygulamaları arasında geçiş yapmanıza olanak tanır.

This question arasındaki fark hakkında daha fazla bilgi vardır.

+0

Teşekkür ederiz! Başka bir yan soru - SessionFactory 'üzerinde 'EntityManager' kullanmak için bir neden var mı, tersi mi? Yoksa ikisi de aynı şeyi yapar mı? –

+0

Bu süper (User.class); 'satırını eklemenize gerek yok. Özet genel sınıf, burada görüldüğü gibi çocuk sınıflarının tip argümanını bulabilir: https://github.com/acdcjunior/acdcjunior-github-io-example-projects/blob/master/spring-mvc-jpa-mockito -piloto/src/main/java/net/acdcjunior/piloto/altyapı/jpa/JpaAbstractRepository.java # L43 – acdcjunior

+0

@JakeMiller 'EntityManager' JPA'dır,' SessionFactory' Hazırda bekletme (bir JPA uygulamasıdır). Onlar aynı şey değiller. EntityManager' (JPA), 'EntessionManagerFactory' (JPA)' SessionFactory' (Hazırda Bekleme) olarak 'Session' (Hazırda Beklet)’dir. Genellikle, JPA'yı tercih ederiz. Ancak, uygulamayı hiçbir zaman Hazırda Bekletme modundan diğerine (TopLink gibi) değiştirmeyi düşünmüyorsanız, önemli olmamalıdır (yani, bu durumda tercih ettiğiniz her şeyi kullanın). – acdcjunior