[SPR-5699] Investigating issues surrounding automatic flushing of the underlying ORM tool's session via TransactionalTestExecutionListener.
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
|
||||
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/tx http://www.springframework.org/schema/tx/spring-tx.xsd
|
||||
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd">
|
||||
|
||||
<context:component-scan base-package="org.springframework.test.context.junit4.orm" />
|
||||
|
||||
<tx:annotation-driven />
|
||||
|
||||
<jdbc:embedded-database id="dataSource" type="HSQL">
|
||||
<jdbc:script location="classpath:/org/springframework/test/context/junit4/orm/db-schema.sql" />
|
||||
<jdbc:script location="classpath:/org/springframework/test/context/junit4/orm/db-test-data.sql" />
|
||||
</jdbc:embedded-database>
|
||||
|
||||
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"
|
||||
p:dataSource-ref="dataSource">
|
||||
<property name="hibernateProperties">
|
||||
<props>
|
||||
<prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
|
||||
<prop key="hibernate.show_sql">false</prop>
|
||||
</props>
|
||||
</property>
|
||||
<property name="mappingResources">
|
||||
<list>
|
||||
<value>org/springframework/test/context/junit4/orm/domain/Person.hbm.xml</value>
|
||||
<value>org/springframework/test/context/junit4/orm/domain/DriversLicense.hbm.xml</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"
|
||||
p:sessionFactory-ref="sessionFactory" />
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.context.junit4.orm;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.springframework.test.transaction.TransactionTestUtils.assertInTransaction;
|
||||
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.exception.ConstraintViolationException;
|
||||
import org.hibernate.exception.GenericJDBCException;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;
|
||||
import org.springframework.test.context.junit4.orm.domain.DriversLicense;
|
||||
import org.springframework.test.context.junit4.orm.domain.Person;
|
||||
import org.springframework.test.context.junit4.orm.service.PersonService;
|
||||
|
||||
/**
|
||||
* Transactional integration tests regarding <i>automatic vs. manual</i> session
|
||||
* flushing with Hibernate.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 3.0
|
||||
*/
|
||||
@ContextConfiguration
|
||||
public class HibernateSessionFlushingTests extends AbstractTransactionalJUnit4SpringContextTests {
|
||||
|
||||
private static final String SAM = "Sam";
|
||||
private static final String JUERGEN = "Juergen";
|
||||
|
||||
@Autowired
|
||||
private PersonService personService;
|
||||
|
||||
@Autowired
|
||||
private SessionFactory sessionFactory;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
assertInTransaction(true);
|
||||
assertNotNull("PersonService should have been autowired.", personService);
|
||||
assertNotNull("SessionFactory should have been autowired.", sessionFactory);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findSam() {
|
||||
Person sam = personService.findByName(SAM);
|
||||
assertNotNull("Should be able to find Sam", sam);
|
||||
DriversLicense driversLicense = sam.getDriversLicense();
|
||||
assertNotNull("Sam's driver's license should not be null", driversLicense);
|
||||
assertEquals("Verifying Sam's driver's license number", new Long(1234), driversLicense.getNumber());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void saveJuergenWithDriversLicense() {
|
||||
DriversLicense driversLicense = new DriversLicense(2L, 2222L);
|
||||
Person juergen = new Person(JUERGEN, driversLicense);
|
||||
personService.save(juergen);
|
||||
assertNotNull("Should be able to save and retrieve Juergen", personService.findByName(JUERGEN));
|
||||
assertNotNull("Juergen's ID should have been set", juergen.getId());
|
||||
}
|
||||
|
||||
@Ignore("Disabled until SPR-5699 is resolved")
|
||||
@Test(expected = ConstraintViolationException.class)
|
||||
public void saveJuergenWithNullDriversLicense() {
|
||||
personService.save(new Person(JUERGEN));
|
||||
}
|
||||
|
||||
private void updateSamWithNullDriversLicense() {
|
||||
Person sam = personService.findByName(SAM);
|
||||
assertNotNull("Should be able to find Sam", sam);
|
||||
sam.setDriversLicense(null);
|
||||
personService.save(sam);
|
||||
}
|
||||
|
||||
@Test(expected = GenericJDBCException.class)
|
||||
// @IfProfileValue(name = "spring-compatibility", value = "2.5.6")
|
||||
public void updateSamWithNullDriversLicenseSpring256() {
|
||||
updateSamWithNullDriversLicense();
|
||||
sessionFactory.getCurrentSession().flush();
|
||||
}
|
||||
|
||||
@Ignore("Disabled until SPR-5699 is resolved")
|
||||
@Test(expected = GenericJDBCException.class)
|
||||
// @Test(expected = UncategorizedSQLException.class)
|
||||
// @IfProfileValue(name = "spring-compatibility", value = "3.0.0.M2")
|
||||
public void updateSamWithNullDriversLicenseSpring300() {
|
||||
updateSamWithNullDriversLicense();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
DROP TABLE drivers_license IF EXISTS;
|
||||
DROP TABLE person IF EXISTS;
|
||||
|
||||
CREATE TABLE person (
|
||||
id INTEGER NOT NULL IDENTITY PRIMARY KEY,
|
||||
name VARCHAR(50) NOT NULL,
|
||||
drivers_license_id INTEGER NOT NULL
|
||||
);
|
||||
CREATE UNIQUE INDEX person_name ON person(name);
|
||||
CREATE UNIQUE INDEX person_drivers_license_id ON person(drivers_license_id);
|
||||
|
||||
CREATE TABLE drivers_license (
|
||||
id INTEGER NOT NULL IDENTITY PRIMARY KEY,
|
||||
license_number INTEGER NOT NULL
|
||||
);
|
||||
CREATE UNIQUE INDEX drivers_license_license_number ON drivers_license(license_number);
|
||||
@@ -0,0 +1,3 @@
|
||||
INSERT INTO drivers_license(id, license_number) values(1, 1234);
|
||||
|
||||
INSERT INTO person(id, name, drivers_license_id) values(1, 'Sam', 1);
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
|
||||
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
|
||||
|
||||
<hibernate-mapping auto-import="true" default-lazy="false">
|
||||
|
||||
<class name="org.springframework.test.context.junit4.orm.domain.DriversLicense" table="drivers_license">
|
||||
<id name="id" column="id">
|
||||
<generator class="identity" />
|
||||
</id>
|
||||
<property name="number" column="license_number" />
|
||||
</class>
|
||||
|
||||
</hibernate-mapping>
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.context.junit4.orm.domain;
|
||||
|
||||
/**
|
||||
* DriversLicense POJO.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 3.0
|
||||
*/
|
||||
public class DriversLicense {
|
||||
|
||||
private Long id;
|
||||
|
||||
private Long number;
|
||||
|
||||
|
||||
public DriversLicense() {
|
||||
}
|
||||
|
||||
public DriversLicense(Long number) {
|
||||
this(null, number);
|
||||
}
|
||||
|
||||
public DriversLicense(Long id, Long number) {
|
||||
this.id = id;
|
||||
this.number = number;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
protected void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Long getNumber() {
|
||||
return this.number;
|
||||
}
|
||||
|
||||
public void setNumber(Long number) {
|
||||
this.number = number;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
|
||||
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
|
||||
|
||||
<hibernate-mapping auto-import="true" default-lazy="false">
|
||||
|
||||
<class name="org.springframework.test.context.junit4.orm.domain.Person" table="person">
|
||||
<id name="id" column="id">
|
||||
<generator class="identity" />
|
||||
</id>
|
||||
<property name="name" column="name" />
|
||||
<many-to-one name="driversLicense" class="org.springframework.test.context.junit4.orm.domain.DriversLicense"
|
||||
column="drivers_license_id" unique="true" />
|
||||
</class>
|
||||
|
||||
</hibernate-mapping>
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.context.junit4.orm.domain;
|
||||
|
||||
/**
|
||||
* Person POJO.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 3.0
|
||||
*/
|
||||
public class Person {
|
||||
|
||||
private Long id;
|
||||
private String name;
|
||||
private DriversLicense driversLicense;
|
||||
|
||||
|
||||
public Person() {
|
||||
}
|
||||
|
||||
public Person(Long id) {
|
||||
this(id, null, null);
|
||||
}
|
||||
|
||||
public Person(String name) {
|
||||
this(name, null);
|
||||
}
|
||||
|
||||
public Person(String name, DriversLicense driversLicense) {
|
||||
this(null, name, driversLicense);
|
||||
}
|
||||
|
||||
public Person(Long id, String name, DriversLicense driversLicense) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.driversLicense = driversLicense;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
protected void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public DriversLicense getDriversLicense() {
|
||||
return this.driversLicense;
|
||||
}
|
||||
|
||||
public void setDriversLicense(DriversLicense driversLicense) {
|
||||
this.driversLicense = driversLicense;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.context.junit4.orm.repository;
|
||||
|
||||
import org.springframework.test.context.junit4.orm.domain.Person;
|
||||
|
||||
/**
|
||||
* Person Repository API.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 3.0
|
||||
*/
|
||||
public interface PersonRepository {
|
||||
|
||||
Person findByName(String name);
|
||||
|
||||
Person save(Person person);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.context.junit4.orm.repository.hibernate;
|
||||
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.springframework.test.context.junit4.orm.domain.Person;
|
||||
import org.springframework.test.context.junit4.orm.repository.PersonRepository;
|
||||
|
||||
/**
|
||||
* Hibernate implementation of the {@link PersonRepository} API.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 3.0
|
||||
*/
|
||||
@Repository
|
||||
public class HibernatePersonRepository implements PersonRepository {
|
||||
|
||||
private final SessionFactory sessionFactory;
|
||||
|
||||
|
||||
@Autowired
|
||||
public HibernatePersonRepository(SessionFactory sessionFactory) {
|
||||
this.sessionFactory = sessionFactory;
|
||||
}
|
||||
|
||||
public Person save(Person person) {
|
||||
this.sessionFactory.getCurrentSession().save(person);
|
||||
return person;
|
||||
}
|
||||
|
||||
public Person findByName(String name) {
|
||||
return (Person) this.sessionFactory.getCurrentSession().createQuery(
|
||||
"from Person person where person.name = :name").setString("name", name).uniqueResult();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.context.junit4.orm.service;
|
||||
|
||||
import org.springframework.test.context.junit4.orm.domain.Person;
|
||||
|
||||
/**
|
||||
* Person Service API.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 3.0
|
||||
*/
|
||||
public interface PersonService {
|
||||
|
||||
Person findByName(String name);
|
||||
|
||||
Person save(Person person);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.context.junit4.orm.service.impl;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.test.context.junit4.orm.domain.Person;
|
||||
import org.springframework.test.context.junit4.orm.repository.PersonRepository;
|
||||
import org.springframework.test.context.junit4.orm.service.PersonService;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* Standard implementation of the {@link PersonService} API.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 3.0
|
||||
*/
|
||||
@Service
|
||||
@Transactional(readOnly = true)
|
||||
public class StandardPersonService implements PersonService {
|
||||
|
||||
private final PersonRepository personRepository;
|
||||
|
||||
|
||||
@Autowired
|
||||
public StandardPersonService(PersonRepository personRepository) {
|
||||
this.personRepository = personRepository;
|
||||
}
|
||||
|
||||
public Person findByName(String name) {
|
||||
return this.personRepository.findByName(name);
|
||||
}
|
||||
|
||||
@Transactional(readOnly = false)
|
||||
public Person save(Person person) {
|
||||
return this.personRepository.save(person);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user