【问题标题】:System design to support database connectivity支持数据库连接的系统设计
【发布时间】:2015-07-02 22:59:58
【问题描述】:
我正在尝试开发一个论坛系统作为大学作业的一部分,
其中包含一个数据库连接部分。
我正在用java编写服务器,并决定使用hibernate作为ORM工具来保存和加载数据库。
我的问题不是关于语法,而是关于整个系统的数据库设计。
- 谁应该负责创建会话和提交事务?我应该制作一个接收对象并将其保存到数据库中的单例,并在不同类的每个设置器/构造器中使用这个单例吗?
- 应该直接提交内存对象中的每个更改,还是应该只提交每几个更改? (如果是这样,最好的方法是什么?)
【问题讨论】:
标签:
java
database
architecture
【解决方案1】:
理想情况下,框架应该为您做到这一点。例如,使用 Spring,您可以简单地使用注解将 Spring bean 的方法标记为事务性的,而会话和事务处理将由 Spring 完成:
@Autowired
private SessionFactory sessionFactory;
@Transactional
public void foo() {
Session session = sessionFactory.getCurrentSession();
// do some work with the session
}
而不是
private SessionFactory sessionFactory;
public void foo() {
Session sess = sessionFactory.openSession();
Transaction tx = null;
try {
tx = sess.beginTransaction();
// do some with the session
tx.commit();
}
catch (RuntimeException e) {
if (tx != null) {
tx.rollback();
}
throw e;
}
finally {
sess.close();
}
}
您不应在每次更改后提交,也不应每隔几次更改提交一次。您应该提交原子的、连贯的更改。这就是事务的全部意义:能够从数据库的一个连贯状态转到数据库的另一个连贯状态。
例如,如果将消息发布到主题论坛包含
- 保持消息实例
- 增加论坛的 messageCount 字段
- 为主题海报创建通知
那么这三个更改应该在一个事务中进行,以确保您最终不会导致消息被持久化,但 messageCount 不会增加。
【解决方案2】:
我建议您不要在容器中创建和提交事务,除非您确定要自己完成。在这种情况下,您可以使用 JTA,并使用容器管理事务 (CMT)。还要记住避免 entitymanager-per-operation 反模式。要了解更多信息,请阅读Transactions and Concurrency 并自行决定最适合您的方式。