Spring TX interaction with caching / detached entities
Hello,
I'm using Spring Data JPA in a simple "frontend <=> service <=> repository" layered architecture.
What I'd like to do is to make my @Service return "detached" entities to the frontend, so it can freely and securely manipulate these objects.
That seems to be the default behavior "out of the box" (?) but that changes when I happen to use Spring transactions.
Here's a simplified test case :
Code:
@Entity
public class Record implements Serializable {
@Id
@GeneratedValue(generator = "uuid")
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
private String title;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
private boolean published = false;
public boolean isPublished() {
return published;
}
public void setPublished(boolean published) {
this.published = published;
}
}
public interface RecordRepository
extends JpaRepository<RecordRepository, String> {
}
@Service
public class RecordService {
@Resource
private RecordRepository recordRepository;
@Transactional
public Record createRecord(Record recordRemote) {
Record recordLocal = new Record();
recordLocal.setTitle(recordRemote.getTitle());
recordLocal = recordRepository.save(recordLocal);
return recordLocal;
}
@Transactional
public Record updateRecord(Record recordRemote) {
Record recordLocal = recordRepository.findOne(recordRemote.getId());
recordLocal.setTitle(recordRemote.getTitle());
recordLocal = recordRepository.save(recordLocal);
return recordLocal;
}
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "/beans.xml")
@TestExecutionListeners(TransactionalTestExecutionListener.class)
public class AppTest extends AbstractJUnit4SpringContextTests {
@Resource
private RecordService recordService;
@Test
@Transactional
public void test1() {
String TITLE = "my title";
Record record = new Record();
record.setTitle(TITLE);
record = recordService.createRecord(record);
assertEquals(TITLE, record.getTitle());
TITLE = "another title";
record.setTitle(TITLE);
record.setPublished(true); // that shouldn't have any impact on the JPA entity (cache)
record = recordService.updateRecord(record);
assertEquals(TITLE, record.getTitle());
assertFalse(record.isPublished()); // fails when using @Transactional
}
}
Basically, the test succeeds... except when I try to use it in a @Transactional setup.
So what's going on here ? Why does Spring TX have such an impact ?
And, back to my initial goal, how can I easily returned detached entities out of my @Service methods?
I suppose I could clone all my objects but I'd prefer to take advantage of JPA capabilities if possible...
Environnement : Spring 3.0.7, Spring Data JPA 1.0.2, EclipseLink 2.2.1 with PostgreSQL.
Thanks a lot!