如何在 Spring / Hibernate 事务中包装 Wicket 页面渲染?

发布于 2024-11-10 04:53:51 字数 545 浏览 2 评论 0原文

我的应用程序从 Hibernate DAO 加载实体,并使用 OpenSessionInViewFilter 来允许渲染。

在某些情况下,我想对字段进行较小的更改 -

Long orderId ...

link = new Link("cancel") {
    @Override public void onClick() {
        Order order = orderDAO.load(orderId);
        order.setCancelledTime(timeSource.getCurrentTime());       
    };

但这样的更改不会持久,因为 OSIV 不会刷新。

在这些情况下必须调用 orderDOA.save(order) 似乎真的很遗憾,但我不想更改 OSIV 上的 FlushMode。

有没有人找到任何方法将“请求处理”(例如 onClick)声明为需要事务?

理想情况下,我认为事务将在请求周期的早期启动,并由 OSIV 提交,以便所有逻辑和渲染都将在同一事务中进行。

My application loads entities from a Hibernate DAO, with OpenSessionInViewFilter to allow rendering.

In some cases I want to make a minor change to a field -

Long orderId ...

link = new Link("cancel") {
    @Override public void onClick() {
        Order order = orderDAO.load(orderId);
        order.setCancelledTime(timeSource.getCurrentTime());       
    };

but such a change is not persisted, as the OSIV doesn't flush.

It seems a real shame to have to call orderDOA.save(order) in these cases, but I don't want to go as far as changing the FlushMode on the OSIV.

Has anyone found any way of declaring a 'request handling' (such as onClick) as requiring a transaction?

Ideally I suppose the transaction would be started early in the request cycle, and committed by the OSIV, so that all logic and rendering would take place in same transaction.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

这个俗人 2024-11-17 04:53:51

我通常更喜欢使用包装基本 DAO 的附加“服务”代码层
逻辑并通过@Transactional 提供事务。这使我可以更好地分离表示与业务逻辑,并且
更容易测试。

但是由于您已经使用了 OSIV,您可能可以在代码中放置一些 AOP 拦截器
并让它执行flush()?

I generally prefer to use additional 'service' layer of code that wraps basic DAO
logic and provides transactions via @Transactional. That gives me better separation of presentation vs business logic and is
easier to test.

But since you already use OSIV may be you can just put some AOP interceptor around your code
and have it do flush()?

凝望流年 2024-11-17 04:53:51

免责声明:我从未真正尝试过这个,但我认为它会起作用。这也可能比您想要编写的代码多一点。最后,我假设您的 WebApplication 是 SpringWebApplication 的子类。到目前为止你还和我在一起吗?

该计划是告诉 Spring 我们要在事务中运行 onClick 方法的语句。为了做到这一点,我们必须做三件事。

第 1 步:将 PlatformTransactionManager 注入您的网页:

@SpringBean
private PlatformTransactionManager platformTransactionManager;

第 2 步:在您的网页中创建一个静态 TransactionDefinition,我们稍后将引用它:

protected static final TransactionDefinition TRANSACTION_DEFINITION;
static {
    TRANSACTION_DEFINITION = new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
    ((DefaultTransactionDefinition) TRANSACTION_DEFINITION).setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);
}

随意更改 TransactionDefinition 设置和/或将定义移动到适当的共享位置。这一特定定义指示 Spring 启动一个新事务(即使已经启动了一个事务)并使用最大事务隔离级别。

第 3 步:将事务管理添加到 onClick 方法中:

link = new Link("cancel") {
    @Override 
    public void onClick() {
        new TransactionTemplate(platformTransactionManager, TRANSACTION_DEFINITION).execute(new TransactionCallback() {
            @Override
            public Object doInTransaction(TransactionStatus status) {
                Order order = orderDAO.load(orderId);
                order.setCancelledTime(timeSource.getCurrentTime());      
            }
        }
    } 
};

这样就可以解决问题了!

Disclaimer : I've never actually tried this, but I think it would work. This also may be a little bit more code than you want to write. Finally, I'm assuming that your WebApplication subclasses SpringWebApplication. Are you with me so far?

The plan is to tell Spring that we want to run the statements of you onClick method in a transaction. In order to do that, we have to do three things.

Step 1 : inject the PlatformTransactionManager into your WebPage:

@SpringBean
private PlatformTransactionManager platformTransactionManager;

Step 2 : create a static TransactionDefinition in your WebPage that we will later reference:

protected static final TransactionDefinition TRANSACTION_DEFINITION;
static {
    TRANSACTION_DEFINITION = new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
    ((DefaultTransactionDefinition) TRANSACTION_DEFINITION).setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);
}

Feel free to change the TransactionDefinition settings and/or move the definition to a shared location as appropriate. This particular definition instructs Spring to start a new transaction even if there's already one started and to use the maximum transaction isolation level.

Step 3 : add transaction management to the onClick method:

link = new Link("cancel") {
    @Override 
    public void onClick() {
        new TransactionTemplate(platformTransactionManager, TRANSACTION_DEFINITION).execute(new TransactionCallback() {
            @Override
            public Object doInTransaction(TransactionStatus status) {
                Order order = orderDAO.load(orderId);
                order.setCancelledTime(timeSource.getCurrentTime());      
            }
        }
    } 
};

And that should do the trick!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文