gpt4 book ai didi

hibernate - 实体不持久 - Spring + Hibernate + JPA

转载 作者:行者123 更新时间:2023-12-04 05:14:40 25 4
gpt4 key购买 nike

我正在使用 Spring + Hibernate + JPA,但我遇到了无法让我的实体持久保存到数据库的情况。我已经设置了一个使用@Transactional 注释的服务类。它使用包含注入(inject)的 EntityManager 的 DAO。当我在服务对象上调用该函数时,我看到 DAO 正在执行的读取的一堆选择,但由于我的 DAO 发出的合并和删除,没有更新/删除。我的设置肯定有问题,但我看不到。

持久性.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>

配置文件
<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/> only looks for @Transactional on beans in the same application context it is defined in. This means that, if you put <tx:annotation-driven/> in a WebApplicationContext for a DispatcherServlet, it only checks for @Transactional beans in your controllers, and not your services. See Section 15.2, “The DispatcherServlet” for more information.



我原来的帖子中没有发布的是我的 servlet 定义,它有以下几行配置代码:

我的Servlet.xml
<context:annotation-config /> 
<context:component-scan base-package="com.myDomain.*" />

这会将所有带注释的 bean,包括 Controller 、服务和存储库,带入 servlet 上下文而不是应用程序上下文。这就是问题所在。当 Spring 查找带有 @Transactional 注释的 bean 时(由于我的 config.xml 文件中存在 <tx:annotation-driven/>),它正在应用程序上下文中查找它们。而且,根据我在上一个线程中发布的配置,没有 bean 被加载到我的应用程序上下文中……它们都在 servlet 上下文中。因此,当我的 servlet 调用带有 @Service 和 @Transactional 注释的 bean 时,它是 使用未被事务代理包裹的 bean .因此,没有交易。诀窍(确切地说,正确的方法)是通过以下方式更改我的配置文件:

我的Servlet.xml
<context:annotation-config /> 
<context:component-scan base-package="com.myDomain.servlets" />

配置文件
<context:annotation-config /> 
<context:component-scan base-package="com.myDomain.dao" />
<context:component-scan base-package="com.myDomain.services" />

此配置确保所有 Controller 都存在于 servlet 上下文中,事务服务和存储库存在于应用程序上下文中,这是它们所属的位置。最后,经过许多不眠之夜,我的数据库写入仍然存在。

关于hibernate - 实体不持久 - Spring + Hibernate + JPA,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6483006/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com