我知道这个问题很多,但我被困住了。我将我的项目从本教程开始:http://www.cavalr.com/blog/Spring_3_and_Annotation_Based_Hibernate_4_Example
这是我的root-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="initialPoolSize" value="1" />
<property name="minPoolSize" value="1" />
<property name="maxPoolSize" value="20" />
</bean>
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:db.properties</value>
</list>
</property>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan" value="com.joe.recipes.data" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<!-- Enables the Hibernate @Transactional programming model -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
</beans>
这是我的servlet-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<context:component-scan base-package="com.joe.recipes" />
<!-- Enables the Spring MVC @Controller programming model -->
<mvc:annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
</beans:beans>
这是我的AbstractDaoImpl
public abstract class AbstractDaoImpl<E, I extends Serializable> implements AbstractDao<E,I> {
private Class<E> entityClass;
protected AbstractDaoImpl(Class<E> entityClass) {
this.entityClass = entityClass;
}
@Autowired
private SessionFactory sessionFactory;
public Session getCurrentSession() {
return sessionFactory.getCurrentSession();
}
@SuppressWarnings("unchecked")
@Override
public E findById(I id) {
return (E) getCurrentSession().get(entityClass, id);
}
@Override
public void saveOrUpdate(E e) {
getCurrentSession().saveOrUpdate(e);
}
@Override
public void delete(E e) {
getCurrentSession().delete(e);
}
@Override
public List findByCriteria(Criterion criterion) {
Criteria criteria = getCurrentSession().createCriteria(entityClass);
criteria.add(criterion);
return criteria.list();
}
}
这是我的RecipeDaoImpl
班级
@Repository
public class RecipeDaoImpl extends AbstractDaoImpl<Recipe, String> implements RecipeDao {
protected RecipeDaoImpl() {
super(Recipe.class);
}
@Override
public boolean saveRecipe(Recipe r) {
return saveRecipe(r);
}
@Override
public Recipe getRecipe(String recipeId) {
return findById(recipeId);
}
@SuppressWarnings("unchecked")
@Override
public List<Recipe> findRecipes(String keyword) {
return findByCriteria( Restrictions.and( Restrictions.like("name", keyword, MatchMode.ANYWHERE),
Restrictions.like("keywords", keyword, MatchMode.ANYWHERE) ) );
}
}
这是我的RecipeServiceImpl
班级
@Service("recipeService")
@Transactional(readOnly = true)
public class RecipeServiceImpl implements RecipeService {
@Autowired
private RecipeDao recipeDao;
@Override
@Transactional(readOnly = false)
public boolean saveRecipe(Recipe r) {
return recipeDao.saveRecipe(r);
}
@Override
public Recipe getRecipe(String recipeId) {
return recipeDao.getRecipe(recipeId);
}
@Override
public List<Recipe> findRecipes(String keyword) {
return recipeDao.findRecipes(keyword);
}
}
这是我的RecipeController
/**
* Handles requests for the application home page.
*/
@Controller
public class RecipeController {
private static final Logger logger = LoggerFactory.getLogger(RecipeController.class);
@Autowired
private RecipeService recipeService;
/**
* Adds recipes to the DB
*/
@RequestMapping(value = "/add", method = RequestMethod.GET)
public String add(Locale locale, Model model) {
return "add";
}
/**
* Searches for recipes
*/
@RequestMapping(value = "/search", method = RequestMethod.POST)
public String search(@RequestParam(value="keyword", required=true) String keyword, Model model) {
List<Recipe> recipes = recipeService.findRecipes(keyword);
System.out.println( "Results:"+ recipes.size() );
return "results";
}
/**
* Logs in the user
*/
@RequestMapping(value = "/login", method = RequestMethod.POST)
public String login(Locale locale, Model model) {
return "login";
}
}
我已尝试将@Transactional
放在RecipeDaoImpl
班级和AbstractDaoImpl
班级上,但都没有奏效。
编辑: 我通过捕获异常并打开一个新异常来解决这个问题:
public Session getCurrentSession() {
Session session = null;
try {
session = sessionFactory.getCurrentSession();
} catch ( HibernateException he ) {
session = sessionFactory.openSession();
}
return session;
}
答案 0 :(得分:0)
它是什么意思&#34;既不起作用又#34 ;?你的问题是什么?
我认为您的问题是@EnableTransactionManagement,并且只在它们定义的相同应用程序上下文中查找bean上的@Transactional。这意味着,如果您在WebApplicationContext中为DispatcherServlet添加注释驱动配置,它只会检查@控制器中的事务bean,而不是您的服务。
在application-context.xml中尝试
<context:component-scan base-package="path.to.your.models, path.to.your.daos, path.to.your.services"/>
在servlet-context.xml中
<context:component-scan base-package="com.springhibernatejpatest.controllers"/>
答案 1 :(得分:0)
您的“修复”实际上是一个危险的修复,因为您正在Springs事务管理范围之外打开一个新会话。这最终将导致连接泄漏,内存问题和稳定性问题。
真正的问题是您的根上下文中有<tx:annotation-driven />
,并且您要进行组件扫描DispatcherServlet
加载的上下文。将<tx:annotation-driven />
移到DispatcherServlet
加载的上下文中以真正解决您的问题。
或将组件扫描分为2个,根上下文应扫描除控制器外的所有内容
<context:component-scan base-package="com.joe.recipes">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
,并且调度程序servlet应该仅检测与Web相关的bean。
<context:component-scan base-package="com.joe.recipes" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
现在您可以将<tx:annotation-driven />
留在原处了。