Jak ręcznie stworzyć entity manager (persistance context)?

0

Mamy taką przykładową klasę repozytorium:

@Repository
public class MyRepository {
    
    @PersistenceContext
    EntityManager em;

    //...
}

W jaki sposób zamienić to na coś takiego?

public class MyRepository {
    
    private EntityManager em;

    public Repository(EntityManager entityManager) {
        em = entityManager;
    }

    // ...

}

@Configuration
public class Config {

    @Bean
    public MyRepository repository() {
        return new MyRepository(???); 
    } 
}

Wiem, że @PersistanceContext ogarnia sporo rzeczy spring stworzy proxy pod to i
tam będzie inny EntityManager per thread (EntityManager nie jest thread-safe) i zamyka go automatycznie.
Natomiast ja chcę mieć też możliwość ręcznie stworzenia tego beana. Czy wgl da się coś takiego zrobić
czy trzeba ręcznie za każdym razem by było tworzyć EntityManagera za pomocą factory. Problem w tym,
że pewnie spring by nic o tym EntityManagerze nie wiedział więc zakładam, że @Transactional by nie
działał poprawnie??

2

A po co Ci to ręczne tworzenie?

2x kontekst to proszenie się o kłopoty i nieczytelny kod, potem będziesz debugował czemu lecą jakieś dziwne błędy bo mieszasz encje z 2 kontekstów.

Napisz lepiej jaki jest pierwotny problem, być może da się go łatwiej rozwiązać np. StatelessSession czy zagnieżdżoną transakcją....

0

A po co Ci to ręczne tworzenie?

A jak potem w testach ustawić? Zastanawiam się jak to mogłoby wyglądać jak
trzymamy się zasady wstrzykiwania przez konstruktor.
Nie ma jakiegoś pierwotnego problemu chodzi tylko o to by mieć możliwość
korzystania z entityManagera i jak najlepiej go wstrzyknąć.

0

Ludzie różnie robią, generalnie testy repozytoriów to raczej nie unit testy bo zazwyczaj sprawdza się z DB która będzie użyta na produkcji np. MySQL. Można się bawić im memory ale zdania są podzielone (większa szybkość vs nie 100% kompatybilność; można też mixować oba podejścia czyli mieć 2 wykonania testów na im-memie do developerki i na właściwym DB na CI, zajawka: https://www.baeldung.com/java-in-memory-databases).

Generalnie w testach możesz robić tak że stawiasz sobie context springa z ewentualnie podmienionymi niektórymi beanami. Nie musi być to cały context, wystarczy wydzielić beany persystencji do osobnej Configuration i ładować niezbędne minimum.

Gdybyś używał Spring Data to miałbyś wszystko out-of-the-box: https://reflectoring.io/spring-boot-data-jpa-test/

0

Persistence.createEntityManager("unit") gdzie unit to nazwa zdefinionwana w pliku persistence.xml. Drugiem argumentem metody jest mapa properties przez co mozna w kodzie dynamicznie nadpisywac wlasciwosci zdefiniowane w pliku persistence

4

@lookacode1: pragnę zauważyć że normalny EntityManager to jest kontekst transakcji bazodanowej, odpowiednik sesji z Hibernate, a raczej w drugą stronę, sessja z Hibernate to implementacja EntityManagera. Jeżeli chcesz wstrzykiwać ręcznie to jak już raczej EntityManagerFactory

0

A co chcesz przetestować? ;)

0

@scibi_92:

pragnę zauważyć że normalny EntityManager to jest kontekst transakcji bazodanowej, odpowiednik sesji z Hibernate, a raczej w drugą stronę, sessja z Hibernate to implementacja EntityManagera. Jeżeli chcesz wstrzykiwać ręcznie to jak już raczej EntityManagerFactory

Tak to wiem natomiast jak wstrzyknę EntityManagerFactory to @Transactional nie zadziała bo spring nie będzie nic wiedział o tej sesji/entity-managerze,
który stworzę ręcznie. Wtedy sam bym musiał ogarnąć commit / rollback i close na entity-managerze.

@Charles_Ray:

A co chcesz przetestować? ;)

Na razie nic xd. Zastanawiam się po prostu jak skonfigurować tego beana jeżeli wszędzie stosuję constructor based injection.

3

Zostaw tego beana w spokoju :) użyj jakiegoś H2 albo TestContainers.

To jest czysta infrastruktura, traktuj to w testach jako blackbox, który został już przetestowany. Przecież nie będziesz sprawdzał czy EM działa zgodnie z dokumentacja.

1 użytkowników online, w tym zalogowanych: 0, gości: 1