diff --git a/org.springframework.test/.classpath b/org.springframework.test/.classpath
index 247b29a9f8b..b2fe691626b 100644
--- a/org.springframework.test/.classpath
+++ b/org.springframework.test/.classpath
@@ -27,6 +27,10 @@
+
+
+
+
diff --git a/org.springframework.test/ivy.xml b/org.springframework.test/ivy.xml
index 9e4dfd64eda..c09ff16e058 100644
--- a/org.springframework.test/ivy.xml
+++ b/org.springframework.test/ivy.xml
@@ -25,12 +25,15 @@
-
-
+
-
+
+
+
+
+
@@ -41,7 +44,7 @@
-
+
-
+
\ No newline at end of file
diff --git a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/orm/HibernateSessionFlushingTests-context.xml b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/orm/HibernateSessionFlushingTests-context.xml
new file mode 100644
index 00000000000..d1f5ca7849a
--- /dev/null
+++ b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/orm/HibernateSessionFlushingTests-context.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ org.hibernate.dialect.HSQLDialect
+ false
+
+
+
+
+ org/springframework/test/context/junit4/orm/domain/Person.hbm.xml
+ org/springframework/test/context/junit4/orm/domain/DriversLicense.hbm.xml
+
+
+
+
+
+
+
diff --git a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/orm/HibernateSessionFlushingTests.java b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/orm/HibernateSessionFlushingTests.java
new file mode 100644
index 00000000000..78d9e58e9cb
--- /dev/null
+++ b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/orm/HibernateSessionFlushingTests.java
@@ -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 automatic vs. manual 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();
+ }
+
+}
diff --git a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/orm/db-schema.sql b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/orm/db-schema.sql
new file mode 100644
index 00000000000..960b101e7fe
--- /dev/null
+++ b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/orm/db-schema.sql
@@ -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);
diff --git a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/orm/db-test-data.sql b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/orm/db-test-data.sql
new file mode 100644
index 00000000000..a174e3fbed7
--- /dev/null
+++ b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/orm/db-test-data.sql
@@ -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);
diff --git a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/orm/domain/DriversLicense.hbm.xml b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/orm/domain/DriversLicense.hbm.xml
new file mode 100644
index 00000000000..025256301ad
--- /dev/null
+++ b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/orm/domain/DriversLicense.hbm.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/orm/domain/DriversLicense.java b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/orm/domain/DriversLicense.java
new file mode 100644
index 00000000000..cdb2b0f884d
--- /dev/null
+++ b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/orm/domain/DriversLicense.java
@@ -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;
+ }
+
+}
diff --git a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/orm/domain/Person.hbm.xml b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/orm/domain/Person.hbm.xml
new file mode 100644
index 00000000000..aa6478b9891
--- /dev/null
+++ b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/orm/domain/Person.hbm.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/orm/domain/Person.java b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/orm/domain/Person.java
new file mode 100644
index 00000000000..e264f66e8e5
--- /dev/null
+++ b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/orm/domain/Person.java
@@ -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;
+ }
+}
diff --git a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/orm/repository/PersonRepository.java b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/orm/repository/PersonRepository.java
new file mode 100644
index 00000000000..a0b7730d31c
--- /dev/null
+++ b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/orm/repository/PersonRepository.java
@@ -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);
+
+}
diff --git a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/orm/repository/hibernate/HibernatePersonRepository.java b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/orm/repository/hibernate/HibernatePersonRepository.java
new file mode 100644
index 00000000000..702dfcae7e4
--- /dev/null
+++ b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/orm/repository/hibernate/HibernatePersonRepository.java
@@ -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();
+ }
+}
diff --git a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/orm/service/PersonService.java b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/orm/service/PersonService.java
new file mode 100644
index 00000000000..73aa29a5c31
--- /dev/null
+++ b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/orm/service/PersonService.java
@@ -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);
+
+}
diff --git a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/orm/service/impl/StandardPersonService.java b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/orm/service/impl/StandardPersonService.java
new file mode 100644
index 00000000000..dbd7fe6c22b
--- /dev/null
+++ b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/orm/service/impl/StandardPersonService.java
@@ -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);
+ }
+
+}