我正在使用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&@Transactional 注释的 bean时, 它 使用的是未由事务代理包装的bean。因此,没有交易。诀窍(而是正确的方法)是通过以下方式更改我的配置文件:
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 MVC / JPA / Hibernate应用程序。我试图保存一个UserProfile实体来测试我是否真的可以持久化它,但是什么也没有保存,也没有抛出异常。 在控制器方法中,我创建了一个简单的UserProfile(这是一个@Entity),并将其发送到服务方法。类使用 @Service 对类进行批注,并使用 @Transactional 对 addUserPro
我正在使用在Hibernate中指定映射设置。也就是说,我正在使用EntityManager类获取事务。 现在,我的中列出了以下类 另外,在我的Eclipse项目中,我还有两个类(student.java和user.java),它们用注释标记,但没有在文件中列出。 但当我运行我的项目时,Hibernate实际上也映射了这两个类。我的意思是,它还为这两个类创建数据库表(我将设置为)。 它为什么要这样
此代码崩溃: 原因:组织。postgresql。util。PSQLException:错误:关系“订阅”不存在 spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect Springjpa。数据库平台=组织。冬眠地方话PostgreSQL10方言Spring。jpa。冬眠ddl auto=创建拖放
问题内容: 我有两个具有双向@OneToOne映射的类。 我需要编写代码来检索B的所有实例,这些实例没有与之关联的A实例。我还需要为所有没有B的A编写类似的查询。 我努力了: 但这似乎总是返回null。有什么想法吗? 问题答案: 这对两个方向都应该起作用:
我有一个第三方jar,可以容纳所有实体和映射。我目前正在经典的Spring-MVC应用程序中成功使用此jar,但现在我正在尝试在Spring-Boot应用程序中使用它。(1.5.7.发布) 我有这个用于我的应用程序.java: 由于它是第三方,我也必须进行会话扫描,所以我在我的@Configuration类中有这个: 在我的application.properties中: 我收到此错误: 现在表名