我正在使用org.springframework.data.repository.CrudRepository来保存我的实体。
这是我的实体:
@Entity
@Table (name="ThirdClass")
public abstract class ThirdClassBase
extends BaseDomainObject
implements Serializable, Cloneable{
/**
* Default serialID to prevent warning
*/
private static final long serialVersionUID = 1L;
/*
* A T T R I B U T E S
*/
@Id
private String pk;
@Version
private Integer version;
...
}
这是我的spring-config:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.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"
default-autowire="byName">
<!-- only components from this package can be wired by spring -->
<context:component-scan base-package="test.envmuster.*" />
<!-- Directory to scan for repository classes -->
<jpa:repositories base-package="test.domain.repository" />
<!-- jdbc.properties => used to put db-connection data to an own property-file -->
<bean id="domainPropertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="locations">
<list>
<value>classpath:jdbc.properties</value>
</list>
</property>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${db.driver}" />
<property name="url" value="${db.url}" />
<property name="username" value="${db.username}" />
<property name="password" value="${db.password}" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" >
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" >
<list>
<value>test.domain</value>
</list>
</property>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="generateDdl" value="true" />
</bean>
</property>
</bean>
</beans>
测试:
@ContextConfiguration(locations = { "classpath:spring-test-config.xml" })
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = false)
@Transactional
public class OptimisticLockingTest extends AbstractTransactionalTestNGSpringContextTests {
@Autowired
private ThirdClassRepository thirdRepository;
@BeforeClass
public void setUpData(){
ThirdClass thirdClass = new ThirdClass(3L);
thirdClass.setPk("pk1");
thirdClass.setVersion(30);
thirdClass = thirdRepository.save(thirdClass);
Assert.assertEquals(thirdClass.getVersion(), new Integer(30));
}
@Test
public void optimisticLockingCheck(){
ThirdClass thirdClass = thirdRepository.findByPK("pk1");
Assert.assertEquals(thirdClass.getVersion(), new Integer(30));
thirdClass.setValue(5L);
thirdClass.setVersion(5);
thirdClass = thirdRepository.save(thirdClass);
}
@AfterClass
public void deleteData(){
thirdRepository.delete("pk1");
}
}
控制台中的测试结果:
Hibernate: select thirdclass0_.pk as pk2_8_3_, thirdclass0_.secondClass_pk as secondCl5_8_3_, thirdclass0_.value as value3_8_3_, thirdclass0_.version as version4_8_3_, secondclas1_.pk as pk2_2_0_, secondclas1_.id as id3_2_0_, secondclas1_.thirdClass_pk as thirdCla5_2_0_, secondclas1_.version as version4_2_0_, secondclas1_.wayone_pk as wayone_p6_2_0_, fourthclas2_.SecondClass_pk as SecondCl1_2_5_, fourthclas3_.pk as fourthCl2_3_5_, fourthclas3_.pk as pk2_0_1_, fourthclas3_.prop as prop3_0_1_, fourthclas3_.secondClass_pk as secondCl5_0_1_, fourthclas3_.version as version4_0_1_, thirdclass4_.pk as pk2_8_2_, thirdclass4_.secondClass_pk as secondCl5_8_2_, thirdclass4_.value as value3_8_2_, thirdclass4_.version as version4_8_2_ from ThirdClass thirdclass0_ left outer join SecondClass secondclas1_ on thirdclass0_.secondClass_pk=secondclas1_.pk left outer join SecondClass_FourthClass fourthclas2_ on secondclas1_.pk=fourthclas2_.SecondClass_pk left outer join FourthClass fourthclas3_ on fourthclas2_.fourthClass_pk=fourthclas3_.pk left outer join ThirdClass thirdclass4_ on secondclas1_.thirdClass_pk=thirdclass4_.pk where thirdclass0_.pk=? and thirdclass0_.DTYPE='ThirdClass'
Hibernate: insert into ThirdClass (secondClass_pk, value, version, DTYPE, pk) values (?, ?, ?, 'ThirdClass', ?)
Hibernate: select thirdclass0_.pk as pk2_8_3_, thirdclass0_.secondClass_pk as secondCl5_8_3_, thirdclass0_.value as value3_8_3_, thirdclass0_.version as version4_8_3_, secondclas1_.pk as pk2_2_0_, secondclas1_.id as id3_2_0_, secondclas1_.thirdClass_pk as thirdCla5_2_0_, secondclas1_.version as version4_2_0_, secondclas1_.wayone_pk as wayone_p6_2_0_, thirdclass2_.pk as pk2_8_1_, thirdclass2_.secondClass_pk as secondCl5_8_1_, thirdclass2_.value as value3_8_1_, thirdclass2_.version as version4_8_1_, myfirstcla3_.pk as pk2_4_2_, myfirstcla3_.flag as flag3_4_2_, myfirstcla3_.text as text4_4_2_, myfirstcla3_.version as version5_4_2_, myfirstcla3_.myID as myID6_4_2_, myfirstcla3_.property2 as property7_4_2_, myfirstcla3_.property3 as property8_4_2_ from ThirdClass thirdclass0_ left outer join SecondClass secondclas1_ on thirdclass0_.secondClass_pk=secondclas1_.pk left outer join ThirdClass thirdclass2_ on secondclas1_.thirdClass_pk=thirdclass2_.pk left outer join SuperClass myfirstcla3_ on secondclas1_.wayone_pk=myfirstcla3_.pk where thirdclass0_.pk=? and thirdclass0_.DTYPE='ThirdClass'
Hibernate: update ThirdClass set secondClass_pk=?, value=?, version=? where pk=? and version=?
Hibernate: select thirdclass0_.pk as pk2_8_3_, thirdclass0_.secondClass_pk as secondCl5_8_3_, thirdclass0_.value as value3_8_3_, thirdclass0_.version as version4_8_3_, secondclas1_.pk as pk2_2_0_, secondclas1_.id as id3_2_0_, secondclas1_.thirdClass_pk as thirdCla5_2_0_, secondclas1_.version as version4_2_0_, secondclas1_.wayone_pk as wayone_p6_2_0_, thirdclass2_.pk as pk2_8_1_, thirdclass2_.secondClass_pk as secondCl5_8_1_, thirdclass2_.value as value3_8_1_, thirdclass2_.version as version4_8_1_, myfirstcla3_.pk as pk2_4_2_, myfirstcla3_.flag as flag3_4_2_, myfirstcla3_.text as text4_4_2_, myfirstcla3_.version as version5_4_2_, myfirstcla3_.myID as myID6_4_2_, myfirstcla3_.property2 as property7_4_2_, myfirstcla3_.property3 as property8_4_2_ from ThirdClass thirdclass0_ left outer join SecondClass secondclas1_ on thirdclass0_.secondClass_pk=secondclas1_.pk left outer join ThirdClass thirdclass2_ on secondclas1_.thirdClass_pk=thirdclass2_.pk left outer join SuperClass myfirstcla3_ on secondclas1_.wayone_pk=myfirstcla3_.pk where thirdclass0_.pk=? and thirdclass0_.DTYPE='ThirdClass'
Hibernate: delete from ThirdClass_FourthClass where ThirdClass_pk=?
Hibernate: delete from ThirdClass where pk=? and version=?
PASSED: optimisticLockingCheck
我知道我不应该设置version-property =&gt;但它不是自动设置的,或者至少不会增加。如果我把它保留为null,它会在第一次保存后切换到0 ......这似乎没问题,但是第二次保存并没有增加它...所以我试着设置版本手册。
有些东西似乎有效,因为在控制台输出中,我在更新语句中看到&#34;其中pk =?和版本=?&#34; =&GT;但为什么没有例外抛出?似乎版本字段的使用方式与普通列一样......
请帮助我,我不知道我做错了什么。非常感谢提前。 BR
依赖关系(以防万一):
<dependencies>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<scope>test</scope>
<version>6.8.7</version>
<exclusions>
<exclusion>
<artifactId>junit</artifactId>
<groupId>junit</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.179</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.6.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.0.6.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.2.8.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.0-api</artifactId>
<version>1.0.1.Final</version>
</dependency>
</dependencies>
编辑: 另一个对我意外的行为...我在OneToOne-Relations上使用CascadeType(REMOVE,MERGE)。在我添加@Version注释后,它不再起作用了。我通过一个repository.save保存2个新实体(1:1)关系 - 调用但未保存关联关系(但没有发生异常)。
答案 0 :(得分:0)
回答CascadeType的未预料到的行为: 添加@Version似乎改变了保存行为......因为当我将CascadeType.MERGE更改为CascadeType.PERSIST时,它再次起作用。
通过添加@Version似乎更改了一些:我只在事务提交后才收到所有异常。如果我删除了@Version,我会在persist方法中收到异常。