正确使用spring mvc 3与hibernate(Spring ORM) [英] Proper usage of Spring mvc 3 with hibernate (Spring ORM)

查看:110
本文介绍了正确使用spring mvc 3与hibernate(Spring ORM)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开始一个新项目,尝试做正确的事情(所以不止一个问题),我可能需要一些帮助,我不确定我做错了什么:


  1. Spring上下文

  2. 管理员

  3. 服务界面
  4. 服务实施
  5. DAO界面

  6. DAO实施

我想尽可能多地使用spring MVC,我如何让@Transactional处理会话开启/关闭?



如何捕获异常(即不存在记录或数据库失败)(如果有的话)。即我的数据库不接受这样的重复条目:

  com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException:重复入门

我怎样才能看到这个?



对于我接下来的每一个请求,我都会得到这个异常:

  org.hibernate.AssertionFailure:null com.test中的id。 spring.ws.service.impl.TestObject条目(发生异常后不刷新会话)

我做错了什么?任何人都可以在我的项目中提出一些改进建议吗?

解决方案

组件扫描 b

首先要做的是:您使用@Controller,@Service,@Repository和@Autowired,但您不会对它们做任何事情。我建议使用类路径扫描

 < context:component- scan base-package =com.test.spring.ws/> 

这将通过注释找到并创建这些bean,而不是要求您在XML中声明它们。将@Autowired添加到您的服务中的 testServiceDAO 字段以及DAO中的 sessionFactory 字段。删除这些字段的setters。他们不再需要。组件扫描标签也会为您自动装配。要使用上下文命名空间,您需要将它添加到根元素。例如:

 < beans xmlns =http://www.springframework.org/schema/beans
xmlns:xsi =http://www.w3.org/2001/XMLSchema-instance
xmlns:context =http://www.springframework.org/schema/context
xsi :schemaLocation =
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd\">

交易管理

使用@Transactional ,正如Sean所说,你需要为你的spring上下文文件添加一个元素:

 < tx:annotation-驱动/> 

由于您的事务管理器bean被命名为transactionManager,它会自动找到它。您还需要将tx名称空间添加到根元素,因此它应该类似于: =http://www.springframework.org/schema/beans
xmlns:xsi =http://www.w3.org/2001/XMLSchema-instance
xmlns:context = http://www.springframework.org/schema/context
xmlns:tx =http://www.springframework.org/schema/tx
xsi:schemaLocation =
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework。 org / schema / tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd\">

为了有这个机会,你需要删除 session .beginTransaction() session.close()。以这种方式开放自己的交易是混合程序化的和声明式的交易划界,而陈述式的方式通常更好。此外,您绝对不应在实际项目中关闭DAO中的会话。这会让你陷入各种麻烦中。

异常处理

MySQLIntegrityConstraintViolationException 是一个特定于数据库的异常,它将被Hibernate捕获并包装在 ConstraintViolationException ,这就是你的DAO会出现的问题;但是,由于您的DAO现在是@Repository,您可以从Spring的例外翻译。有了这个,Hibernate异常将被Spring捕获并转换为 DataIntegrityViolationException 。数据库异常处理总是很有趣!



会话管理

OpenSessionInViewFilter 的OpenSessionInViewInterceptor ?如果是这样,一个Hibernate会话在第一次收到请求时打开,在写入响应后关闭。如果不是,那么会话在事务开始之前(在@Transactional方法中)才会启动,并且在事务完成时它会关闭。使用过滤器/拦截器,您可以在视图层执行需要调用回数据库的事情 - 特别是当您需要渲染视图时需要惰性关系或延迟加载的对象时。如果会话不可用 - 因为它不是只存在于事务服务方法的长度 - 您不能在视图中执行这些操作,并且您将看到臭名昭着的LazyInitializationException



至于发生异常后不会刷新会话错误,我没有立即看到任何会让我认为应该发生的事情。也许你的Web层Spring上下文中的某些东西是错误配置的,或者在你如何直接在DAO中处理事务和会话方面存在一些奇怪的相互作用。


I'm starting a new project, trying to do things right this time(so more than one question), I might need some help, I'm not sure what I'm doing wrong :

  1. Spring context
  2. Controller
  3. Service Interface
  4. Service Implementation
  5. DAO interface
  6. DAO implementation

I want to utilize spring MVC as much as possible, how do I make session opening/closing handled by @Transactional?

How do I catch the exceptions(i.e. non existing record or database failed) if any. i.e My database doesn't accept duplicate entries like this one :

com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry

How can I catch this?

And for every next request I make I get this exception :

org.hibernate.AssertionFailure: null id in com.test.spring.ws.service.impl.TestObject entry (don't flush the Session after an exception occurs)

What I'm doing wrong? Can anyone suggest some improvements in my project?

解决方案

Component Scan

First things first: you're using @Controller, @Service, @Repository, and an @Autowired, but you don't do anything with them. I recommend using classpath scanning. Remove the "testServiceDAO" and "testService" beans from your spring context file, and instead use:

<context:component-scan base-package="com.test.spring.ws"/>

That will find and create those beans by their annotations instead of requiring you to declare them in the XML. Add @Autowired to the testServiceDAO field in your service and to the sessionFactory field in your DAO. Remove the setters for these fields. They're no longer needed. The component-scan tag will also do the autowiring for you. To use the context namespace, you need to add it to your root element. For example:

<beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:context="http://www.springframework.org/schema/context"
     xsi:schemaLocation="
         http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
         http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context-3.0.xsd">

Transaction Management

To use @Transactional, as Sean said, you need to add an element to your spring context file:

<tx:annotation-driven/>

Since your transaction manager bean is named "transactionManager", it will find it automatically. You also need to add the "tx" namespace to your root element, so it should look something like:

<beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:context="http://www.springframework.org/schema/context"
     xmlns:tx="http://www.springframework.org/schema/tx"
     xsi:schemaLocation="
         http://www.springframework.org/schema/beans 
         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
         http://www.springframework.org/schema/tx 
         http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
         http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context-3.0.xsd">

For this to have any chance of working, you need to remove both session.beginTransaction() and session.close() from your DAO method. Opening your own transaction in that way is mixing programmatic and declarative transaction demarcation, and the declarative way is usually better. Also, you should never ever close a session in a DAO in a real project. That will get you into all kinds of trouble.

Exception Handling

Your MySQLIntegrityConstraintViolationException, being a database-specific exception, would be caught by Hibernate and wrapped in a ConstraintViolationException, which is what would come out of your DAO; however, since your DAO is a @Repository now, you can benefit from Spring's exception translation. With this, the Hibernate exception will be caught by Spring and translated to a DataIntegrityViolationException. Database exception handling is always fun!

Session Management

Are you using an OpenSessionInViewFilter or OpenSessionInViewInterceptor? If so, a Hibernate session is opened when a request is first received and closed after the response is written. If not, then the session doesn't start until a transaction begins (at an @Transactional method), and it's closed when that transaction finishes. With the filter/interceptor, you can do things in the "view" tier that require calling back to the database--specifically when you have lazy relationships or lazy-loaded objects that you need for rendering the view. If the session isn't available--as it isn't if it only exists for the length of the transactional service method--you can't do those things in the view and you'll get the infamous LazyInitializationException.

As for the "don't flush the Session after an exception occurs" error you're getting, I don't see anything immediately that would make me think that should happen. Perhaps something in your web-tier spring context is misconfigured, or maybe there's some weird interplay in how you're handling the transaction and session directly in the DAO.

这篇关于正确使用spring mvc 3与hibernate(Spring ORM)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆