Creating DAOs with Hibernate 3.5 & JPA 2.0 Annotations

本文介绍如何使用Hibernate 3.5和JPA 2.0创建Data Access Object (DAO),包括定义通用DAO接口、实现具体DAO类及在客户端应用中使用DAO进行数据增删改查操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Creating Good DAOs with Hibernate 3.5 and JPA 2.0 Annotations

In previous tutorials, we configured a 3.5 environment for development and testing, and went through the steps of persisting a very simple POJO, named the GameSummary, to the database. We even created a little class, named the HibernateCrudRunner, that went through the process of creating a persistent object, updating that object, querying that object, and finally, deleting that object. Yeah, it was a pretty awesome tutorial. 

But the problem with the application code was that it made direct calls to the Hibernate Session, and the transaction management was inconsistent and messy. In production applications, you want to minimize the exposure your client applications have to the internal workings of your persistence mechanism, and the best way to do that is to create fairly generic Data Access Object. And that's exactly what I'm going to do here.

By the way, you can find a really awesome and advanced tutorial on creating DAOs right here: Coding Advanced DAOs with Hibernate and JPA Annotations - The Pattern Our DAOs are going to be pretty awesome in their own right, but that tutorial goes really in depth about DAOs and the Factory Pattern and such. Once you've mastered this tutorial, you'll be ready to really advance your knowledge of DAOs by heading over there. But first things first, and with that saying in mind, the first thing we need is a generic interface for our DAOs:

The Very Generic GameSummaryDAO Interface

Our GameSummaryDAO will simply define four methods: save, delete, findByPrimaryKey and findAll.


package com.mcnz.dao;

import java.io.*;
import java.util.*;

public interface GameSummaryDAO < T, ID extends Serializable >{

 T save( T entity);
 void delete( T entity);  
 T findByPrimaryKey( ID id);
 List < T > findAll();

}


We've thrown around a few generics in there, namely the T and the ID. Basically, this will simply ensure that every DAO is associated with a serializable primary key (ID), and a specific Java class (T). For this application, our ID will be of type Long, and of course, our associated Java class is the GameSummary class.

You can see how in the class declaration of the HiberanteGameSummaryDAO how the ID and T attributes are provided concrete values:


package com.mcnz.dao;

import java.util.*;
import org.hibernate.*;
import com.mcnz.model.*;

public class HibernateGameSummaryDAO implements GameSummaryDAO <GameSummary, Long > {

}


Implementation Code In, Transaction Details Out

Now, the rule for creating DAOs is that you keep implementation details inside of them so that the implementation isn't exposed to the client. And even more importantly, you keep transaction details outside of them. I can't tell you how many times I've seen people starting and stopping transactions inside of a DAO method. That is wrong, wrong, wrong, wrong wrong! "Implementation code in, transaction details  out," that should be your mantra when coding DAOs. Since we're using Hibernate, the key Hibernate component each DAO needs is a SessionFactory. So, you'll need to declare a SessionFactory instance, define a setter method for that SessionFactory, and also declare a constructor that takes a SessionFactory as an argument. We'll also add in a default constructor, just for fun, but be warned, if someone calls this default constructor and doesn't set a fully mature SessionFactory into that DAO after it is created, you'll be in a world of NullPointerException hurt.


public class HibernateGameSummaryDAO implements GameSummaryDAO <GameSummary, Long>{

  private SessionFactory sessionFactory = null;

  public void setSessionFactory (SessionFactory sessionFactory) {
    this.sessionFactory = sessionFactory;
  }

  public HibernateGameSummaryDAO() {}

  public HibernateGameSummaryDAO (SessionFactory sessionFactory) {
    setSessionFactory(sessionFactory);
  }

}


Implementing & Overriding the Inherited Methods

With the pleasantries of coding a constructor and declaring our SessionFactory instance, we can go ahead and implement the findAll, findByPrimaryKey, save and delete methods. There's really nothing too interesting about them; they simply invoke the corresponding method on the Hibernate Session, each of which we spoke about in the previous tutorial. Here's the completed class, import statements and all:

package com.mcnz.dao;

import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;

import com.mcnz.model.GameSummary;

public class HibernateGameSummaryDAO implements GameSummaryDAO <GameSummary, Long>{

  private SessionFactory sessionFactory = null;

  public void setSessionFactory(SessionFactory sessionFactory) {
    this.sessionFactory = sessionFactory;
  }

  public HibernateGameSummaryDAO(){}
  public HibernateGameSummaryDAO(SessionFactory sessionFactory){
    setSessionFactory(sessionFactory);
  }

  @Override
  public List findAll() {
    Session session = sessionFactory.getCurrentSession();
    Query queryResult = session.createQuery("from GameSummary");
    return queryResult.list();
  }

  @Override
  public GameSummary findByPrimaryKey(Long id) {
    Session session = sessionFactory.getCurrentSession();
    Object o = session.load(GameSummary.class, id);
    return (GameSummary)o;
  }

  @Override
  public GameSummary save(GameSummary entity) {
    Session session = sessionFactory.getCurrentSession();
    session.saveOrUpdate(entity);
    return entity;
  }

  @Override
  public void delete(GameSummary entity) {
    sessionFactory.getCurrentSession().delete(entity);
  }

}


There are a few interesting changes I have made when compared to a previous tutorial. First of all, I used saveOrUpdate in the save method, rather than having separate create and update methods. With the saveOrUpdate method, Hibernate will create a new representation for any entity it is passed that doesn't have a propery primary key, aka id field. If the entity passed in does have an id field, Hibernate will simply perform an update.

Also, I used the load method in the findByPrimaryKey method, as opposed to the get method. The load method is a bit easier on the database, as it doesn't load in every piece of data about the entity, but it does open the door for LazyLoadingExceptions down the road. I typically use get instead of load, but I thought I'd just demonstrate the load method here for andragogal purposes. Here's a more in depth look at the differences between the two methods: The Difference Between the Hibernate Session's Load and Get Methods

Using a DAO in Client Applications

So, we have our DAO. Now all we need is a client application to call it.

I'm going to create a simple little class called the CrudRunnerDAO that will have a simple main method. Since our DAO needs a SessionFactory, the first thing we'll need to do is create a SessionFactory. Once the SessionFactory is created, we create an instance of our DAO by feeding it to the HibernateGameSummaryDAO's constructor.


package com.mcnz.dao;

import org.hibernate.*;
import org.hibernate.cfg.*;
import com.mcnz.model.*;

public class CrudRunnerDAO {

  public static void main(String[] args) {

    /* Initialize the Hibernate Environment */
    AnnotationConfiguration config = new AnnotationConfiguration();
    config.addAnnotatedClass(GameSummary.class);
    config.configure();
    SessionFactory sessionFactory = config.buildSessionFactory();

    /* Create the DAO, passing in the SessionFactory */
    GameSummaryDAO dao = new HibernateGameSummaryDAO(sessionFactory);

    /* more to come!!! */

  }

}


Adding Records with the DAO

With the DAO created and properly initialized, we can go ahead and create instances and save them to the database. Notice that while the DAO takes care of the actual saving and persisting of the data, the client application is responsible for demarcating the transaction.


/* Create a record and keep track of its assigned id */
Long id = null;
{
GameSummary gs = new GameSummary();
gs.setResult("tie");
System.out.println(gs);
sessionFactory.getCurrentSession().beginTransaction();
dao.save(gs);
id = gs.getId();
sessionFactory.getCurrentSession().getTransaction().commit();
System.out.println(gs);
}


Loading and Updating a Record with the Hibernate DAO

The previous code snippet held onto the unique primary key the database assigned our entity when it was saved to the datastore. Using this id, we will now fetch the entity that was just saved. Note that we can do this, as the previous transaction has finished, and because of the placement of the curly braces, the GameSummary instance that was created earlier is now out of scope. 


/* Find and update the created record that has gone out of scope */
sessionFactory.getCurrentSession().beginTransaction();
GameSummary gs = (GameSummary) dao.findByPrimaryKey(id);
gs.setResult("win");
sessionFactory.getCurrentSession().getTransaction().commit();


Querying the Database

After updating the record, we do a fully query on the database using the findAll method of the DAO. We print out each record returned from this query, and notice that the record with our current id has had the result property updated from a tie to a win .

Deleting a Record from the Database Using the Hibernate DAO

Finally, we delete the record we created from the database. When this transaction is complete, we create another transaction, and print out a findAll query from the database. As this query runs, we will see that the record that we created at the beginning of this method has been permanently deleted.

内容概要:本文档详细介绍了Analog Devices公司生产的AD8436真均方根-直流(RMS-to-DC)转换器的技术细节及其应用场景。AD8436由三个独立模块构成:轨到轨FET输入放大器、高动态范围均方根计算内核和精密轨到轨输出放大器。该器件不仅体积小巧、功耗低,而且具有广泛的输入电压范围和快速响应特性。文档涵盖了AD8436的工作原理、配置选项、外部组件选择(如电容)、增益调节、单电源供电、电流互感器配置、接地故障检测、三相电源监测等方面的内容。此外,还特别强调了PCB设计注意事项和误差源分析,旨在帮助工程师更好地理解和应用这款高性能的RMS-DC转换器。 适合人群:从事模拟电路设计的专业工程师和技术人员,尤其是那些需要精确测量交流电信号均方根值的应用开发者。 使用场景及目标:①用于工业自动化、医疗设备、电力监控等领域,实现对交流电压或电流的精准测量;②适用于手持式数字万用表及其他便携式仪器仪表,提供高效的单电源解决方案;③在电流互感器配置中,用于检测微小的电流变化,保障电气安全;④应用于三相电力系统监控,优化建立时间和转换精度。 其他说明:为了确保最佳性能,文档推荐使用高质量的电容器件,并给出了详细的PCB布局指导。同时提醒用户关注电介质吸收和泄漏电流等因素对测量准确性的影响。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值