1. Въведение
EntityManager е част от API за устойчивост на Java. Най-вече, той изпълнява интерфейсите за програмиране и правилата за жизнения цикъл, определени от спецификацията JPA 2.0.
Освен това можем да осъществим достъп до контекста на постоянство, като използваме API- тата в EntityManager .
В този урок ще разгледаме конфигурацията, типовете и различните API на EntityManager .
2. Зависимости на Maven
Първо, трябва да включим зависимостите на Hibernate:
org.hibernate hibernate-core 5.4.0.Final
Също така ще трябва да включим зависимостите на драйвера, в зависимост от базата данни, която използваме:
mysql mysql-connector-java 8.0.13
Зависимостите hibernate-core и mysql-connector-java са налични в Maven Central.
3. Конфигурация
Сега, нека демонстрираме EntityManager , като използваме обект Movie , който съответства на таблица MOVIE в базата данни.
По време на тази статия ще използваме API на EntityManager за работа с обектите Movie в базата данни.
3.1. Определяне на субекта
Нека започнем, като създадем обекта, съответстващ на таблицата MOVIE, като използваме анотацията @Entity :
@Entity @Table(name = "MOVIE") public class Movie { @Id private Long id; private String movieName; private Integer releaseYear; private String language; // standard constructor, getters, setters }
3.2. В persistence.xml File
Когато EntityManagerFactory е създаден, изпълнението на постоянство търси файла META-INF / persistence.xml в пътя на класа .
Този файл съдържа конфигурацията за EntityManager :
Hibernate EntityManager Demo com.baeldung.hibernate.pojo.Movie true
За да обясним, ние дефинираме единицата на постоянство, която определя основния склад за данни, управляван от EntityManager .
Освен това дефинираме диалекта и другите JDBC свойства на базисното хранилище за данни. Хибернацията е агностична за бази данни. Въз основа на тези свойства Hibernate се свързва с основната база данни.
4. Управляван от контейнери и приложения EntityManager
По принцип има два типа EntityManager : управляван от контейнер и управляван от приложения.
Нека разгледаме по-отблизо всеки тип.
4.1. Управляван от контейнер EntityManager
Тук контейнерът инжектира EntityManager в нашите корпоративни компоненти.
С други думи, контейнерът създава EntityManager от EntityManagerFactory за нас:
@PersistenceContext EntityManager entityManager;
Това също означава, че контейнерът е отговорен за започване на транзакцията, както и за ангажиране или връщане обратно.
По същия начин контейнерът е отговорен за затварянето на EntityManager, така че е безопасен за използванебез ръчно почистване. Дори ако се опитаме да затворим EntityManager , управляван от контейнер , той трябва да хвърли IllegalStateException.
4.2. Управляван от приложения EntityManager
И обратно, жизненият цикъл на EntityManager се управлява от приложението тук.
Всъщност ще създадем ръчно EntityManager. Освен това ще управляваме и жизнения цикъл на EntityManager, който сме създали.
Първо, нека създадем EntityManagerFactory:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("com.baeldung.movie_catalog");
За да създадем EntityManager , трябва изрично да извикаме createEntityManager () в EntityManagerFactory :
public static EntityManager getEntityManager() { return emf.createEntityManager(); }
Тъй като ние отговаряме за създаването на екземпляри на EntityManager , нашата отговорност е и да ги затворим . Затова трябва да затворим всеки EntityManager, когато приключим с използването им.
4.3. Безопасност на резбата
На EntityManagerFactory случаи и следователно Хиберниране на SessionFactory случаи, са конци-безопасно . Така че е напълно безопасно в едновременен контекст да пишете:
EntityManagerFactory emf = // fetched from somewhere EntityManager em = emf.createEntityManager();
От друга страна, екземплярите на EntityManager не са безопасни за нишки и са предназначени да се използват в среди, ограничени от нишки . Това означава, че всяка нишка трябва да получи своя екземпляр, да работи с него и да го затвори в края.
Когато използвате EntityManager , управляван от приложения , е лесно да създадете екземпляри, ограничени от нишки:
EntityManagerFactory emf = // fetched from somewhere EntityManager em = emf.createEntityManager(); // use it in the current thread
Нещата обаче стават контраинтуитивни при използване на EntityManager, управляван от контейнери . Например:
@Service public class MovieService { @PersistenceContext // or even @Autowired private EntityManager entityManager; // omitted }
It seems that one EntityManager instance should be shared for all operations. However, the container (JakartaEE or Spring) injects a special proxy instead of a simple EntityManager here. Spring, for example, injects a proxy of type SharedEntityManagerCreator.
Every time we use the injected EntityManager, this proxy will either reuse the existing EntityManager or create a new one. Reuse usually occurs when we enable something like Open Session/EntityManager in View.
Either way, the container ensures that each EntityManager is confined to one thread.
5. Hibernate Entity Operations
The EntityManager API provides a collection of methods. We can interact with the database, by making use of these methods.
5.1. Persisting Entities
In order to have an object associated with the EntityManager, we can make use of the persist() method :
public void saveMovie() { EntityManager em = getEntityManager(); em.getTransaction().begin(); Movie movie = new Movie(); movie.setId(1L); movie.setMovieName("The Godfather"); movie.setReleaseYear(1972); movie.setLanguage("English"); em.persist(movie); em.getTransaction().commit(); }
Once the object is saved in the database, it is in the persistent state.
5.2. Loading Entities
For the purpose of retrieving an object from the database, we can use the find() method.
Here, the method searches by the primary key. In fact, the method expects the entity class type and the primary key:
public Movie getMovie(Long movieId) { EntityManager em = getEntityManager(); Movie movie = em.find(Movie.class, new Long(movieId)); em.detach(movie); return movie; }
However, if we just need the reference to the entity, we can use the getReference() method instead. In effect, it returns a proxy to the entity:
Movie movieRef = em.getReference(Movie.class, new Long(movieId));
5.3. Detaching Entities
In the event that we need to detach an entity from the persistence context, we can use the detach() method. We pass the object to be detached as the parameter to the method:
em.detach(movie);
Once the entity is detached from the persistence context, it will be in the detached state.
5.4. Merging Entities
In practice, many applications require entity modification across multiple transactions. For example, we may want to retrieve an entity in one transaction for rendering to the UI. Then, another transaction will bring in the changes made in the UI.
We can make use of the merge() method, for such situations. The merge method helps to bring in the modifications made to the detached entity, in the managed entity, if any:
public void mergeMovie() { EntityManager em = getEntityManager(); Movie movie = getMovie(1L); em.detach(movie); movie.setLanguage("Italian"); em.getTransaction().begin(); em.merge(movie); em.getTransaction().commit(); }
5.5. Querying for Entities
Furthermore, we can make use of JPQL to query for entities. We'll invoke getResultList() to execute them.
Of course, we can use the getSingleResult(), if the query returns just a single object:
public List queryForMovies() { EntityManager em = getEntityManager(); List movies = em.createQuery("SELECT movie from Movie movie where movie.language = ?1") .setParameter(1, "English") .getResultList(); return movies; }
5.6. Removing Entities
Additionally, we can remove an entity from the database using the remove() method. It's important to note that, the object is not detached, but removed.
Here, the state of the entity changes from persistent to new:
public void removeMovie() { EntityManager em = HibernateOperations.getEntityManager(); em.getTransaction().begin(); Movie movie = em.find(Movie.class, new Long(1L)); em.remove(movie); em.getTransaction().commit(); }
6. Conclusion
In this article, we have explored the EntityManager in Hibernate. We've looked at the types and configuration, and we learned about the various methods available in the API for working with the persistence context.
Както винаги, кодът, използван в статията, е достъпен в Github.