https://youtu.be/07GSHVeQbKo
Khi phát triển các ứng dụng Java, chúng ta thường cần lưu trữ dữ liệu vào cơ sở dữ liệu quan hệ như MySQL database, PostgreSQL database hoặc là Oracle database. Java cung cấp JDBC để ứng dụng có thể kết nối và làm việc với database. Tuy nhiên, khi ứng dụng trở nên lớn hơn, việc sử dụng JDBC trực tiếp có thể dẫn đến khá nhiều code lặp lại, đặc biệt là khi chúng ta phải chuyển đổi dữ liệu giữa các Java object và các record trong database.
Để giải quyết vấn đề này, các bạn có thể sử dụng JPA (Java Persistence API), hiện tại thì nó được gọi là Jakarta Persistence API, với ORM (Object-Relational Mapping) đó các bạn. JPA là một standard specification dành cho việc sử dụng các Java object để làm việc với relational database. Các bạn có thể sử dụng nó để mapping giữa Java object và các record trong database và cũng có thể sử dụng nó để truy vấn, thao tác với các record này. Cụ thể như thế nào? Trong bài viết này, chúng ta sẽ tìm hiểu JPA là gì, ORM là gì, JPA có vai trò như thế nào trong Java ecosystem và đặc biệt là sự khác nhau giữa JPA và Hibernate, các bạn nhé!
Để làm ví dụ cho bài viết này, mình sẽ tạo mới một Maven project:

Để làm việc với JPA thì các bạn có thể khai báo Jakarta Persistence API dependency như sau:
|
1 2 3 4 5 |
<dependency> <groupId>jakarta.persistence</groupId> <artifactId>jakarta.persistence-api</artifactId> <version>3.2.0</version> </dependency> |
Vấn đề của việc lưu trữ Java Object vào Database
Giả sử bây giờ, mình có một class Student có nội dung 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 24 25 26 27 28 29 30 31 |
package com.huongdanjava.jpa; public class Student { private Long id; private String name; private String email; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } } |
Trong database, mình có một table students với cấu trúc như sau:
|
1 2 3 4 5 6 |
CREATE TABLE `students` ( `id` INT NOT NULL, `name` VARCHAR(100) NOT NULL, `email` VARCHAR(100) NOT NULL, PRIMARY KEY (`id`) ) ENGINE = InnoDB; |
Mình cũng đã insert sẵn một số example data như sau:
Trong ứng dụng Java, để lấy thông tin student từ table students này, chúng ta sẽ làm việc với Student object với các attribute là id, name, email. Còn trong database thì chúng ta sẽ làm việc với table students với các column là id, name và email. Đây chính là object-relational impedance mismatch — sự khác biệt giữa mô hình object-oriented của Java và mô hình relational của database đó các bạn.
Nếu sử dụng JDBC trực tiếp, chúng ta thường phải tự thực hiện nhiều công việc để chuyển đổi giữa hai mô hình này, ví dụ 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 24 25 26 27 28 29 30 31 32 33 34 35 |
package com.huongdanjava.jpa; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class Application { static void main(String[] args) throws SQLException { try (Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3307/example", "root", "123456")) { String sql = "SELECT id, name, email FROM students WHERE id = ?"; PreparedStatement statement = connection.prepareStatement(sql); statement.setLong(1, 1); ResultSet resultSet = statement.executeQuery(); Student student = new Student(); if (resultSet.next()) { student.setId(resultSet.getLong("id")); student.setName(resultSet.getString("name")); student.setEmail(resultSet.getString("email")); } System.out.println(student.getName()); } } } |
Với một ứng dụng lớn thì kiểu code mapping như vậy có thể xuất hiện ở rất nhiều nơi. Do đó, việc sử dụng JPA với ORM sẽ giúp cho chúng ta làm việc dễ dàng hơn với database trong các ứng dụng Java đó các bạn.
ORM là gì?
ORM là viết tắt của Object-Relational Mapping.
Nó là kỹ thuật ánh xạ giữa các Java object trong ứng dụng Java và dữ liệu trong relational database.
Ví dụ như field id trong class Student có thể map với column id trong table students, field name có thể map với column name, field email có thể map với column email, …
ORM có thể giúp các bạn mô tả mapping này bằng cách sử dụng các annotation thay vì các bạn phải tự viết toàn bộ code để mapping.
Ví dụ các bạn có thể viết lại class Student sử dụng các annotation của JPA API 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 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
package com.huongdanjava.jpa; import jakarta.persistence.Entity; import jakarta.persistence.Id; import jakarta.persistence.Table; @Entity @Table(name = "students") public class Student { @Id private Long id; private String name; private String email; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } } |
Trong ví dụ trên:
Studentđại diện cho một persistent object.@Entityxác định rằng class này là một entity.@Table: nếu tên table trong database khác với tên entity, thì các bạn cần sử dụng annotation này để mapping nhé.idđược xác định là identity của entity thông qua@Id.
Các field của entity có thể được mapping tới các column trong database đó các bạn.
ORM chủ yếu cung cấp một abstraction để chúng ta có thể làm việc với persistence theo mô hình object-oriented.
JPA là gì?
JPA là viết tắt của Java Persistence API.
JPA là tên gọi được sử dụng trước đây cho specification về persistence trong Java. Ngày nay, specification này thuộc Jakarta EE và có tên chính thức là Jakarta Persistence nha các bạn.
JPA là một specification, không phải một implementation.
Specification này định nghĩa các API, annotation và behavior mà một persistence provider cần cung cấp.
Ví dụ, JPA định nghĩa các annotation như:
- @Entity
- @Id
- @Table
- @Column
và các API như:
- EntityManager
Nhưng JPA không tự thực hiện việc kết nối và thao tác với database. Công việc đó sẽ được thực hiện bởi một JPA provider.
JPA Specification và JPA Implementation
Để hiểu JPA, các bạn cần phải phân biệt hai khái niệm:
- Specification
- Implementation
Một specification định nghĩa contract.
Implementation là phần mềm thực hiện contract đó.
Một số JPA provider phổ biến gồm:
- Hibernate
- EclipseLink
- OpenJPA
Trong đó, Hibernate là implementation mà chúng ta thường gặp nhất trong các ứng dụng Java hiện đại.
Các bạn hãy nhớ:
- JPA là specification.
- Hibernate là một implementation của specification đó.
JPA và Hibernate khác nhau như thế nào?
Đây là một trong những điểm dễ gây nhầm lẫn nhất đối với những người mới học JPA.
Khi chúng ta viết:
|
1 2 3 4 |
@Entity public class Student { ... } |
@Entity là một annotation được định nghĩa bởi Jakarta Persistence.
Tương tự:
|
1 |
@Id |
cũng thuộc Jakarta Persistence.
Những API và annotation này không phải riêng của Hibernate.
Hibernate là một implementation có khả năng hiểu và thực hiện các quy tắc được định nghĩa bởi Jakarta Persistence.
Các bạn có thể hình dung:
Application -> Jakarta Persistence API -> Hibernate (hoặc là EclipseLink hay OpenJPA) -> JDBC -> Database
Chúng ta có thể viết application dựa trên JPA API thay vì phụ thuộc trực tiếp vào Hibernate API trong phần lớn các trường hợp.
Những khái niệm cơ bản trong JPA
JPA cung cấp một số khái niệm quan trọng, bao gồm:
- Entity
- Persistence Context
- EntityManager
- Entity Lifecycle
- Persistence Unit
- JPA Provider
Entity
Entity là một Java object được quản lý bởi persistence mechanism và có thể được lưu trữ vào database.
Như ví dụ ở trên thì Student là một entity đó các bạn.
Entity thường đại diện cho một khái niệm dữ liệu trong application. Ví dụ như các bạn có thể định nghĩa các entity như sau trong một ứng dụng:
- Student
- Course
- Employee
- Department
- Product
- Order
- Customer
Persistence Context
Persistence Context là một khái niệm rất quan trọng trong JPA. Các bạn có thể hiểu đơn giản rằng persistence context là một môi trường trong đó các entity instances được persistence provider quản lý.
Ví dụ như khi các bạn tạo nhiều instance cho entity Student thì Persistence Context nó sẽ nắm giữ thông tin của các instance này. Nhờ đó mà một entity nằm trong persistence context có thể được persistence provider theo dõi trạng thái của nó, đó các bạn.
EntityManager
EntityManager là một trong những API quan trọng nhất của Jakarta Persistence. Nó cung cấp các API để application có thể làm việc với entity và persistence context.
Một số operation phổ biến được cung cấp bởi EntityManager bao gồm:
- persist(): entity sẽ được managed và sẽ được insert vào database
- find(): tìm kiếm một entity bằng primary key của nó
- merge(): copy trạng thái của một entity vào một entity đã được manage
- remove(): đánh dấu một entity sẽ bị xóa
- detach(): xóa entity khỏi persistence context
- refresh(): reload trạng thái của entity từ database
Mình sẽ đi chi tiết các phương thức này sau các bạn nhé.
Entity lifecycle
Một entity có thể trải qua nhiều trạng thái khác nhau trong quá trình tồn tại. Các trạng thái chính thường được nhắc tới là:
- New: một entity là New khi nó chỉ mới được tạo và chưa được quản lý bởi persistence context.
- Managed: entity đã được quản lý bởi persistence context
- Detached: entity trước đó đã được quản lý bởi một persistence context nhưng hiện tại đã bị remove ra khỏi persistence context đó.
- Removed: khi entity bị đánh dấu là sẽ remove trong database.
Chúng ta có thể tìm hiểu chi tiết entity lifecycle và cách EntityManager tác động đến các trạng thái này trong các bài viết khác, các bạn nhé.
Persistence Unit
Persistence Unit là một tập hợp các persistence-related configurations và entity được quản lý cùng nhau.
Trong các ứng dụng Jakarta Persistence truyền thống, persistence unit thường được cấu hình thông qua tập tin persistence.xml. Persistence unit xác định các thông tin cần thiết cho persistence environment, chẳng hạn như persistence provider và database configuration.
Trong các framework hiện đại, các bạn có thể không trực tiếp làm việc với persistence.xmlnhưng khái niệm persistence unit vẫn là một phần quan trọng của Jakarta Persistence, đó các bạn.
Ví dụ JPA đơn giản
Bây giờ, chúng ta sẽ convert ví dụ trên bằng cách sử dụng Jakarta Persistence để xem cách làm việc với nó sẽ như thế nào, các bạn nhé!
Đầu tiên, các bạn cần thêm Hibernate dependency để làm phần implementation của Jakarta Persistence như sau:
|
1 2 3 4 5 |
<dependency> <groupId>org.hibernate.orm</groupId> <artifactId>hibernate-core</artifactId> <version>7.4.14.Final</version> </dependency> |
hibernate-core dependency sẽ tự động include jakarta.persistence-api dependency nên các bạn không cần khai báo jakarta.persistence-api dependency nữa nhé.
Các bạn cần tạo mới tập tin Persistence Unit persistence.xml trong thư mục /src/main/resources/META-INF để định nghĩa thông tin về database và persistence provider như sau:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<?xml version="1.0" encoding="UTF-8"?> <persistence xmlns="https://jakarta.ee/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_2.xsd" version="3.2"> <persistence-unit name="jpaexamplePU"> <class>com.huongdanjava.jpa.Student</class> <properties> <property name="jakarta.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/> <property name="jakarta.persistence.jdbc.url" value="jdbc:mysql://localhost:3307/example"/> <property name="jakarta.persistence.jdbc.user" value="root"/> <property name="jakarta.persistence.jdbc.password" value="123456"/> </properties> </persistence-unit> </persistence> |
Như các bạn thấy, chúng ta sẽ định nghĩa thông tin về entity class và thông tin database bên trong thẻ <persistence-unit>
Bây giờ thì trước khi lấy đối tượng EntityManager để làm việc với các entity, chúng ta sẽ khởi tạo đối tượng của class EntityManagerFactory từ tập tin persistence.xml này như sau:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
package com.huongdanjava.jpa; import jakarta.persistence.EntityManager; import jakarta.persistence.EntityManagerFactory; import jakarta.persistence.Persistence; public class Application { static void main(String[] args) { try (EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpaexamplePU")) { EntityManager em = emf.createEntityManager(); } } } |
Các bạn chỉ cần truyền thông tin Persistence Unit name vào phương thức createEntityManagerFactory là được. Jakarta Persistence với Hibernate implementation sẽ đọc tập tin persistence.xml để tạo EntityManagerFactory cho chúng ta.
Sau khi đã lấy EntityManager từ EntityManagerFactory, các bạn có thể lấy thông tin student như sau:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
package com.huongdanjava.jpa; import jakarta.persistence.EntityManager; import jakarta.persistence.EntityManagerFactory; import jakarta.persistence.Persistence; public class Application { static void main(String[] args) { try (EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpaexamplePU")) { EntityManager em = emf.createEntityManager(); Student student = em.find(Student.class, 1); System.out.println(student.getName()); } } } |
Kết quả khi các bạn chạy ví dụ này như sau:

Như các thấy, chỉ với vài dòng code, chúng ta đã có thể lấy được thông tin của Student trong database rồi.
JPA và JDBC
JPA không thay thế JDBC theo nghĩa JDBC không còn tồn tại. Thay vào đó, JPA thường nằm ở abstraction level cao hơn JDBC nha các bạn.
Đây là bảng so sánh đơn giản giữa JPA và JDBC:
| JDBC | JPA |
|---|---|
| API để làm việc với database | Specification cho persistence |
| SQL-centric | Object-centric |
| Developer thường xử lý mapping thủ công | ORM hỗ trợ mapping |
| Làm việc trực tiếp với JDBC API | Làm việc thông qua persistence API |
| Không phải ORM | Cung cấp ORM programming model |
Với JDBC, chúng ta sẽ thường làm việc trực tiếp với:
- Connection
- PreparedStatement
- ResultSet
Trong khi đó, với JPA, chúng ta sẽ làm việc với:
- Entity
- EntityManager
- Persistence Context
JPA provider sau đó có thể sử dụng JDBC để giao tiếp với database.
Kết luận
JPA là một phần rất quan trọng trong Java persistence ecosystem. Ngày nay, JPA được gọi chính thức là Jakarta Persistence và đóng vai trò là một specification cho persistence trong Java.
Điều quan trọng nhất, các bạn cần nhớ là:
- JPA = Specification
- Hibernate = Implementation
JPA cung cấp một object-oriented persistence model dựa trên ORM, trong đó các Java object có thể được mapping với dữ liệu trong relational database.
Nhờ vậy mà chúng ta có thể làm việc với database dễ dàng hơn trong các ứng dụng Java đó các bạn.


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é!