복붙노트

[SPRING] 엔티티가 지속되지 않음 - Spring + Hibernate + JPA

SPRING

엔티티가 지속되지 않음 - 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);
    }

}

해결법

  1. ==============================

    1.Ok, 나는 문제를 알아 냈다. 그것은 영원히 그것을 파악하는 데 걸렸고 데이터베이스 구성과 관련이 없으므로 비슷한 문제가있는 사람들을 돕고 싶습니다.

    Ok, 나는 문제를 알아 냈다. 그것은 영원히 그것을 파악하는 데 걸렸고 데이터베이스 구성과 관련이 없으므로 비슷한 문제가있는 사람들을 돕고 싶습니다.

    Spring 문서에는 다음 내용이 나와 있습니다.

    내 원본 게시물에 게시되지 않은 내용은 다음과 같은 구성 코드 행을 가진 내 서블릿 정의입니다.

    myServlet.xml

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

    이것은 컨트롤러, 서비스 및 저장소를 포함하여 주석이 달린 모든 bean을 응용 프로그램 컨텍스트가 아닌 서블릿 컨텍스트로 가져옵니다. 그리고 그 안에 문제가 있습니다. Spring이 @Transactional로 주석 처리 된 빈을 찾으면 (내 config.xml 파일에 이 존재하기 때문에) 애플리케이션 컨텍스트에서 빈을 찾는다. 그리고, 내 이전의 스레드에 게시 된 내 구성을 기반으로 내 응용 프로그램 컨텍스트에로드되는 콩이 없습니다 ... 그들은 모두 서블릿 컨텍스트에 있습니다. 따라서 내 서블릿이 @Service & @Transactional로 주석 처리 된 빈을 호출 할 때 트랜잭션 프록시가 래핑하지 않은 빈을 사용하고있었습니다. 따라서 트랜잭션이 없습니다. 트릭 (정확한 방법)은 다음과 같은 방법으로 설정 파일을 변경하는 것이 었습니다.

    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" /> 
    

    이 구성을 사용하면 모든 컨트롤러가 서블릿 컨텍스트에 있고 트랜잭션 서비스 및 리포지토리가 속해있는 응용 프로그램 컨텍스트에 존재하는지 확인할 수 있습니다. 그리고 마지막으로, 많은 불면의 밤 이후, 내 데이터베이스 쓰기가 지속됩니다.

  2. ==============================

    2.다음과 같이 servlet-context.xml에 컨트롤러를 제공 할 수 있습니다.

    다음과 같이 servlet-context.xml에 컨트롤러를 제공 할 수 있습니다.

        <context:component-scan base-package="com.myDomain" use-default-filters="false" >
            <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        </context:component-scan>
    

    이렇게하면 컨트롤러 만 서블릿 컨텍스트에만 존재하게됩니다. root-context.xml에서 다음을 사용하십시오.

        <context:component-scan base-package="com.myDomain">
            <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        </context:component-scan>
    

    이렇게하면 컨트롤러 이외의 구성 요소가 응용 프로그램 컨텍스트에 있는지 확인할 수 있습니다. 이 JPA가 데이터베이스를 업데이트하지 않고서이 솔루션을 많이 검색했습니다. 이것이 누군가를 도울 수 있기를 바랍니다.

  3. from https://stackoverflow.com/questions/6483006/entities-not-persisting-spring-hibernate-jpa by cc-by-sa and MIT license