2016-10-03 100 views
0

我正在開發Spring + JPA示例。在此示例中,我能夠根據ProductCode找到Product,但無法使用Junit保存產品。請指導代碼中的錯誤。我也看到,對於每個junit運行auto_incrementedproduct_id是自動increment,但實體沒有得到保存。無法使用spring + spring數據jpa將數據保存到mysql數據庫中,爲什麼?

注意:我遵循了很多從stackoverflow的鏈接,但沒有得到任何幫助。

Product.java

@Entity 
@Table(name = "product") 
public class Product { 

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

    @Column(name = "product_code") 
    private String productCode; 

    @Column(name = "product_name") 
    private String productName; 

    @Column(name = "price") 
    private float price; 

    @Column(name = "vat") 
    private float vat; 

    @Transient 
    @Formula("price * 2") 
    private float totalPrice; 

    @Column(name = "manufactured_date") 
    @Temporal(TemporalType.TIMESTAMP) 
    private Date manufacturedDate; 

    public int getId() { 
     return id; 
    } 

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

    public String getProductCode() { 
     return productCode; 
    } 

    public void setProductCode(String productCode) { 
     this.productCode = productCode; 
    } 

    public String getProductName() { 
     return productName; 
    } 

    public void setProductName(String productName) { 
     this.productName = productName; 
    } 

    public float getPrice() { 
     return totalPrice; 
    } 

    public void setPrice(float price) { 
     this.price = price; 
    } 

    public float getVat() { 
     return vat; 
    } 

    public void setVat(float vat) { 
     this.vat = vat; 
    } 

    public Date getManufacturedDate() { 
     return manufacturedDate; 
    } 

    public void setManufacturedDate(Date manufacturedDate) { 
     this.manufacturedDate = manufacturedDate; 
    } 

    @Override 
    public String toString() { 
     return "Product [id=" + id + ", productCode=" + productCode 
       + ", productName=" + productName + ", price=" + price 
       + ", vat=" + vat + ", manufacturedDate=" + manufacturedDate + "]"; 
    } 
} 

ProductRepository.java

public interface ProductRepository extends JpaRepository<Product, Integer>{ 
    Product findByProductCode(String productCode); 
} 

的persistence.xml

<?xml version="1.0" encoding="UTF-8"?> 
<persistence version="1.0" 
    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"> 

    <persistence-unit name="jpa-mysql-db" transaction-type="RESOURCE_LOCAL"> 
     <class>com.javamakeuse.entity.Product</class> 
    </persistence-unit> 
</persistence> 

數據庫的context.xml

<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:jdbc="http://www.springframework.org/schema/jdbc" 
    xmlns:context="http://www.springframework.org/schema/context" 
    xmlns:jpa="http://www.springframework.org/schema/data/jpa" 
    xmlns:tx="http://www.springframework.org/schema/tx" 
    xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd 
     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.xsd"> 

    <context:annotation-config/>  
    <context:component-scan base-package="com.javamakeuse.*"/> 
    <tx:annotation-driven transaction-manager="transactionManager" /> 
    <context:property-placeholder location="classpath:database.properties" /> 

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

    <!-- Jpa Repositories --> 
    <jpa:repositories base-package="com.javamakeuse.repository" /> 

    <bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
     <property name="driverClassName" value="${mysql.driver.class.name}" /> 
     <property name="url" value="${mysql.url}" /> 
     <property name="username" value="${mysql.username}" /> 
     <property name="password" value="${mysql.username}" /> 
    </bean> 

    <bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> 
     <property name="showSql" value="true" /> 
     <property name="generateDdl" value="${mysql.generate.ddl}" /> 
     <property name="databasePlatform" value="${mysql.dialect}" /> 
    </bean> 

    <!-- ================= Entity Manager ===================== --> 
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
     <property name="dataSource" ref="datasource" /> 

     <property name="packagesToScan" value="com.scheduler.model" /> 

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

     <property name="persistenceUnitName" value="${mysq.persistent.unit.name}" /> 

     <property name="jpaProperties"> 
      <props> 
       <prop key="hibernate.show_sql">${hibernate.show.sql}</prop> 
       <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop> 
      </props> 
     </property> 
    </bean> 

    <!-- ==================== Transaction Manager ========================== --> 
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
     <property name="entityManagerFactory" ref="entityManagerFactory" /> 
    </bean> 
</beans> 

database.properties

mysql.driver.class.name=com.mysql.jdbc.Driver 
mysql.url=jdbc:mysql://localhost/test 
mysql.username=root 
mysql.password=root 
mysql.dialect=org.hibernate.dialect.MySQLDialect 

hibernate.show.sql=true 
hibernate.hbm2ddl.auto=update 
mysq.persistent.unit.name=jpa-mysql-db 
mysql.generate.ddl=true 

db.sql

create table product (
    product_id integer not null auto_increment, 
    manufactured_date datetime, 
    price float, 
    product_code varchar(255), 
    product_name varchar(255), 
    vat float, 
    primary key (product_id) 
); 

INSERT INTO product (manufactured_date,price,product_code,product_name,vat) VALUES (STR_TO_DATE('03-03-2016', '%d-%m-%Y'), 130, 'AZ00010','IPhone-New-7', 5.6); 
INSERT INTO product (manufactured_date,price,product_code,product_name,vat) VALUES (STR_TO_DATE('01-01-2016', '%d-%m-%Y'), 130, 'AZ00011','Lenovo Vibe X3', 5.6); 

應用的context.xml

<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jdbc="http://www.springframework.org/schema/jdbc" 
    xmlns:context="http://www.springframework.org/schema/context" 
    xmlns:jpa="http://www.springframework.org/schema/data/jpa" 
    xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd 
     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"> 

    <import resource="database-context.xml"/> 

</beans> 

ProductTest.java

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = "classpath:application-context.xml") 
@Transactional(propagation = Propagation.REQUIRED) 
@Rollback 
public class ProductTest { 
    private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; 
    private SimpleDateFormat SDF = new SimpleDateFormat(DATE_FORMAT); 

    @PersistenceContext 
    private EntityManager em; 

    @Autowired 
    private ProductRepository productRepository; 

    @Test 
    public void testProductFinal() throws ParseException { 
     Product product = new Product(); 
     product.setManufacturedDate(SDF.parse("2016-08-08 01:01:01")); 
     product.setPrice(200); 
     product.setProductCode("AZ0100"); 
     product.setProductName("Lenovo Vibe X3"); 
     product.setVat(5.64F); 

     productRepository.save(product); 
    } 

    @Test 
    public void testFindByProductCode(){ 
     Product product = productRepository.findByProductCode("AZ00010"); 
     System.out.println("---------------------"); 
     System.out.println("ManufacturedDate : "+product.getManufacturedDate()); 
     System.out.println("Price    : "+product.getPrice()); 
     System.out.println("ProductCode  : "+product.getProductCode()); 
     System.out.println("Product Name  : "+product.getProductName()); 
     System.out.println("Vat    : "+product.getVat()); 
    } 
} 

下面的記錄是說,實體插入,但沒有得到持續到DB。請幫忙。我正在使用MYSQL DB。

Hibernate: insert into product (manufactured_date, price, product_code, product_name, vat) values (?, ?, ?, ?, ?) 

的pom.xml

<properties> 
     <java.version>1.8</java.version> 
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 
     <spring.version>4.3.1.RELEASE</spring.version> 
     <spring-data-jpa-version>1.9.2.RELEASE</spring-data-jpa-version> 
     <hibernate-entitymanager-version>5.1.0.Final</hibernate-entitymanager-version> 
     <mysql.version>5.1.39</mysql.version> 
     <querydsl.version>4.1.3</querydsl.version> 
     <camel.version>2.17.3</camel.version> 
     <logback.version>1.1.7</logback.version> 
     <jcl-over-slf4j.version>1.7.21</jcl-over-slf4j.version> 
    </properties> 

    <dependencies> 
     <dependency> 
      <groupId>org.springframework</groupId> 
      <artifactId>spring-web</artifactId> 
      <version>${spring.version}</version> 
     </dependency> 

     <!-- Spring TEST --> 
     <dependency> 
      <groupId>org.springframework</groupId> 
      <artifactId>spring-tx</artifactId> 
      <version>${spring.version}</version> 
     </dependency> 

     <dependency> 
      <groupId>org.springframework</groupId> 
      <artifactId>spring-test</artifactId> 
      <version>${spring.version}</version> 
     </dependency> 

     <!-- Spring Data JPA --> 
     <dependency> 
      <groupId>org.springframework.data</groupId> 
      <artifactId>spring-data-jpa</artifactId> 
      <version>${spring-data-jpa-version}</version> 
     </dependency> 

     <!-- Hibernate Entity Manager --> 
     <dependency> 
      <groupId>org.hibernate</groupId> 
      <artifactId>hibernate-entitymanager</artifactId> 
      <version>${hibernate-entitymanager-version}</version> 
     </dependency> 

     <dependency> 
      <groupId>org.hibernate.javax.persistence</groupId> 
      <artifactId>hibernate-jpa-2.1-api</artifactId> 
      <version>1.0.0.Final</version> 
      <scope>compile</scope> 
     </dependency> 

     <!-- QueryDSL --> 
     <dependency> 
      <groupId>com.querydsl</groupId> 
      <artifactId>querydsl-jpa</artifactId> 
      <version>${querydsl.version}</version> 
     </dependency> 

     <dependency> 
      <groupId>com.querydsl</groupId> 
      <artifactId>querydsl-apt</artifactId> 
      <version>${querydsl.version}</version> 
      <scope>provided</scope> 
     </dependency> 


     <!-- Junit --> 
     <dependency> 
      <groupId>junit</groupId> 
      <artifactId>junit</artifactId> 
      <version>4.12</version> 
      <scope>test</scope> 
     </dependency> 

     <!-- MYSQL --> 
     <dependency> 
      <groupId>mysql</groupId> 
      <artifactId>mysql-connector-java</artifactId> 
      <version>${mysql.version}</version> 
     </dependency> 

     <!-- logging Framework Logback, slf4j --> 
     <!-- <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> 
      <version>${jcl-over-slf4j.version}</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> 
      <artifactId>logback-classic</artifactId> <version>${logback.version}</version> 
      </dependency> --> 
    </dependencies> 
+2

您正在測試類上使用Rollback註釋,導致在測試完成而不是提交時回滾任何「已插入」。這是每次測試,因此一個數據不能用於另一個測試。 – Chris

+0

'@ Transactiona'默認進行回滾(在測試中)。你還有'@ Rollback',它再次強制執行此操作。然而,除此之外,你的測試方式是有缺陷的,你的測試應該是獨立的,你的測試是相互依賴的。可能是在升級jUnit時,您的測試突然失敗,因爲訂單發生了變化。真正的問題不在於回滾,而在於測試的方式。 –

+0

@Chris - 謝謝!!除此問題之外,我還有一個問題,並且很快發佈單獨的問題。當我保存實體並返回已保存的實體時,我發現'@ Formula'註解不能正常工作,但是當我返回時,「@ Formula」註解不起作用。爲找到它工作正常。 –

回答

0

謝謝克里斯。根據克里斯的建議,我們需要刪除@Rollback這導致測試完成而不是提交時導致任何「插入」回滾。除此之外,我們還需要刪除@Transactional(propagation = Propagation.REQUIRED),即使我僅使用@Transactional進行了測試,它也不起作用。因此,簡單地使用如下:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = "classpath:application-context.xml") 
@Transactional(propagation = Propagation.REQUIRED) 
public class ProductTest { 
    private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; 
    private SimpleDateFormat SDF = new SimpleDateFormat(DATE_FORMAT); 

    @PersistenceContext 
    private EntityManager em; 

    @Autowired 
    private ProductService productService; 

    @Test 
    public void testProductFinal() throws ParseException { 
     Product product = new Product(); 
     product.setId(1); 
     product.setManufacturedDate(SDF.parse("2016-08-08 01:01:01")); 
     product.setPrice(200); 
     product.setProductCode("AZ0100"); 
     product.setProductName("Lenovo Vibe X3"); 
     product.setVat(5.64F); 

     productService.create(product); 
    } 

    @Test 
    public void testFindByProductCode(){ 
     Product product = productService.findByProductCode("AZ00010"); 
     System.out.println("----------------------------------------"); 
     System.out.println("ManufacturedDate : "+product.getManufacturedDate()); 
     System.out.println("Price    : "+product.getPrice()); 
     System.out.println("ProductCode  : "+product.getProductCode()); 
     System.out.println("Product Name  : "+product.getProductName()); 
     System.out.println("Vat    : "+product.getVat()); 
    } 
} 

Spring聲明式和Programatic事務管理功能強大且多功能。它效果很好。在這裏證明:)

mysql> select * from product; 
+------------+---------------------+-------+--------------+----------------+------+ 
| product_id | manufactured_date | price | product_code | product_name | vat | 
+------------+---------------------+-------+--------------+----------------+------+ 
|   2 | 2016-03-03 00:00:00 | 130 | AZ00010  | IPhone-New-7 | 5.6 | 
|   3 | 2016-01-01 00:00:00 | 130 | AZ00011  | Lenovo Vibe X3 | 5.6 | 
|   14 | 2016-08-08 01:01:01 | 200 | AZ0100  | Lenovo Vibe X3 | 5.64 | 
+------------+---------------------+-------+--------------+----------------+------+ 
3 rows in set (0.00 sec) 
相關問題