Cơ bản về JPA

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:

Cơ bản về JPA

Vì mình sẽ sử dụng JPA với implementation của Hibernate, do đó, mình sẽ thêm Hibernate dependencies như sau:

Mình cũng sẽ sử dụng MySQL database nên mình cũng sẽ thêm MySQL Driver dependency như sau:

Project Lombok:

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:

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).

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.

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.

Cơ bản về JPA

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.

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.

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:

Ở đâ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:

và dùng đối tượng EntityManager để lưu đối tượng Clazz này vào database:

Toàn bộ code như sau:

Kết quả:

Cơ bản về JPA


3.7/5 - (3 bình chọn)

22 thoughts on “Cơ bản về JPA

  1. 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 ạ.

  2. 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

    1. 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ử.

      1. 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 😀

        1. @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é!

  3. 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)

    1. à 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

  4. 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 ạ

  5. 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

    1. 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ì.

  6. 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á.

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

Add Comment