实体不存在-spring+hibernate+ JPA

我正在使用Spring + Hibernate+JPA,但遇到无法将实体持久保存到数据库的情况。我已经建立了一个带有@Transactional注释的服务类。它使用包含注入的EntityManager的DAO。当我在服务对象上调用函数时,我看到DAO正在进行大量的选择读取,但是由于我的DAO发出的合并和删除操作,没有更新/删除。当然,我的设置有问题,但是我看不到它。

persistence.xml

<persistence xmlns="http://java.sun.com/xml/ns/persistence"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"

version="1.0">

<persistence-unit name="pu">

<properties>

<property name="hibernate.dialect" value="org.hibernate.dialect.InformixDialect" />

<property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider" />

<property name="hibernate.showsql" value="true" />

<property name="hibernate.cache.use_second_level_cache"

value="false" />

</properties>

</persistence-unit>

config.xml

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:security="http://www.springframework.org/schema/security"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:tx="http://www.springframework.org/schema/tx"

xmlns:p="http://www.springframework.org/schema/p"

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/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd

http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd

http://www.springframework.org/schema/security

http://www.springframework.org/schema/security/spring-security-3.0.3.xsd

http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"

destroy-method="close">

<property name="driverClassName" value="org.postgresql.Driver" />

<property name="url" value="jdbc:postgresql://localhost:5432/testdb" />

<property name="username" value="username" />

<property name="password" value="password" />

</bean>

<bean id="entityManagerFactory"

class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">

<property name="persistenceUnitName" value="pu" />

<property name="dataSource" ref="dataSource" />

<property name="jpaVendorAdapter">

<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">

<property name="showSql" value="true" />

<property name="databasePlatform" value="org.hibernate.dialect.PostgreSQLDialect" />

</bean>

</property>

<property name="loadTimeWeaver">

<bean

class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>

</property>

</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"

p:entityManagerFactory-ref="entityManagerFactory" />

<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>

<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>

<context:annotation-config/>

</beans>

AccountService.java

@Service("accountService")

@Transactional(propagation=Propagation.REQUIRED)

public class AccountService {

private static final Logger log = Logger.getLogger(AccountService.class);

@Autowired

private UserDAO userDAO;

public void activateUser(String username, String activationCode) {

PendingActivation pendingActivation = userDAO.getPendingActivation(

username, activationCode);

Client client = pendingActivation.getClient();

if (!userDAO.removePendingActivation(pendingActivation)) {

log.warn("Unable to remove pending activation");

}

if (!userDAO.enableUser(client)) {

log.error("Unable to enable client");

return;

}

return;

}

}

UserDAOImpl.java

@Repository("userDAO")

public class UserDAOImpl implements UserDAO, Serializable {

private static final long serialVersionUID = 1L;

private static Logger log = Logger.getLogger(UserDAOImpl.class);

@PersistenceContext

EntityManager em;

@Override

public PendingActivation getPendingActivation(String username, String activationCode) {

Query q = em.createNamedQuery("getActivationCode")

.setParameter("activationCode", activationCode);

PendingActivation pendingActivation = null;

try {

pendingActivation = (PendingActivation)q.getSingleResult();

return pendingActivation;

}

catch (Exception e) {

log.warn("Could not retrieve activation code " + activationCode + " for user " + username, e);

return null;

}

}

@Override

public boolean enableUser(Client client) {

try {

client.setEnabled(true);

client = em.merge(client); // this never generates an update

}

catch(Exception e) {

log.error("Unable to enable client: " + client.getUsername(), e);

return false;

}

return true;

}

@Override

public boolean removePendingActivation(PendingActivation pendingActivation) {

try {

pendingActivation = (PendingActivation)em.getReference(PendingActivation.class, pendingActivation.getPendingActivationId());

em.remove(pendingActivation); // this never generates a delete

}

catch(Exception e) {

log.warn("Unable to remove activation: " + pendingActivation.getActivationCode(), e);

return false;

}

return true;

}

}

AccountActivationController.java

@Controller

public class AccountActivationController {

@Autowired

@Qualifier("accountService")

AccountService accountService;

@RequestMapping("activate.do")

public String doActivate(

@RequestParam("activationCode") String activationCode,

@RequestParam("username") String username,

ModelMap model) {

UnitCriteria unitCriteria = accountService.activateUser(username, activationCode);

if (unitCriteria == null) {

return "account/activationError";

}

model.addAttribute("fromActivation", true);

return "forward:search.do?" + unitCriteria.toUrlParams(true);

}

}

回答:

好的,我知道了问题所在。我花了很长时间才弄清楚这一点,与我的数据库配置无关,所以我想为遇到类似问题的人们提供帮助。

Spring文档指出以下内容:

<tx:annotation-driven/>仅在定义的相同应用程序上下文中在bean上查找@Transactional。这意味着,如果<tx:annotation- driven/>为DispatcherServlet 放入 WebApplicationContext,则仅在控制器而不是服务中检查@Transactional bean。有关更多信息,请参见第15.2节“ DispatcherServlet”。

我的原始帖子中没有发布的是我的Servlet定义,其中包含以下几行配置代码:

myServlet.xml

<context:annotation-config /> 

<context:component-scan base-package="com.myDomain.*" />

这会将所有带注释的Bean(包括控制器,服务和存储库)带入Servlet上下文而不是应用程序上下文。问题就在这里。当Spring寻找用@Transactional注释的bean(由于<tx:annotation-

driven/>config.xml文件中存在)时,它将在应用程序上下文中寻找它们。而且,根据我在上一个线程中发布的配置,没有将任何bean加载到我的应用程序上下文中……它们都在servlet上下文中。因此,当我的servlet调用以@Service&@ 注释的 它 。因此,没有交易。诀窍(而是正确的方法)是通过以下方式更改我的配置文件:

myServlet.xml

<context:annotation-config /> 

<context:component-scan base-package="com.myDomain.servlets" />

config.xml

<context:annotation-config /> 

<context:component-scan base-package="com.myDomain.dao" />

<context:component-scan base-package="com.myDomain.services" />

此配置确保所有Controller都存在于servlet上下文中,而Transactional Services和Repository存在于 _它们所属_的应用程序上下文中。最后,经过许多不眠之夜,我的数据库写操作仍在继续。

以上是 实体不存在-spring+hibernate+ JPA 的全部内容, 来源链接: utcz.com/qa/397312.html

回到顶部