Basic Spring CRUD
Create, Read, Update, and Delete are the four basic database access operations. This article explains these basic operations.
Retrieve a List of Data with Query
The basics of database operations are called CRUD. Previously, we created an example that stored a few pieces of dummy data and displayed a list of that data.
Reference: Using Spring Data JPA - Let’s use a database.
If you look at the example, the basics of Create and Read are already in place. Let’s review how it was done.
package com.devkuma.spring.db;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Query;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class App {
public static void main(String[] args) {
ApplicationContext app = new
AnnotationConfigApplicationContext(SampleEntityConfig.class);
EntityManagerFactory factory = app.getBean(EntityManagerFactory.class);
EntityManager manager = factory.createEntityManager();
makeDummyData(manager);
// get list
Query query = manager.createQuery("from SampleEntity");
List list = query.getResultList();
printList(list);
System.out.println("...ok.");
}
public static void makeDummyData(EntityManager manager) { ...omitted... }
public static void printList(List list) { ...omitted... }
}
First is retrieving a list of data. This uses a class named Query.
Query query = manager.createQuery("from SampleEntity");
This creates an instance of the Query class and calls its methods to retrieve the full list of entities. Query is used to access the database with statements similar to simplified SQL query statements.
Instead of new, the instance is created with the createQuery method. The argument is the text from SampleEntity. This syntax means that all SampleEntity entities are retrieved.
List list = query.getResultList();
Calling getResultList on the Query created in this way returns the retrieved entities as a list. After that, you can take entities from the result list one by one and process them.
The key question is what result you get when you specify a certain text string as the createQuery argument. For now, remember that writing from entity retrieves a list of that entity.
Add a New Entity
Next, save a new entity. Conceptually, this is very simple. Create an instance of the entity class and call the save method on EntityManager.
However, be careful when updating the database. Simply reading data is straightforward, but updating data requires caution. Databases may be accessed from several places at the same time. If data is updated while other access is taking place, problems can occur.
Therefore, when data must be updated, you need to use a transaction. A transaction is a feature that lets multiple operations be grouped and executed together.
While a transaction is in progress, external access to the data being processed is blocked. After the transaction processing completes, external access to the data becomes available again.
package com.devkuma.spring.db;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Query;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class App {
public static void main(String[] args) {
ApplicationContext app = new
AnnotationConfigApplicationContext(SampleEntityConfig.class);
EntityManagerFactory factory = app.getBean(EntityManagerFactory.class);
EntityManager manager = factory.createEntityManager();
makeDummyData(manager);
// get list
Query query = manager.createQuery("from SampleEntity");
List list = query.getResultList();
printList(list);
System.out.println("...ok.");
}
// create dummy entity data.
public static void makeDummyData(EntityManager manager) {
EntityTransaction transaction = manager.getTransaction();
transaction.begin();
manager.persist(new SampleEntity("tuyano", "syoda@tuyano.com"));
manager.persist(new SampleEntity("hanako", "hanako@flower"));
manager.persist(new SampleEntity("taro", "taro@yamada"));
manager.persist(new SampleEntity("sachiko", "sachico@happy"));
manager.flush();
transaction.commit();
}
public static void printList(List list) { ...omitted... }
}
By using a transaction, external access is blocked while a specific operation is performed, allowing the database to be updated safely. Now let’s look at the flow.
EntityTransaction transaction = manager.getTransaction ();
The getTransaction method of EntityManager obtains an instance of the EntityTransaction class. This is the transaction class.
transaction.begin ();
Run the begin method to start transaction processing.
manager.persist(new SampleEntity ( "tuyano", "syoda@tuyano.com"));
manager.persist(new SampleEntity ( "hanako", "hanako @ flower"));
manager.persist(new SampleEntity ( "taro", "taro @ yamada"));
manager.persist(new SampleEntity ( "sachiko", "sachico @ happy"));
To add a new entity, use the persist method of EntityManager. Call it with an instance of the entity class, SampleEntity here, and that entity is saved to the database.
manager.flush ();
transaction.commit ();
Finally, call flush on EntityManager to clear the buffer, and call the commit method of EntityTransaction to commit. Then all persisted entities are saved to the database. Once committed, transaction processing ends immediately and the database is released.
To add data, you need to understand how to use transactions. This is the foundation of database updates, so be sure to remember the basic usage here.
Modify an Entity
Next is modifying an entity. To update data already stored in the database, retrieve the corresponding data entity, change its values, and save it.
The following is a simple example.
package com.devkuam.spring.db;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Query;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class App {
private static EntityManager manager;
public static void main(String[] args) {
ApplicationContext app = new
AnnotationConfigApplicationContext(SampleEntityConfig.class);
EntityManagerFactory factory = app.getBean(EntityManagerFactory.class);
manager = factory.createEntityManager();
// make dummy
makeDummyData();
// update entity
updateEntity(1L);
updateEntity(3L);
// get list
Query query = manager.createQuery("from SampleEntity");
List list = query.getResultList();
printList(list);
System.out.println("...ok.");
}
public static void makeDummyData() { ...omitted... }
public static void printList(List list) { ...omitted... }
// update entity
public static void updateEntity(long id) {
SampleEntity entity = manager.find(SampleEntity.class, id);
entity.setName("**update name**");
entity.setMail("**update@mail**");
EntityTransaction transaction = manager.getTransaction();
transaction.begin();
manager.merge(entity);
manager.flush();
transaction.commit();
}
}
When executed, this changes and prints two of the four pieces of dummy data.
The update processing is organized in the updateEntity method. The ID number of the data to change can be passed as an argument.
Let’s look at the flow.
EntityManagerFactory factory = app.getBean(EntityManagerFactory.class);
manager = factory.createEntityManager();
First, obtain an EntityManager instance and use it for processing.
SampleEntity entity = manager.find(SampleEntity.class, id);
Obtain a SampleEntity instance. This is not created with new; instead, the find method of EntityManager is called. find searches for an entity with a specific ID. Specify the class value of the entity class and the ID value of the entity to search for as arguments.
When you first obtain a list, later processing can become tedious. With this EntityManager method, however, you can get an entity simply by specifying its ID. However, this cannot be used if you do not know the ID.
Next, call methods on the retrieved entity and update its contents.
entity.setName("** update name **");
entity.setMail("** update @ mail **");
After editing, use a transaction to perform the update, just as when creating a new entity. The flow is basically the same as creating a new entity, but the update part is different.
EntityTransaction transaction = manager.getTransaction ();
transaction.begin ();
manager.merge (entity);
manager.flush ();
transaction.commit ();
Changes to an already stored entity are performed with the merge method. Specify the instance of the entity class to update as the argument, and the values of that entity are updated to the latest state.
After that, flush the EntityManager and commit the EntityTransaction to complete the work. Unlike creating a new entity, updating means obtaining an entity with a specific ID through find and then performing the update with merge.
Delete an Entity
The remaining operation is deleting an entity.
Deletion is basically the same as updating an entity. Specify an ID to obtain the entity instance, delete it, and commit the transaction.
The following is a simple example.
package com.devkuma.spring.db;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Query;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class App {
private static EntityManager manager;
public static void main(String[] args) {
ApplicationContext app = new
AnnotationConfigApplicationContext(SampleEntityConfig.class);
EntityManagerFactory factory = app.getBean(EntityManagerFactory.class);
manager = factory.createEntityManager();
// make dummy
makeDummyData();
// delete entity
deleteEntity(1L);
deleteEntity(3L);
// get list
Query query = manager.createQuery("from SampleEntity");
List list = query.getResultList();
printList(list);
System.out.println("...ok.");
}
public static void makeDummyData() { omitted }
public static void printList(List list) { omitted }
// delete entity
public static void deleteEntity(long id) {
SampleEntity entity = manager.find(SampleEntity.class, id);
EntityTransaction transaction = manager.getTransaction();
transaction.begin();
manager.remove(entity);
manager.flush();
transaction.commit();
}
}
When executed, this removes the elements with ID=1 and ID=3 and displays the remaining two. Let’s summarize the flow.
SampleEntity entity = manager.find (SampleEntity.class, id);
First, use find on EntityManager to obtain the entity with the specified ID, SampleEntity here.
EntityTransaction transaction = manager.getTransaction ();
transaction.begin ();
Next, obtain an EntityTransaction instance and start transaction processing.
manager.remove(entity);
Delete the entity. This uses the remove method of EntityManager. If you specify an entity instance retrieved from the database as the argument, that entity is removed from the database.
manager.flush();
transaction.commit();
Finally, flush the EntityManager and commit the EntityTransaction. The database update is completed and the data is deleted. Once you understand entity updates, deletion can be performed in almost the same way.
Basics of JPQL Query Statements
At this point, you can perform the basic CRUD operations. The part you still need to understand a little more is the most basic part: Read.
The previous example had a simple sample that retrieved all entities. In actual processing, however, you will often need to search for entities with more detailed conditions.
When retrieving entities, we used a class named Query. When creating this Query instance, the statement from SampleEntity was passed as an argument. This statement works like an SQL query statement and is called JPQL. However, it is written a little differently from SQL. First, let’s explain the basic way to write entity searches.
Basic JPQL Search
from entity where condition
Using the familiar where clause from SQL lets you perform most basic searches. The condition expression is written with comparison operators such as equals signs (=<>).
Return the entity whose ID is 1
from SampleEntity where id = 1
Return entities whose ID is greater than 2
from SampleEntity where id > 2
To search text, you can also use fuzzy search with like. You can specify wildcards with the % symbol.
Return entities whose name starts with ‘K’
from SampleEntity where name like 'K %'
To set multiple conditional expressions, use and and or. In the where clause, multiple conditions are connected with and or or, such as condition and condition.
Retrieve entities whose id is between 10 and 20 inclusive
from SampleEntity where id> = 10 and id <= 20
For now, if you understand these basic search methods, you should be able to handle most beginner-level data search processing. It is useful to actually create and execute JPQL query statements yourself.