The company is developing a web application using the struts2 framework. This application uses Hibernate instead of JDBC for DB access, but I was in trouble because I didn't have any knowledge. Meanwhile, I came across the following good books, so I understood the contents and summarized the main points.
--Introduction to JPA for database access learned with Seasar2 and Hibernate Written by Toshihiro Nakamura, published by Mainichi Communications
Associate a Java object (Object) with data on a relational database (Relational). A major feature of JPA is that it has an O / R mapping function. On the other hand, JDBC (*) needs to program the association between the object and the DB. (The program becomes complicated.)
b. JPA(Java Persistence API) API included in Java EE (*). JPA is only a specification, and there are multiple products that implement JPA, and the representatives are Hibernate, TopLink Essentials, and Open JPA. Environmental aspect: Can be used with Java EE and Java SE. JDK 5.0 or above is required.
-[Introduction to Java] Explains the differences between Java SE and EE and JRE / JDK in the world's easiest way https://www.sejuku.net/blog/12902 --Differences between Java and Java EE in Eclipse https://qiita.com/kojocho/items/b5d3646012b7a6411c3d
c. Hibernate
An open source JPA implementation provided by Red Hat. To use Hibernate as a JPA implementation, you need 3 products: Hibernate Core, Hibernate Annotations, and Hibernate Entity Manager. Compared with JDBC, the following 4 processes are unnecessary. (Details will be described later)
--SQL statement --Refilling data from ResultSet --Resource close --Exception handling
JPA associates a table with a Java class by O / R mapping and treats one record of the table as one instance of Java class. This time. Java classes are called ** entity classes **, their instances are called ** entities **, and entities are handled through ** EntityManager **.
When an application requests to get an entity, EntityManager first checks if it is cached in the persistent context and returns the cached entity if the cache exists.
The image looks like this.
There are two types of entity acquisition methods: primary key acquisition (1) and JPQL (2) acquisition.
To get an entity with a primary key, use EntityManager's *** find method ***.
item | Description |
---|---|
argument | Pass the entity class as the first argument and the primary key value as the second argument |
Return value | If an entity exists, that entity. Null if it does not exist |
public void findById() throws Exception{
// EntityManager(em)Is injected with DI
//Get record (entity) whose primary key of Emp class (table) is "1"
Emp emp = em.find(Emp.class, 1L);
}
In the case where the entity is not acquired by specifying the primary key, the find method of EntityManager cannot be used and it is necessary to implement it in JPQL. JPQL is JPA's own query language and is completely different from SQL. In JPQL, you can create a Query object by passing an argument to the *** createQuery method *** of EntityManager. You can pass bind variable parameters and paging information to Query. Entity can be obtained by executing getResultList method and getSingleResult method of Query.
item | Description |
---|---|
argument | jpql (inquiry text) |
Return value | If there is a record that matches the condition, the matching entity list Empty list if it does not exist (size = 0) |
You can update the data by getting the entity you want to update with EntityManager and changing the state of that entity. EntityManager manages the original data before the change, compares the original data with the current data at an appropriate timing, and automatically detects the update. When it detects that an entity has been updated, an Update statement is automatically issued.
(The condition of the version column (described later) used in optimistic exclusive control is automatically added to the Update statement issued at this time.)
public void updateEntity() throws Exception{
// EntityManager(em)Is injected with DI
//Get record (entity) whose primary key of Emp class (table) is "1"
Emp emp = em.find(Emp.class, 1L);
emp.setEmpName("NEWNAME");
//Update statement is issued automatically
}
To add an entity, pass the newly created entity to the *** persist method *** of EntityManager. If @GeneratedValue annotation is specified in the primary key record in the entity class definition of the operation target, it is automatically set without setting the value in the primary key element.
public void persistEntity() throws Exception{
// EntityManager(em)Is injected with DI
//Generate the following Emp entity
Emp emp = new Emp();
emp.setEmpNo (123);
emp.setEnpName("123Name");
em.persist(emp);
//Insert statement is issued automatically
}
To delete an entity, pass the entity you want to remove to the *** remove method *** of EntityManager. EntityManager issues a SQL Delete statement at the right time.
(The condition of the version column (described later) used in optimistic exclusive control is automatically added to the Delete statement issued at this time.)
public void removeEntity() throws Exception{
// EntityManager(em)Is injected with DI
//Delete the following entity
em.remove(emp);
//Delete statement is issued automatically
}
The annotations required for O / R mapping are as follows. All of these annotations belong to the "javax.persistence" package.
*** For the fetch attribute of @ManyToOne, @OneToMany, and @OneToOne, basically specify "fetchType.LAZY" (described later). *** ***
No | Annotation | Specified location | Meaning to represent |
---|---|---|---|
1 | @Entity | class | Being an entity Entity name is a name used in JPQL to identify an entity in the Java world. Example:@Entity(name = "Hoge") |
2 | @Id | field | Being a primary key |
3 | @Transient | field | Be non-permanent Give when you do not want to associate with database columns |
4 | @GeneratedValue | field | Automatically generate primary key value |
5 | @ManyToOne | field | The relationship is many-to-one |
6 | @OneToMany | field | The relationship is one-to-many |
7 | @OneToOne | field | The relationship is one-to-one |
8 | @Table | class | Specify the table to be mapped |
9 | @Column | field | Specify that it is a mapping target column Columns without NOT NULL constraints must use a wrapper type to represent NULL |
10 | @JoinColumn | field | Specify the source column and the destination column |
11 | @SequenceGenerator | field | Definition of the sequence that generates the primary key |
12 | @TableGenerator | field | Definition of the table that generates the primary key |
13 | @Version | field | Must be a version number field for using optimistic concurrency control (discussed below) Field type should be Integer type or Long type |
When a table has a parent-child configuration, the child table is not acquired when the parent table is acquired, but is acquired when needed (on the back side).
Since the fetch attribute of @ManyToOne, @OneToMany, and @OneToOne defaults to "fetchType.EAGER", use the delayed loading "fetchType.LAZY" unless you have a specific intention.
Issue a SELECT statement once to get N records (parent entities) from any table, N records issue a SELECT statement once to get the related data (child entity), a total of N times. Please note that a large amount of SQL will be issued unintentionally. There are the following two solutions.
--Using JOIN FETCH with JPQL -Use @Fetch annotation
reference
--JPA performance problems and countermeasures https://qiita.com/itagakishintaro/items/04b6933a29e92f8ee4b7
Specify the entity name (≠ table name) in the FROM section of JPQL. The identification variable (hereinafter "e" in SQL) is declared after the entity name, and the extraction items etc. are specified using it.
select e from Employee e;
With lazy loading applied, child entities are only retrieved when needed. On the other hand, if it is known that child entities are also needed from the beginning, it is more efficient to get them at the same time with one SQL. In such cases, use *** fetch join ***. The SQL using fetch join is as follows.
select distinct d d from Department d inner join fetch d.employees where d.name = "ABC";
Once retrieved, the entity is managed in a persistent context. Within the persistent context, it is managed in the following four states. These states change due to EntityManager method execution and persistence context termination, and are called *** entity lifecycle ***. The figure is as follows.
--New The new entity remains the new entity unless you specify the EntityManager's persist and merge methods.
--Managed When an entity is acquired using EntityManager's find method or JPQL, when the entity is passed to the merge method by EntityManager's persist method, the entity is managed in a persistent context. Persistent field changes to managed entities are automatically detected.
--Detached Even if you make changes to the separated entity, the changes will not be reflected in the persistence context unless the entity is remanaged by the merge method of EntityManager.
--Removed If you pass the managed entity to the remove method of EntityManager, it will be removed from the persistence context.
EntityManager reflects managed entities and deleted entities in the database. This process is called *** database synchronization ***. Synchronization writes entity change information stored in the persistence context to the database.
The default timing for database synchronization is as follows:
--When the flush method of EntityManager is called --Just before the transaction is committed --Just before executing the inquiry
Exclusive control includes pessimistic exclusive control that locks specific data and prohibits CRUD from other transactions, and optimistic exclusive control that does not lock data and fails the other processing when updates conflict. ..
JPA can realize optimistic exclusive control based on this version number by preparing an integer type column that manages the version number (@Version assignment) in the database.
--I want to check the SQL issued by Hibernate in the log → Set "true" in the hibernate.show_sql property of persistence.xml (*).
<property name = "hibernate.show_sql" value = "true" />
--I want to format and display the SQL in the log issued by Hibernate → Set "true" in the hibernate.format_sql property of persistence.xml (*).
<property name = "hibernate.format_sql" value = "true" />
Recommended Posts