JPA с использованием альтернативного "persistence.xml"
Я знаю, что с инструкцией:
Persistence.createEntityManagerFactory("persistence-unit-name");
Механизм сохранения JPA считывает файл "persistence.xml", ищет блок сохранения, называемый "persistence-unit-name", и создает на нем EntityManagerFactory.
Мой вопрос: как я могу заставить JPA взять файл, отличный от "persistence.xml" ? например, "persistence-test.xml".
Ответы
Ответ 1
Нет стандартизованного метода JPA для этого, хотя отдельные поставщики JPA могут предоставить способ. Я бы предложил стандартный способ иметь другой путь класса для основного и теста.
Например, если вы используете Maven, и у вас есть два файла META-INF/persistence.xml
, один в src/main/resources
и один в src/test/resources
, тесты подберут значение в src/test/resources
, потому что Maven помещает тестовые классы/ресурсы впереди основных классов/ресурсов в пути к классам. Вы можете легко настроить Ant на работу аналогичным образом.
Если вам нужна более сложная логика, рассмотрите возможность использования Spring поддержки JPA. Это позволит вам работать с такими расширенными ситуациями, как интеграция нескольких файлов persistence.xml.
Ответ 2
В EclipseLink вы можете сделать следующее:
Properties pros = new Properties();
pros.setProperty(PersistenceUnitProperties.ECLIPSELINK_PERSISTENCE_XML,
"META-INF/persistence-alternative.xml");
EntityManagerFactory factory =
Persistence.createEntityManagerFactory("pu-name", pros);
Ответ 3
Я не думаю, что ты можешь. Длинный способ сделать это:
Ответ 4
Если вы использовали OpenEJB для тестирования вашего тестирования, вы могли бы сделать именно то, что хотите, используя какой бы то ни было JPA-провайдер. Аналогичный вопрос и соответствующий ответ здесь:
Как указать Maven игнорировать мой main/resources/persistence.xml в пользу теста/...?
Ответ 5
Вы можете настроить Hibernate без использования persistence.xml вообще в Spring, например:
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean()
{
Map<String, Object> properties = new Hashtable<>();
properties.put("javax.persistence.schema-generation.database.action",
"none");
HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
adapter.setDatabasePlatform("org.hibernate.dialect.MySQL5InnoDBDialect"); //you can change this if you have a different DB
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(adapter);
factory.setDataSource(this.springJpaDataSource());
factory.setPackagesToScan("package name");
factory.setSharedCacheMode(SharedCacheMode.ENABLE_SELECTIVE);
factory.setValidationMode(ValidationMode.NONE);
factory.setJpaPropertyMap(properties);
return factory;
}
Поскольку вы не используете persistence.xml, вы должны создать bean, который возвращает DataSource, указанный вами в указанном выше методе, который устанавливает источник данных:
@Bean
public DataSource springJpaDataSource()
{
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setUrl("jdbc:mysql://localhost/SpringJpa");
dataSource.setUsername("tomcatUser");
dataSource.setPassword("password1234");
return dataSource;
}
Затем вы используете аннотацию @EnableTransactionManagement
по этому файлу конфигурации. Теперь, когда вы помещаете эту аннотацию, вам нужно создать последний bean:
@Bean
public PlatformTransactionManager jpaTransactionManager()
{
return new JpaTransactionManager(
this.entityManagerFactoryBean().getObject());
}
Теперь не забудьте использовать @Transactional
Аннотацию к тем методам, которые относятся к БД.
Наконец, не забудьте ввести EntityManager
в ваш репозиторий (этот класс репозитория должен иметь аннотацию @Repository
над ним).
Ответ 6
Итак, мы хотим иметь 2 отдельных файла persistence.xml
. Один должен быть прочитан только по конфигурации производства, а другой для тестов. Идея состоит в том, чтобы переименовать или скрыть файлы.
Военное решение
Не помещайте persistence.xml
в src\main\resources\META-INF\
. Вместо этого поместите его в src\main\webapp\WEB-INF\classes\META-INF\
. Это место, где должен находиться файл, и в этом месте оно не будет видно по тестам.
Это решение работает для меня в среде gradle, но я надеюсь, что и в других тоже будет.
Решение Jar
Переименуйте производственный файл в persistence-ee.xml
. Теперь мы закончили с тестовой конфигурацией. Для производства мы должны использовать некоторую обработку. Каждая среда может иметь свой собственный путь, как я это делаю в gradle:
tasks.withType(Jar) {
rename { fileName ->
fileName == "persistence-ee.xml" ? "persistence.xml" : fileName;
}
}
В моих приложениях, имеющих файл persistence.xml
для производства, требуется только во время развертывания, то есть в jar/war-пакетах. И это единственные места, где этот файл виден. Без double persistence
я не мог запустить свою базу данных. Основная причина заключалась в использовании jta-data-source
, другой: 2 отдельных именованных модуля сохранения.