Trong bài viết này, như bài viết giới thiệu về Hibernate, không dài dòng, mình sẽ đi thẳng vào một ví dụ về JPA với implementation của Hibernate để các bạn có cái nhìn đầu tiên và hiểu cách mà JPA làm việc luôn các bạn nhé!
Đầu tiên, mình sẽ tạo một Maven project như sau:
Vì mình sẽ sử dụng JPA với implementation của Hibernate, do đó, mình sẽ thêm Hibernate dependencies như sau:
1 2 3 4 5 6 7 8 9 10 |
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>5.2.12.Final</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>5.2.12.Final</version> </dependency> |
Mình cũng sẽ sử dụng MySQL database nên mình cũng sẽ thêm MySQL Driver dependency như sau:
1 2 3 4 5 |
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>6.0.6</version> </dependency> |
Project Lombok:
1 2 3 4 5 6 |
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.18</version> <scope>provided</scope> </dependency> |
Trong ví dụ này, mình sẽ định nghĩa một database chứa thông tin của lớp học và những sinh viên của lớp học đó như sau:
1 2 3 4 5 |
CREATE TABLE `clazz` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(45) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; |
1 2 3 4 5 6 7 8 9 10 11 |
CREATE TABLE `students` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(45) NOT NULL, `code` varchar(10) NOT NULL, `date_of_birth` datetime DEFAULT NULL, `email` varchar(100) DEFAULT NULL, `clazz_id` int(11) NOT NULL, PRIMARY KEY (`id`), KEY `student_clazz_idx` (`clazz_id`), CONSTRAINT `student_clazz` FOREIGN KEY (`clazz_id`) REFERENCES `clazz` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION ) ENGINE=InnoDB DEFAULT CHARSET=utf8; |
Các bước chuẩn bị đã xong, giờ chúng ta bắt đầu đi vào phần chính nhé các bạn.
Đầu tiên, để có thể thao tác với các bảng clazz và students trong database, chúng ta sẽ ánh xạ các bảng, các cột của những table này qua thành những Java object trước (ORM).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
package com.huongdanjava.jpa; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; import lombok.Getter; import lombok.Setter; @Entity @Table @Getter @Setter public class Clazz { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column private String name; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
package com.huongdanjava.jpa; import java.util.Date; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; import lombok.Getter; import lombok.Setter; @Entity @Table @Getter @Setter public class Students { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column private String name; @Column private String code; @Column(name = "date_of_birth") private Date dateOfBirth; @Column private String email; @Column(name = "clazz_id") private Long clazzId; } |
Tiếp theo chúng ta sẽ là tạo một tập tin cấu hình để làm việc với JPA.
Tập tin cấu hình này sẽ chứa thông tin của một hay nhiều persistence unit. Một persistence unit là một tập hợp chứa thông tin những Java object ánh xạ đến các cột các bảng trong database và thông tin về kết nối tới database, username, password. Ngoài ra, nó còn chứa một số thông tin cấu hình khác nữa.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence_2_1.xsd"> <persistence-unit name="jpaexample" transaction-type="RESOURCE_LOCAL"> <class>com.huongdanjava.jpa.Clazz</class> <class>com.huongdanjava.jpa.Students</class> <exclude-unlisted-classes>true</exclude-unlisted-classes> <properties> <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" /> <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/jpa_example" /> <property name="javax.persistence.jdbc.user" value="root" /> <property name="javax.persistence.jdbc.password" value="123456" /> <property name="hibernate.format_sql" value="true" /> <property name="hibernate.use_sql_comments" value="true" /> </properties> </persistence-unit> </persistence> |
Mình sẽ giải thích chi tiết những cấu hình này trong bài viết sau nhé các bạn.
Thông thường chúng ta đặt tên cho tập tin cấu hình này là persistence.xml và tập tin này sẽ được chứa trong thư mục /src/main/resources/META-INF của project.
OK, chúng ta đã cấu hình xong, vậy giờ làm thế nào để sử dụng những thông tin cấu hình đó.
Chúng ta sẽ dùng đối tượng Persistence của JPA để đọc những thông tin cấu hình đó lên và dùng đối tượng EntityManagerFactory để chứa chúng.
1 |
EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpaexample"); |
Các bạn để ý là jpaexample chính là tên của persistence unit mà chúng ta đã khai báo trong tập tin cấu hình.
Và giờ chúng ta có thể sử dụng đối tượng EntityManagerFactory để làm việc rồi.
Để làm việc với JPA, chúng ta sẽ lấy một đối tượng EntityManager từ EntityManagerFactory.
1 |
EntityManager em = emf.createEntityManager(); |
Nếu các bạn cần thao tác có liên quan đến cập nhập database, chúng ta cần mở một transaction mới. Nếu không thì không cần mở transaction nhé các bạn. Ở đây, mình cần thêm mới một class, do đó mình sẽ mở một transaction như sau:
1 2 |
EntityTransaction transaction = em.getTransaction(); transaction.begin(); |
Ở đây, chúng ta sẽ thêm mới một record trong bảng clazz nên chúng ta sẽ khởi tạo mới đối tượng Clazz:
1 2 |
Clazz clazz = new Clazz(); clazz.setName("Class A"); |
và dùng đối tượng EntityManager để lưu đối tượng Clazz này vào database:
1 2 |
em.persist(clazz); transaction.commit(); |
Toàn bộ code như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
package com.huongdanjava.jpa; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.EntityTransaction; import javax.persistence.Persistence; public class Application { public static void main(String[] args) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpaexample"); EntityManager em = emf.createEntityManager(); EntityTransaction transaction = em.getTransaction(); transaction.begin(); Clazz clazz = new Clazz(); clazz.setName("Class A"); em.persist(clazz); transaction.commit(); } } |
Kết quả:
Hoàng Nam
Em khai báo persistence.xml như trên bài nhưng lại báo lỗi như thế này
Feb 22, 2020 12:02:12 PM org.hibernate.jpa.internal.util.LogHelper logPersistenceUnitInformation
INFO: HHH000204: Processing PersistenceUnitInfo [
name: jpaexample
…]
Feb 22, 2020 12:02:12 PM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate Core {5.2.12.Final}
Feb 22, 2020 12:02:12 PM org.hibernate.cfg.Environment
INFO: HHH000206: hibernate.properties not found
Exception in thread “main” java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException
at org.hibernate.boot.spi.XmlMappingBinderAccess.(XmlMappingBinderAccess.java:43)
at org.hibernate.boot.MetadataSources.(MetadataSources.java:87)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.(EntityManagerFactoryBuilderImpl.java:208)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.(EntityManagerFactoryBuilderImpl.java:170)
at org.hibernate.jpa.boot.spi.Bootstrap.getEntityManagerFactoryBuilder(Bootstrap.java:76)
at org.hibernate.jpa.HibernatePersistenceProvider.getEntityManagerFactoryBuilder(HibernatePersistenceProvider.java:181)
at org.hibernate.jpa.HibernatePersistenceProvider.getEntityManagerFactoryBuilderOrNull(HibernatePersistenceProvider.java:129)
at org.hibernate.jpa.HibernatePersistenceProvider.getEntityManagerFactoryBuilderOrNull(HibernatePersistenceProvider.java:71)
at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:52)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:55)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:39)
at entity.Application.main(Application.java:8)
Anh xem dùm em thử tại sao được ko ạ.
Khanh Nguyen
java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException đó e. Em coi thử phần dependencies có thiếu gì ko nhé!
Trần Trung Hiếu
Mình đang làm 1 bài kết nối hibernate thì bị lỗi này, bạn giúp mình với ????
org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘entityManagerFactory’ defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.AnnotationException: Illegal attempt to map a non collection as a @OneToMany, @ManyToMany or @CollectionOfElements: com.example.demo.model.MyUserType.userTypeName
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1628) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080) ~[spring-context-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:857) ~[spring-context-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) ~[spring-context-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) ~[spring-boot-1.5.9.RELEASE.jar:1.5.9.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) [spring-boot-1.5.9.RELEASE.jar:1.5.9.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) [spring-boot-1.5.9.RELEASE.jar:1.5.9.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) [spring-boot-1.5.9.RELEASE.jar:1.5.9.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1118) [spring-boot-1.5.9.RELEASE.jar:1.5.9.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1107) [spring-boot-1.5.9.RELEASE.jar:1.5.9.RELEASE]
at com.example.demo.DemoApplication.main(DemoApplication.java:10) [classes/:na]
Caused by: org.hibernate.AnnotationException: Illegal attempt to map a non collection as a @OneToMany, @ManyToMany or @CollectionOfElements: com.example.demo.model.MyUserType.userTypeName
at org.hibernate.cfg.annotations.CollectionBinder.getCollectionBinder(CollectionBinder.java:322) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:1892) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.cfg.AnnotationBinder.processIdPropertiesIfNotAlready(AnnotationBinder.java:911) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:738) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.boot.model.source.internal.annotations.AnnotationMetadataSourceProcessorImpl.processEntityHierarchies(AnnotationMetadataSourceProcessorImpl.java:245) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess$1.processEntityHierarchies(MetadataBuildingProcess.java:222) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:265) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) ~[spring-orm-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:360) ~[spring-orm-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:382) ~[spring-orm-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:371) ~[spring-orm-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:336) ~[spring-orm-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1687) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1624) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
… 16 common frames omitted
Process finished with exit code 1
Khanh Nguyen
Bạn cần xem lại cái này nhé “Illegal attempt to map a non collection as a @OneToMany, @ManyToMany or @CollectionOfElements: com.example.demo.model.MyUserType.userTypeName”, xem thử bạn đang khai báo các relationship có chỗ nào chưa đúng ko nhé?
Hoặc cũng có thể share cái class này lên mình xem thử.
Trần Trung Hiếu
Class MyUser:
package com.example.demo.model;
import javax.persistence.*;
import java.util.Set;
@Entity
@Table(name=”user”)
public class MyUser {
@Id
@GeneratedValue
@Column(name = “id”)
private int userId;
@Column(name = “name”)
private String userName;
@Column(name = “email”)
private String userEmail;
@Column(name = “salary”)
private int userSalary;
@ManyToOne
@JoinColumn(name = “user_type_id”)
private MyUserType userType;
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserEmail() {
return userEmail;
}
public void setUserEmail(String userEmail) {
this.userEmail = userEmail;
}
public int getUserSalary() {
return userSalary;
}
public void setUserSalary(int userSalary) {
this.userSalary = userSalary;
}
public MyUserType getUserType() { return userType; }
public void setUserType(MyUserType userType) { this.userType = userType; }
}
Class MyUserType:
package com.example.demo.model;
import javax.persistence.*;
import java.util.Set;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.SortedSet;
import java.util.SortedMap;
@Entity
@Table(name = “user_type”)
public class MyUserType {
@Id
@Column(name = “user_type_id”)
private int userTypeId;
@Column(name = “user_type_name”)
private List userList;
@OneToMany(mappedBy = “myUserType”, cascade = CascadeType.ALL)
@JoinColumn(name = “user_type_id”)
private String userTypeName;
public int getUserTypeId() { return userTypeId; }
public void setUserTypeId(int userTypeId) { this.userTypeId = userTypeId; }
public String getUserTypeName() { return userTypeName; }
public void setUserTypeName(String userTypeName) { this.userTypeName = userTypeName; }
}
Một UserType thì có nhiều user (khóa ngoại tham chiếu đến: user_type_id) Mình chỉ mới tìm hiểu còn nhiều sai sót mong bạn giúp đỡ, cảm ơn bạn nhiều 😀
Khanh Nguyen
@Column(name = “user_type_name”)
private List userList;
@OneToMany(mappedBy = “myUserType”, cascade = CascadeType.ALL)
@JoinColumn(name = “user_type_id”)
private String userTypeName;
Cái này có vẻ không đúng? Bạn check lại chỗ này nhé!
Minato
Cho mình hỏi sự khác nhau giữa “EntityManager” và “CrudRepository”?
Khanh Nguyen
EntityManager là của JPA còn CrudRepository là của Spring Data JPA nhé bạn. Bạn có thể đọc bài viết của mình về Spring Data JPA để hiểu rõ thêm về chúng nhé https://huongdanjava.com/vi/tong-quan-ve-spring-data-jpa.html
abc
ok cho em hỏi lại tổng kết một làn cuối, hibernate ngoài đặc tả cho jpa nó còn đặc tả chỉ chính bản thân nó, jpa thì có đặc tả là hibernate or eclipse link or …. thì như trong bài này nó tự đặc tả cho chính nó phải ko anh (tại em thấy bài viết trươc anh nói là jpa như một interface mà interface thì ko có các hàm chi tiết của no mà chỉ để cho thằng khác implement và viết chi tiết lại)
abc
à sorry anh em chưa đọc kỹ, bài này là thằng jpa có đặc tả của nó là hibernate.
tại bửa em thực tập bên tma thì dùng hibernate ko thấy cái gì liên quan đến file persistence.xml hóa ra là bên đó dùng hibernate đặc tả cho chính no. làm cho em rối tung mù xòe mấy phần này
Khanh Nguyen
Rối thiệt rồi đó,:D
Khanh Nguyen
😀 Tẩu hoả nhập ma luôn rồi đó em.
Đa số các bài viết của Hướng Dẫn Java đều sử dụng Hibernate là implementation của JPA nha em.
Phan Quân
anh cho em hỏi. em có 2 bảng như sau
User(Username, Password) Username là khóa chính
UserInfo(Username, Fullname); Username là khóa chính và là khóa ngoài tham chiếu đến User.
Vậy quan hệ này là OneToOne hay sao ạ.
Và config như thế nào ạ
Khanh Nguyen
Đúng rồi em. Sử dụng @OneToOne annotation trên Entity của User nhé!
Lap
anh có thể cho em xin skype của anh được không, em đang rất mơ hồ về mọi thứ nên cần anh giúp để vượt qua
Khanh Nguyễn
Bạn không hiểu về vấn đề gì thì có thể gửi tin nhắn cho mình.
Sử dụng http://huongdanjava.com/lien-he để gửi tin nhắn cho mình nhé! Hoặc gửi email huongdanjava.com@gmail.com.
Skype thì đôi lúc mình bận quá, không trả lời hết được. Anyway, bạn có thể add skype của mình: phys.rainbow.
Trinh Minh
Anh cho em hỏi sao emcopy code y sì của anh luôn, có sửa lại (password, user, url cho phù hợp với mySQL của mình) nhưng chạy không được. Nó ko báo lỗi gì hết nhưng nó như kiểu rơi vào vòng lặp vô tận ấy, ko chạy tiếp được nữa. Mình debug thì nó bị ngay dòng đầu tiên này luôn :
EntityManagerFactory emf = Persistence.createEntityManagerFactory(“jpaexample”);
Và nó làm cái MySQL Workbench của mình bị treo luôn, tắt eclipse mới hết treo
Khanh Nguyễn
Có cách nào bạn gửi cái project bạn đang chạy cho mình không?
Mình sẽ thử chạy lại project của bạn trên máy mình để xem thử bị gì.
BaoNam
cho mình hỏi khi nào dùng EntityMangager (của JPA) và khi nào dùng Session (của hibernate) để truy xuất dữ liệu vậy bạn. Tại sao có loại này rồi còn phải có loại kia, và ở dự án thực tế hộ thường dùng cách nào, mình thấy khó phân biệt quá.
Khanh Nguyễn
Bạn nên đọc thêm phần này nhé: http://huongdanjava.com/su-khac-nhau-giua-jpa-va-hibernate-framework.html
Ở các dự án mình làm, đa số họ dùng JPA bạn à.
Đức Nam
a có thể nói rõ hơn phần này đc ko, trong bài viết kia em thấy ko đề cập.
Khanh Nguyen
Hibernate có 2 phiên bản: 1 phiên bản thì hiện thực các đặc tả của JPA sử dụng EntityManager để quản lý các tables và thao tác trên chúng.
Phiên bản thứ hai là phiên bản của riêng nó, nghĩa là Hibernate cũng xây dựng một cách khác để quản lý database. Cách này thì chúng ta sẽ sử dụng Session để thao tác trên database.
Em phải phân biệt cái này để khỏi bị nhầm lẫn nhé!