Автор оригинала: Vlad Mihalcea.
Почему?
JPA в значительной степени полагается на persistence.xml
файл конфигурации и стандартный API для загрузки поставщика JPA программно требуют слишком большого количества шаблонного кода. В то время как в типичном корпоративном приложении, обеспечивающем persistence.xml
файл на самом деле не является проблемой, это требование не согласуется с модульным тестированием, особенно когда тесты полностью изолированы и им необходимо проверять различные аспекты JPA или гибернации.
Это была проблема, с которой я столкнулся при написании тестовых примеров для книги о сохранении высокой производительности Java. Все мои тесты должны быть изолированы, и не все они имеют одинаковые настройки или сущности.
В моем случае, используя один persistence.xml О файле определенно не могло быть и речи, потому что любое изменение будет иметь волнообразный эффект во всем наборе тестов.
Впадайте в спячку, чтобы прийти на помощь
Гибернация-это потрясающе. Это позволяет вам создавать EntityManagerFactory
полностью программно и с несколькими строками кода:
protected EntityManagerFactory newEntityManagerFactory() { PersistenceUnitInfo persistenceUnitInfo = persistenceUnitInfo(getClass().getSimpleName()); Mapconfiguration = new HashMap<>(); configuration.put(AvailableSettings.INTERCEPTOR, interceptor() ); return new EntityManagerFactoryBuilderImpl( new PersistenceUnitInfoDescriptor( persistenceUnitInfo), configuration ).build(); } protected PersistenceUnitInfoImpl persistenceUnitInfo( String name) { return new PersistenceUnitInfoImpl( name, entityClassNames(), properties() ); }
Каждый тест начинается с некоторых разумных свойств по умолчанию, и сущности должны предоставляться на основе каждого теста.
protected Properties properties() { Properties properties = new Properties(); properties.put("hibernate.dialect", dataSourceProvider().hibernateDialect() ); properties.put("hibernate.hbm2ddl.auto", "create-drop"); DataSource dataSource = newDataSource(); if (dataSource != null) { properties.put("hibernate.connection.datasource", dataSource); } return properties; } protected List entityClassNames() { return Arrays.asList(entities()) .stream() .map(Class::getName) .collect(Collectors.toList()); } protected abstract Class[] entities();
Тест может определять свои собственные настройки и сущности, и таким образом мы можем инкапсулировать всю среду.
@Override protected Class>[] entities() { return new Class>[] { Patch.class }; } @Entity(name = "Patch") public class Patch { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; @ElementCollection @CollectionTable( name="patch_change", joinColumns=@JoinColumn(name="patch_id") ) @OrderColumn(name = "index_id") private Listchanges = new ArrayList<>(); public List getChanges() { return changes; } } @Embeddable public class Change { @Column(name = "path", nullable = false) private String path; @Column(name = "diff", nullable = false) private String diff; public Change() { } public Change(String path, String diff) { this.path = path; this.diff = diff; } public String getPath() { return path; } public String getDiff() { return diff; } }
Вывод
Эта техника не является чем-то новым. Весенние рамки LocalContainerEntityManagerFactoryBean также может быть настроен без фактического persistence.xml файл.