Spring Data JPA - save()没有持久化

时间:2014-08-27 01:14:22

标签: hibernate jpa spring-data spring-data-jpa

我试图让Spring Data JPA项目工作。我的数据不会保留在employeeManager.addEmployee(employee)上(见下文)。

实体:

package com.howtodoinjava.entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import org.springframework.data.neo4j.annotation.Indexed;

@Entity
@Table(name = "EMPLOYEE")
@SuppressWarnings("SerializableClass")
public class EmployeeEntity {

    @Id
    @Column(name = "ID")
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long id;

    @Column(name = "FIRSTNAME")
    private String firstname;

    @Column(name = "LASTNAME")
    private String lastname;

    @Indexed
    @Column(name = "EMAIL")
    private String email;

    @Column(name = "TELEPHONE")
    private String telephone;

    public String getEmail() {
        return email;
    }

    public String getTelephone() {
        return telephone;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public void setTelephone(String telephone) {
        this.telephone = telephone;
    }

    public String getFirstname() {
        return firstname;
    }

    public String getLastname() {
        return lastname;
    }

    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }

    public void setLastname(String lastname) {
        this.lastname = lastname;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }
}

服务:

package com.howtodoinjava.service;

import com.howtodoinjava.entity.EmployeeEntity;
import com.howtodoinjava.repository.jpa.EmployeeJpaRepository;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.neo4j.helpers.collection.IteratorUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional
public class EmployeeManagerJpa implements EmployeeManager {

    @Autowired
    private EmployeeJpaRepository employeeRepository;

    @Transactional
    public void addEmployee(EmployeeEntity employee) {
        employeeRepository.save(employee);
    }

    @Transactional
    public List<EmployeeEntity> getAllEmployees() {
        return (List<EmployeeEntity>) makeCollection(employeeRepository.findAll());
    }

    @Transactional
    public void deleteEmployee(Long employeeId) {
        employeeRepository.delete(getEmployee(employeeId));
    }

    @Transactional
    public EmployeeEntity getEmployee(Long employeeId) {
        return employeeRepository.findOne(employeeId);
    }

    public static <E> Collection<E> makeCollection(Iterable<E> iter) {
        Collection<E> list = new ArrayList<E>();
        for (E item : iter) {
            list.add(item);
        }
        return list;
    }
}

存储库:

package com.howtodoinjava.repository.jpa;

import com.howtodoinjava.entity.EmployeeEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.CrudRepository;

public interface EmployeeJpaRepository extends JpaRepository<EmployeeEntity, Long> {}

应用程序上下文分为两个文件(在web.xml的context-param中读取为employee-servlet-*.xml): employee-servlet-app.xml:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:jpa="http://www.springframework.org/schema/data/jpa" 
       xmlns:neo4j="http://www.springframework.org/schema/data/neo4j"
       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/context
            http://www.springframework.org/schema/context/spring-context.xsd            
            http://www.springframework.org/schema/data/jpa
            http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
            http://www.springframework.org/schema/data/neo4j
            http://www.springframework.org/schema/data/neo4j/spring-neo4j.xsd
            http://www.springframework.org/schema/tx 
            http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

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

    <tx:annotation-driven mode="proxy" transaction-manager="transactionManager" />

    <bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
        <property name="prefix" value="/WEB-INF/view/" />
        <property name="suffix" value=".jsp" />
    </bean> 
</beans>

employee-servlet-jpa.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:jpa="http://www.springframework.org/schema/data/jpa" 
       xmlns:neo4j="http://www.springframework.org/schema/data/neo4j"
       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/context
            http://www.springframework.org/schema/context/spring-context.xsd            
            http://www.springframework.org/schema/data/jpa
            http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
            http://www.springframework.org/schema/tx 
            http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

    <jpa:repositories base-package="com.howtodoinjava.repository.jpa" />

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" > 
        <property name="packagesToScan" value="com.howtodoinjava.entity" />
        <property name="persistenceUnitName" value="SpringDataJPA" />
        <!--property name="dataSource" ref="dataSource" /-->
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.show_sql">true</prop>
            </props>
        </property>
        <property name="persistenceProvider">
            <bean class="org.hibernate.jpa.HibernatePersistenceProvider" />
        </property>
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>

</beans>

最后,persistence.xml:

<?xml version="1.0" encoding="UTF-8"?>
<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_2_0.xsd"
             version="2.0">

    <persistence-unit name="SpringDataJPA" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>      
        <properties>
            <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
            <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/atom" />
            <property name="javax.persistence.jdbc.user" value="root" />
            <property name="javax.persistence.jdbc.password" value="123456" />

            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
            <property name="hibernate.show_sql" value="true" />
            <property name="hibernate.hbm2ddl.auto" value="update" />

        </properties>
    </persistence-unit>
</persistence>

我在控制台上看到了这个:

Aug 27, 2014 3:06:48 AM org.hibernate.jpa.internal.util.LogHelper logPersistenceUnitInformation
INFO: HHH000204: Processing PersistenceUnitInfo [
    name: SpringDataJPA
    ...]
Aug 27, 2014 3:06:48 AM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate Core {4.3.6.Final}
Aug 27, 2014 3:06:48 AM org.hibernate.cfg.Environment <clinit>
INFO: HHH000206: hibernate.properties not found
Aug 27, 2014 3:06:48 AM org.hibernate.cfg.Environment buildBytecodeProvider
INFO: HHH000021: Bytecode provider name : javassist
Aug 27, 2014 3:06:48 AM org.hibernate.annotations.common.reflection.java.JavaReflectionManager <clinit>
INFO: HCANN000001: Hibernate Commons Annotations {4.0.5.Final}
Aug 27, 2014 3:06:48 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
WARN: HHH000402: Using Hibernate built-in connection pool (not for production use!)
Aug 27, 2014 3:06:48 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH000401: using driver [com.mysql.jdbc.Driver] at URL [jdbc:mysql://localhost:3306/atom]
Aug 27, 2014 3:06:48 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH000046: Connection properties: {user=root, password=****}
Aug 27, 2014 3:06:48 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH000006: Autocommit mode: false
Aug 27, 2014 3:06:48 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
INFO: HHH000115: Hibernate connection pool size: 20 (min=1)
Aug 27, 2014 3:06:48 AM org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect
Aug 27, 2014 3:06:48 AM org.hibernate.engine.jdbc.internal.LobCreatorBuilder useContextualLobCreation
INFO: HHH000423: Disabling contextual LOB creation as JDBC driver reported JDBC version [3] less than 4
Aug 27, 2014 3:06:49 AM org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory <init>
INFO: HHH000397: Using ASTQueryTranslatorFactory
Aug 27, 2014 3:06:49 AM org.hibernate.tool.hbm2ddl.SchemaUpdate execute
INFO: HHH000228: Running hbm2ddl schema update
Aug 27, 2014 3:06:49 AM org.hibernate.tool.hbm2ddl.SchemaUpdate execute
INFO: HHH000102: Fetching database metadata
Aug 27, 2014 3:06:49 AM org.hibernate.tool.hbm2ddl.SchemaUpdate execute
INFO: HHH000396: Updating schema
Aug 27, 2014 3:06:49 AM org.hibernate.tool.hbm2ddl.TableMetadata <init>
INFO: HHH000261: Table found: atom.employee
Aug 27, 2014 3:06:49 AM org.hibernate.tool.hbm2ddl.TableMetadata <init>
INFO: HHH000037: Columns: [firstname, telephone, id, email, lastname]
Aug 27, 2014 3:06:49 AM org.hibernate.tool.hbm2ddl.TableMetadata <init>
INFO: HHH000108: Foreign keys: []
Aug 27, 2014 3:06:49 AM org.hibernate.tool.hbm2ddl.TableMetadata <init>
INFO: HHH000126: Indexes: [primary]
Aug 27, 2014 3:06:49 AM org.hibernate.tool.hbm2ddl.SchemaUpdate execute
INFO: HHH000232: Schema update complete
Hibernate: select employeeen0_.ID as ID1_0_, employeeen0_.EMAIL as EMAIL2_0_, employeeen0_.FIRSTNAME as FIRSTNAM3_0_, employeeen0_.LASTNAME as LASTNAME4_0_, employeeen0_.TELEPHONE as TELEPHON5_0_ from EMPLOYEE employeeen0_
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 4.519 sec

表格是正确创建的,只是save()方法没有保存我的数据。我创建了一个小的JUnit测试,我在调用后检查:employeeManager.addEmployee(employee);如果记录数量增加了。

/ *  *要更改此许可证标题,请在“项目属性”中选择“许可证标题”。  *要更改此模板文件,请选择“工具”|模板  *并在编辑器中打开模板。  * /

package com.howtodoinjava;

import com.howtodoinjava.entity.EmployeeEntity;
import com.howtodoinjava.service.EmployeeManager;
import junit.framework.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath*:employee-servlet*.xml")
@Transactional
public class EmployeeManagerTest {

    @Test
    public void emptyTest() {
    }

    @Autowired
    @Qualifier("employeeManagerJpa")
    EmployeeManager employeeManager;

    @Test
    public void test() {
        EmployeeEntity employee = new EmployeeEntity();
        employee.setFirstname("Tom");
        employee.setLastname("One");
        employee.setTelephone("12-154-789");
        employee.setEmail("tom_one@mail.com");

        EmployeeEntity employee1 = new EmployeeEntity();
        employee1.setFirstname("Kat");
        employee1.setLastname("Two");
        employee1.setTelephone("12-154-789");
        employee1.setEmail("kat_two@mail.com");

        employeeManager.addEmployee(employee);
        employeeManager.addEmployee(employee1);

        Assert.assertEquals("Two",employee1.getLastname()); // True

        Assert.assertEquals(0, employeeManager.getAllEmployees().size()); // Always true
    }
}

编辑:如果我使用saveAndFlush()强制写入,则会收到无事务错误: org.springframework.dao.InvalidDataAccessApiUsageException:没有正在进行的事务;嵌套异常是javax.persistence.TransactionRequiredException:没有正在进行的事务

我检查了网络上发现的大多数修补程序(包括<x:annotation-driven />参数,@Transactional参数,删除了@Service注释并在employee-servlet-app.xml上下文文件中明确创建了bean) 。

非常感谢任何其他建议。 随意询问任何其他可能有用的信息。

1 个答案:

答案 0 :(得分:0)

在你的persistence.xml

<persistence-unit name="SpringDataJPA" transaction-type="RESOURCE_LOCAL">

交易类型不应该是JTA吗?

默认行为afaik是一个事务总是自动创建,无论如何,但它是只读的。因此,如果您的配置(或代码)出现问题,则不会保留任何内容。