Рубрики
Без рубрики

Как загрузиться в спящий режим без persistence.xml файл

Автор оригинала: Vlad Mihalcea.

Почему?

JPA в значительной степени полагается на persistence.xml файл конфигурации и стандартный API для загрузки поставщика JPA программно требуют слишком большого количества шаблонного кода. В то время как в типичном корпоративном приложении, обеспечивающем persistence.xml файл на самом деле не является проблемой, это требование не согласуется с модульным тестированием, особенно когда тесты полностью изолированы и им необходимо проверять различные аспекты JPA или гибернации.

Это была проблема, с которой я столкнулся при написании тестовых примеров для книги о сохранении высокой производительности Java. Все мои тесты должны быть изолированы, и не все они имеют одинаковые настройки или сущности.

В моем случае, используя один persistence.xml О файле определенно не могло быть и речи, потому что любое изменение будет иметь волнообразный эффект во всем наборе тестов.

Впадайте в спячку, чтобы прийти на помощь

Гибернация-это потрясающе. Это позволяет вам создавать EntityManagerFactory полностью программно и с несколькими строками кода:

protected EntityManagerFactory newEntityManagerFactory() {
    PersistenceUnitInfo persistenceUnitInfo = 
        persistenceUnitInfo(getClass().getSimpleName());
    Map configuration = 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 List changes = 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 файл.