DATAJPA-669 - Introduced JpaContext to abstract the current JPA setup.

DefaultJpaContext is set up of all EntityManager instances in the current ApplicationContext and exposed for injection. Its interface JpaContext then currently allows looking up EntityManagers by managed domain types.

If multiple EntityManagers of the current ApplicationContext manage the a single domain type the request is rejected.
This commit is contained in:
Oliver Gierke
2015-07-06 15:24:25 +02:00
parent 3bbb1bb5ba
commit 5f1ab5661b
9 changed files with 312 additions and 12 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2014 the original author or authors.
* Copyright 2012-2015 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.
@@ -16,6 +16,7 @@
package org.springframework.data.jpa.repository;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import javax.persistence.EntityManager;
@@ -37,6 +38,7 @@ import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.data.jpa.repository.sample.SampleEvaluationContextExtension;
import org.springframework.data.jpa.repository.sample.UserRepository;
import org.springframework.data.jpa.repository.sample.UserRepositoryImpl;
import org.springframework.data.jpa.repository.support.DefaultJpaContext;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean;
import org.springframework.data.repository.core.NamedQueries;
import org.springframework.data.repository.core.support.PropertiesBasedNamedQueries;
@@ -78,7 +80,8 @@ public class JavaConfigUserRepositoryTests extends UserRepositoryTests {
factory.setEntityManager(entityManager);
factory.setBeanFactory(applicationContext);
factory.setRepositoryInterface(UserRepository.class);
factory.setCustomImplementation(new UserRepositoryImpl());
factory
.setCustomImplementation(new UserRepositoryImpl(new DefaultJpaContext(Collections.singleton(entityManager))));
factory.setNamedQueries(namedQueries());
factory.setEvaluationContextProvider(evaluationContextProvider);
factory.afterPropertiesSet();

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2008-2011 the original author or authors.
* Copyright 2008-2015 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.
@@ -17,7 +17,10 @@ package org.springframework.data.jpa.repository.sample;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.sample.User;
import org.springframework.data.jpa.repository.JpaContext;
import org.springframework.util.Assert;
/**
* Dummy implementation to allow check for invoking a custom implementation.
@@ -28,25 +31,24 @@ public class UserRepositoryImpl implements UserRepositoryCustom {
private static final Logger LOG = LoggerFactory.getLogger(UserRepositoryImpl.class);
@Autowired
public UserRepositoryImpl(JpaContext context) {
Assert.notNull(context, "JpaContext must not be null!");
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.jpa.repository.sample.UserRepositoryCustom#
* someCustomMethod(org.springframework.data.jpa.domain.sample.User)
* @see org.springframework.data.jpa.repository.sample.UserRepositoryCustom#someCustomMethod(org.springframework.data.jpa.domain.sample.User)
*/
public void someCustomMethod(User u) {
LOG.debug("Some custom method was invoked!");
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.jpa.repository.sample.UserRepositoryCustom#
* findByOverrridingMethod()
* @see org.springframework.data.jpa.repository.sample.UserRepositoryCustom#findByOverrridingMethod()
*/
public void findByOverrridingMethod() {
LOG.debug("A method overriding a finder was invoked!");
}
}

View File

@@ -0,0 +1,113 @@
/*
* Copyright 2015 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.data.jpa.repository.support;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import java.util.Arrays;
import java.util.HashSet;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import org.hibernate.ejb.HibernatePersistence;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.data.jpa.domain.sample.Category;
import org.springframework.data.jpa.domain.sample.User;
import org.springframework.data.jpa.repository.JpaContext;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
/**
* Integration tests for {@link DefaultJpaContext}.
*
* @author Oliver Gierke
* @soundtrack Marcus Miller - Papa Was A Rolling Stone (Afrodeezia)
*/
public class DefaultJpaContextIntegrationTests {
public @Rule ExpectedException exception = ExpectedException.none();
static EntityManagerFactory firstEmf, secondEmf;
EntityManager firstEm, secondEm;
JpaContext jpaContext;
@BeforeClass
public static void bootstrapJpa() {
firstEmf = createEntityManagerFactory("spring-data-jpa");
secondEmf = createEntityManagerFactory("querydsl");
}
@Before
public void createEntityManagers() {
this.firstEm = firstEmf.createEntityManager();
this.secondEm = secondEmf.createEntityManager();
this.jpaContext = new DefaultJpaContext(new HashSet<EntityManager>(Arrays.asList(firstEm, secondEm)));
}
/**
* @see DATAJPA-669
*/
@Test
public void rejectsUnmanagedType() {
exception.expect(IllegalArgumentException.class);
exception.expectMessage(Object.class.getSimpleName());
jpaContext.getEntityManagerByManagedType(Object.class);
}
/**
* @see DATAJPA-669
*/
@Test
public void returnsEntitymanagerForUniqueType() {
assertThat(jpaContext.getEntityManagerByManagedType(Category.class), is(firstEm));
}
/**
* @see DATAJPA-669
*/
@Test
public void rejectsRequestForTypeManagedByMultipleEntityManagers() {
exception.expect(IllegalArgumentException.class);
exception.expectMessage(User.class.getSimpleName());
jpaContext.getEntityManagerByManagedType(User.class);
}
private static final EntityManagerFactory createEntityManagerFactory(String persistenceUnitName) {
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setPersistenceProvider(new HibernatePersistence());
factoryBean.setDataSource(new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL).build());
factoryBean.setPersistenceUnitName(persistenceUnitName);
factoryBean.afterPropertiesSet();
return factoryBean.getObject();
}
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright 2015 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.data.jpa.repository.support;
import java.util.Collections;
import javax.persistence.EntityManager;
import org.junit.Test;
/**
* Unit tests for {@link DefaultJpaContext}.
*
* @author Oliver Gierke
* @soundtrack Marcus Miller - B's River (Afrodeezia)
* @since 1.9
*/
public class DefaultJpaContextUnitTests {
/**
* @see DATAJPA-669
*/
@Test(expected = IllegalArgumentException.class)
public void rejectsNullEntityManagers() {
new DefaultJpaContext(null);
}
/**
* @see DATAJPA-669
*/
@Test(expected = IllegalArgumentException.class)
public void rejectsEmptyEntityManagers() {
new DefaultJpaContext(Collections.<EntityManager> emptySet());
}
}