java hibernate BO传递外键作为DAO参数(架构设计)

时间:2013-04-16 18:42:25

标签: java hibernate orm

我遇到了以下架构问题(文本很长,但对于有经验的Java开发人员来说问题应该很容易):

我正在学习Java,我正在开发一个使用Hibernate的简单数据库应用程序。我被建议使用BO和DAO模式来访问数据库。简而言之,DAO是HQL / ORM层(创建,获取,更新,删除等),业务对象执行更抽象的逻辑内容(通过某些标准检索所有记录,获得总和等)。

我想通过BO / DAO在树中创建或移动节点。每个节点都有它的父节点,它用hibernate映射如下:

@Entity
@Table(name = "category")
public class Category {

    @ManyToOne
    @JoinColumn(name="parent_id")
    private Category parent;

    public Category getParent() {
        return parent;
    }

    public void setParent(Category parent) {
        this.parent = parent;
    }

现在,我希望BO能够createmove类别对象,这些方法采用id参数:

public abstract void createCategory(int parent_id, String name, CategoryType type);
public abstract void moveCategory(int category_id, int new_parent_id);

当实现上面的BO方法时,我试图使用hibernate的session.load来延迟加载外键关系:

session.load(Category.class, parent_id)

public void createCategory(int parent_id, String name, CategoryType type) {
    Category category = new Category();
    category.setName(name);
    category.setParent(session.load(Category.class, parent_id));
    category.setType(type);
    this.categoryDao.save(category);
}

DAO应该保持hibernate会话(确切地说,是抽象DAO接口的DAO-hibernate实现),但是没有其他类应该知道像hibernate会话这样的东西存在。特别是,BO不应该对hibernate会话有任何引用。以上代码无法编译(session未知)。

我的问题是 - 我犯了什么错误,如何将其设计为有用/弹性/优雅?我应该提供Category::setParentId()方法来临时存储父节点ID,并且 - 在执行DAO的创建/更新时 - 检查它是否已设置并相应处理?或者可能有更好的解决方案?

2 个答案:

答案 0 :(得分:0)

您应该将方法标记为@Transactional(在xml设置中添加事务支持)。然后在dao中创建2个方法:getCategorysaveCategory(您已经 - save)并使用dao方法进行操作,但不使用业务层中的hibernate会话。

@Transactional
public void createCategory(int parent_id, String name, CategoryType type) {
...
}

答案 1 :(得分:0)

以下模式可以帮助您: 让我们举一个例子,如果有一个业务功能在表Foo上运行。

通用DAO

@Repository
public abstract class DAO<T>
{
    @Autowired
    SessionFactory factory;

    /**
    * Some sample generic methods
    */
    public Session getCurrentSession()
    {
        return factory.getCurrentSession();
    }

    public void create(T record) {
        getCurrentSession().save(record);
    }

    public void update(T record) {
        getCurrentSession().update(record);
    }

    public void delete(T record) {
        getCurrentSession().delete(record);
    }

    public T get(Class<T> clazz, Integer id) {
        return (T) getCurrentSession().get(clazz, id);
    }

    /**
    * Rest of the generic dao methods follow
    */
}

通用BO

@Transactional
public abstract class BO<T>
{
    public abstract DAO<T> getDAO();

    /**
    * Some sample generic methods
    */
    public abstract void create(T record);

    public abstract void update(T record);

    public abstract void delete(T record);

    public abstract T get(Class<T> clazz, Integer id);

    /**
    * Rest of the generic business methods follow
    */
}

特定DAO

@Transactional
@Repository
public FooDAO extends DAO<Foo>
{
}

特定BO

@Transactional
public FooBO extends BO<Foo>
{
    @AutoWired
    FooDAO dao;

    @Override
    public DAO<Foo> getDAO() 
    {
        return dao;
    }

    @Override 
    public void create(T record){ 
        dao.create(record);
    }

    @Override 
    public void update(T record) { 
        dao.update(record);
    }

    @Override 
    public void delete(T record) { 
        dao.delete(record); 
    }

    @Override 
    public T get(Class<T> clazz, Integer id) { 
        return dao.get(Foo.class, id); 
    }
}