Gids voor de Hibernate EntityManager

1. Inleiding

EntityManager maakt deel uit van de Java Persistence API. Het implementeert voornamelijk de programmeerinterfaces en levenscyclusregels die zijn gedefinieerd door de JPA 2.0-specificatie.

Bovendien hebben we toegang tot de Persistence-context door de API's in EntityManager.

In deze zelfstudie bekijken we de configuratie, typen en verschillende API's van de EntityManager.

2. Maven afhankelijkheden

Ten eerste moeten we de afhankelijkheden van Hibernate opnemen:

 org.hibernate hibernate-core 5.4.0.Final 

We zullen ook de afhankelijkheden van stuurprogramma's moeten opnemen, afhankelijk van de database die we gebruiken:

 mysql mysql-connector-java 8.0.13 

De hibernate-core en mysql-connector-java-afhankelijkheden zijn beschikbaar op Maven Central.

3. Configuratie

Laten we nu de EntityManager, door een Film entiteit die overeenkomt met een MOVIE-tabel in de database.

In de loop van dit artikel zullen we gebruik maken van de EntityManager API om te werken met de Film objecten in de database.

3.1. De entiteit definiëren

Laten we beginnen met het maken van de entiteit die overeenkomt met de MOVIE-tabel, met behulp van de @Entiteit annotatie:

@Entity @Table (name = "MOVIE") openbare klasse Film {@Id privé Lange id; private String movieName; private Integer releaseYear; privé String-taal; // standard constructor, getters, setters}

3.2. De persistence.xml het dossier

Wanneer de EntityManagerFactory is gecreëerd, de persistentie-implementatie zoekt naar het META-INF / persistence.xml bestand in het klassenpad.

Dit bestand bevat de configuratie voor het EntityManager:

 Hibernate EntityManager Demo com.baeldung.hibernate.pojo.Movie waar 

Om dit uit te leggen, definiëren we de persistentie-eenheid die de onderliggende datastore specificeert die wordt beheerd door de EntityManager.

Verder definiëren we het dialect en de andere JDBC-eigenschappen van de onderliggende datastore. Hibernate is database-agnostisch. Op basis van deze eigenschappen maakt Hibernate verbinding met de onderliggende database.

4. Beheerd container en applicatie EntityManager

Eigenlijk, er zijn twee soorten EntityManager: Container-beheerd en applicatie-beheerd.

Laten we elk type eens nader bekijken.

4.1. Door containers beheerd EntityManager

Hier injecteert de container het EntityManager in onze bedrijfscomponenten.

Met andere woorden, de container maakt het EntityManager van de EntityManagerFactory voor ons:

@PersistenceContext EntityManager entityManager; 

Dit betekent ook de container is verantwoordelijk voor het starten van de transactie, het vastleggen of terugdraaien ervan.

Evenzo is de container verantwoordelijk voor het sluiten van de Entiteitsmanager, dus het is veilig te gebruikenzonder handmatige schoonmaakacties. Zelfs als we het proberen sluit een container beheerd EntityManager, zou het een moeten werpen IllegalStateException.

4.2. Applicatie-beheerd EntityManager

Omgekeerd is de levenscyclus van het EntityManager wordt beheerd door de applicatie hier.

In feite maken we handmatig het EntityManager. Bovendien beheren we ook de levenscyclus van het EntityManager we hebben gemaakt.

Laten we eerst het EntityManagerFactory:

EntityManagerFactory emf = Persistence.createEntityManagerFactory ("com.baeldung.movie_catalog");

Om een EntityManager, moeten we expliciet bellen createEntityManager () in de EntityManagerFactory:

openbare statische EntityManager getEntityManager () {terugkeer emf.createEntityManager (); }

Omdat we verantwoordelijk zijn voor het creëren EntityManager gevallen is het ook onze verantwoordelijkheid om ze te sluiten. Daarom moeten we dichtbij elk EntityManager als we ze niet meer gebruiken.

4.3. Draad-veiligheid

De EntityManagerFactory instanties en, bijgevolg, Hibernate's SessionFactory instanties, zijn thread-safe. Het is dus volkomen veilig in gelijktijdige contexten om te schrijven:

EntityManagerFactory emf = // ergens vandaan opgehaald EntityManager em = emf.createEntityManager ();

Aan de andere kant, de EntityManager instanties zijn niet thread-safe en zijn bedoeld om te worden gebruikt in omgevingen met threads. Dit betekent dat elke thread zijn instantie moet krijgen, ermee moet werken en deze aan het einde moet sluiten.

Bij gebruik van applicatie-managed EntityManagers, is het eenvoudig om thread-beperkte instanties te maken:

EntityManagerFactory emf = // ergens vandaan opgehaald EntityManager em = emf.createEntityManager (); // gebruik het in de huidige thread

Dingen worden echter contra-intuïtief bij het gebruik van container-managed EntityManagers. Bijvoorbeeld:

@Service openbare klasse MovieService {@PersistenceContext // of zelfs @Autowired private EntityManager entityManager; // weggelaten}

Het lijkt erop dat EntityManager instantie moet worden gedeeld voor alle bewerkingen. De container (JakartaEE of Spring) injecteert echter een speciale proxy in plaats van een simple EntityManager hier. De lente injecteert bijvoorbeeld een soort proxy SharedEntityManagerCreator.

Elke keer dat we de geïnjecteerde gebruiken Entiteitsmanager, deze proxy zal ofwel het bestaande hergebruiken EntityManager of maak een nieuwe. Hergebruik vindt meestal plaats wanneer we zoiets als inschakelen Open Session / EntityManager in View.

Hoe dan ook, de container zorgt ervoor dat elk EntityManager is beperkt tot één thread.

5. Hibernate Entity Operations

De EntityManager API biedt een verzameling methoden. We kunnen communiceren met de database door gebruik te maken van deze methoden.

5.1. Aanhoudende entiteiten

Om een ​​object aan de EntityManager te laten koppelen, kunnen we gebruik maken van de volharden () methode:

openbare void saveMovie () {EntityManager em = getEntityManager (); em.getTransaction (). begin (); Movie movie = nieuwe film (); movie.setId (1L); movie.setMovieName ("The Godfather"); movie.setReleaseYear (1972); movie.setLanguage ("Engels"); em.persist (film); em.getTransaction (). commit (); }

Zodra het object in de database is opgeslagen, bevindt het zich in de aanhoudend staat.

5.2. Entiteiten laden

Om een ​​object uit de database op te halen, kunnen we de vind() methode.

Hier zoekt de methode op de primaire sleutel. In feite verwacht de methode het type entiteitsklasse en de primaire sleutel:

openbare film getMovie (lange movieId) {EntityManager em = getEntityManager (); Movie movie = em.find (Movie.class, new Long (movieId)); em.detach (filmpje); film terug; }

Als we echter alleen de verwijzing naar de entiteit nodig hebben, kunnen we de getReference () methode in plaats daarvan. In feite retourneert het een proxy naar de entiteit:

Movie movieRef = em.getReference (Movie.class, new Long (movieId));

5.3. Entiteiten loskoppelen

In het geval dat we een entiteit moeten loskoppelen van de persistentiecontext, we kunnen de losmaken methode. We geven het te ontkoppelen object als parameter door aan de methode:

em.detach (filmpje);

Als de entiteit eenmaal is losgekoppeld van de persistentiecontext, bevindt deze zich in de ontkoppelde toestand.

5.4. Entiteiten samenvoegen

In de praktijk vereisen veel applicaties entiteitswijziging over meerdere transacties. We willen bijvoorbeeld een entiteit in één transactie ophalen voor weergave in de gebruikersinterface. Vervolgens zorgt een andere transactie voor de wijzigingen die in de gebruikersinterface zijn aangebracht.

We kunnen gebruik maken van de samenvoegen() methode, voor dergelijke situaties. De samenvoegmethode helpt om de wijzigingen die zijn aangebracht in de ontkoppelde entiteit, in de beheerde entiteit, indien van toepassing:

openbare void mergeMovie () {EntityManager em = getEntityManager (); Filmfilm = getMovie (1L); em.detach (filmpje); movie.setLanguage ("Italiaans"); em.getTransaction (). begin (); em.merge (filmpje); em.getTransaction (). commit (); }

5.5. Zoeken naar entiteiten

Verder kunnen we JPQL gebruiken om te zoeken naar entiteiten. We zullen een beroep doen getResultList () om ze uit te voeren.

Natuurlijk kunnen we de getSingleResult (), als de query slechts één object retourneert:

openbare lijst queryForMovies () {EntityManager em = getEntityManager (); List movies = em.createQuery ("SELECTEER film uit filmfilm waar movie.language =? 1") .setParameter (1, "Engels") .getResultList (); films teruggeven; }

5.6. Entiteiten verwijderen

Bovendien, we kunnen een entiteit uit de database verwijderen met behulp van de verwijderen() methode. Het is belangrijk op te merken dat het object niet wordt losgemaakt, maar verwijderd.

Hier verandert de status van de entiteit van persistent naar nieuw:

openbare void removeMovie () {EntityManager em = HibernateOperations.getEntityManager (); em.getTransaction (). begin (); Movie movie = em.find (Movie.class, new Long (1L)); em.remove (filmpje); em.getTransaction (). commit (); }

6. Conclusie

In dit artikel hebben we de EntityManager in Slaapstand. We hebben gekeken naar de typen en configuratie, en we hebben geleerd over de verschillende methoden die beschikbaar zijn in de API voor het werken met de persistentie context.

Zoals altijd is de code die in het artikel wordt gebruikt, beschikbaar op Github.