我遇到了以下架构问题(文本很长,但对于有经验的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能够create
或move
类别对象,这些方法采用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的创建/更新时 - 检查它是否已设置并相应处理?或者可能有更好的解决方案?
答案 0 :(得分:0)
您应该将方法标记为@Transactional
(在xml设置中添加事务支持)。然后在dao中创建2个方法:getCategory
和saveCategory
(您已经 - 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);
}
}