0

我遇到了以下架构问题(文本很长,但对于有经验的 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 能够createmoveCategory 对象,这些方法带有一个id参数:

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

在实现上述 BO 方法时,我正在尝试使用 hibernatesession.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 应该保持休眠会话(准确地说,是抽象 DAO 接口的 DAO-休眠实现),但没有其他类应该知道存在任何类似于休眠会话的东西。特别是,BO 不应该对休眠会话有任何引用。并且上面的代码不能编译(session未知)。

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

4

2 回答 2

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); 
    }
}
于 2013-04-17T05:23:19.147 回答
0

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

@Transactional
public void createCategory(int parent_id, String name, CategoryType type) {
...
}
于 2013-04-17T00:29:22.657 回答