“Java Development Guide” How to use JPA and Spring to manage transactions in MyEclipse? (two)

This tutorial introduces some JPA/spring-based features, focusing on JPA-Spring integration and how to take advantage of these features. You’ll learn how to:

  • Set up a project for JPA and Spring
  • Reverse engineer database tables to generate entities
  • Implement creation, retrieval, editing and deletion functions
  • Enable container-managed transactions

In the above (>”>Click here to review>>), we introduced how to use JPA and Spring Facets to create a Java project and reverse engineering. This article will continue to introduce how to create an application and enable container-managed transactions.

MyEclipse v2023.1.2 offline version download

3. Writing applications

Now that MyEclipse has generated all this code, you can quickly focus on writing the “business logic”, or more specifically, the “code that actually performs the task”.

The JPA tutorial covers the functionality of each entity and DAO class, as well as a basic outline of the main methods to run a simple scenario, including:

  • Create a new entity and insert it into the database
  • Retrieve entities
  • Update entity
  • Delete entity

Similarly, in this tutorial you will see how to get and use a DAO and manage transactions using Spring.

The starting point for this demonstration is the RunJPA.java class, look at the main method in this class.

/* 1. Initialize the transactionManager and DAO */
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
txManager = ((JpaTransactionManager) ctx.getBean("transactionManager"));
dao = ProductlineDAO.getFromApplicationContext(ctx);

/* 2. Create a reference to our ID */
String productlineID = "Men Shoes";

/* 3. Save a new productline to the DB */
saveProductline(productlineID);

/* 4. Load the productline from DB to make sure it worked */
loadProductline(productlineID);

/* 5. Update the productline in the DB and check it */
updateProductline(productlineID);

/* 6. Delete the productline from the DB */
deleteProductline(productlineID);

The sections of code marked in blue are Spring calls where you retrieve configured beans from the bean configuration. Note that since you are managing transactions manually, you also need to retrieve the ‘transactionManager’ from the bean configuration.

The remaining items, #2 – #6, simply call each “do something” method.

3.1 Saving entities

The first interesting method is “saveProductline”, the purpose of this method is to create a new entity and store it in the DB.

/* 1. Create a new Productline instance */
Productline newProductline = new Productline(productlineID,
"Shoes formen.", "<strong>MenShoes</strong>", null);

/* 2. Store our new product line in the DB */
TransactionStatus status = txManager
.getTransaction(new DefaultTransactionDefinition());
dao.save(newProductline);
txManager.commit(status);

First, create a new Productline instance with some basic values. Secondly using transactionManager, the transaction starts before saving the entity to DB. After saving the entity, the transaction is committed.

The purpose of manually managing transactions is because as a developer you know the scope of the “save” operation. Depending on how the application is written, the scope of some operations may include many database modifications, and it is important to wrap all of this in a transaction to prevent failure in the middle of the work. You don’t want to leave your data in a state where some of it is correct and some of it is out of date.

3.2 Retrieve entities

The next method retrieves the entity from the DB using the ID assigned to it and displays its value, which confirms that the save operation was successful.

/* 1. Now retrieve the new product line, using the ID we created */
Productline loadedProductline = dao.findById(productlineID);

/* 2. Print out the product line information */
System.out.println("*NEW* Product Line [productLine="
 + loadedProductline.getProductline() + ", textDescription="
 + loadedProductline.getTextdescription() + "]");

Note that in this code, no transactions are used. The reason is that this code only performs read operations and not write operations, even if the operation fails, any data in the DB will not be affected. Therefore, there is no need to use transactions to protect operations.

3.3 Update entities

Now this next piece of code may look longer, but that’s because it outputs the new value and confirms that the record was updated in the DB.

/* 1. Now retrieve the new product line, using the ID we created */
Productline loadedProductline = dao.findById(productlineID);

/*
* 2. Now let's change same value on the product line, and save the
* change
*/
loadedProductline.setTextdescription("Product line for men's shoes.");

TransactionStatus status = txManager
.getTransaction(new DefaultTransactionDefinition());
dao.update(loadedProductline);
txManager.commit(status);

/*
* 3. Now let's load the product line from the DB again, and make sure
* its text description changed
*/
Productline secondLoadedProductline = dao.findById(productlineID);

System.out.println("*REVISED* Product Line [" + "productLine="
 + secondLoadedProductline.getProductline()
 + ", textDescription="
 + secondLoadedProductline.getTextdescription() + "]");

Note that the update call is encapsulated in a transaction because it has to write something to the database and needs to be protected against failure.

In section 3 above, the product line is loaded from the database immediately after the update, and the update is confirmed by printing the value returned from the database.

3.4 Delete entities

Deleting an entity is almost the same as saving and updating the entity, the work is encapsulated in another transaction and the DAO is then told to do the work.

/* 1. Now retrieve the new product line,
using the ID we created */
TransactionStatus status = txManager
.getTransaction(new DefaultTransactionDefinition());
Productline loadedProductline = dao.findById(productlineID);

/* 2. Now let's delete the product line from
the DB */
dao.delete(loadedProductline);
txManager.commit(status);

/*
* 3. To confirm the deletion, try and load it again and make sure it
* fails
*/
Productline deletedProductline = dao.findById(productlineID);

/*
* 4. We use a simple inline IF clause to test for null and print
*SUCCESSFUL/FAILED
*/
System.out.println("Productline deletion: "
 + (deletedProductline == null ? "SUCCESSFUL" : "FAILED"));

Similar to the “updateProductline” implementation above, you’ll notice that a transaction is used to encapsulate the “delete” call, and then the code attempts to load the entity from the DB and confirms that the operation should fail.

Note: The reason why a transaction must encapsulate the ‘findById ‘ and ‘delete ‘ method calls is because the object managed by JPA must be part of the same transaction, to erase a loaded object it must be in the state where it was loaded and Try to erase it in the same transaction.

3.5 Running the program

The output of running this command looks like this:

How to use JPA and Spring to manage transactions in MyEclipse?

Output

The red text is the default log message that can be ignored (you can set a custom log4j.properties file if you wish to control logging), and below the log warning you can see two messages from TopLink (JPA implementation library), and from Three additional messages implemented.

The first message prints out the added new product line information, the second message updates the product line information and prints the new information, and the last message deletes the product line information from the DB and prints a confirmation message.

4. Enable Spring container-managed transactions

In addition to user-managed transactions, Spring also supports container-managed transactions through the @Transactional attribute. For container-managed transaction support, you must enable it when adding the facet, which you did earlier in this tutorial.

How to use JPA and Spring to manage transactions in MyEclipse?

Enable support for @Transactional annotation

Enabling this feature will add the following transaction elements to the bean configuration file, you should also add a JPAServiceBean which is used to delete entities using container managed transactions. See implementation below:

How to use JPA and Spring to manage transactions in MyEclipse?

Annotation-driven configuration elements

The JPAServiceBean implementation is shown below; note the ‘@Transactional’ annotation on the ‘deleteProductLine’ method and the absence of any user-managed transaction statements.

public class JPAServiceBean
{ private IProductlineDAO dao; @Transactional public void deleteProductLine(String productlineID)

{ /* 1. Now retrieve the new product line, using the ID we created */Productline loadedProductline = dao.findById(productlineID);

/* 2. Now let's delete the product line from the DB */
dao.delete(loadedProductline);

/*
* 3. To confirm the deletion, try and load it again and make sure it * fails
*/
Productline deletedProductline = dao.findById(productlineID);

/*
* 4. We use a simple inline IF clause to test for null and print
*SUCCESSFUL/FAILED
*/
System.out.println("Productline deletion: " + (deletedProductline == null ? "SUCCESSFUL" : "FAILED"));}

public void setProductLineDAO(IProductlineDAO dao) { this.dao = dao; }
}

Get the JPAServiceBean instance from the application context and use it as follows:

JPAServiceBean bean = (JPAServiceBean) ctx.getBean("JPAServiceBean");
bean.deleteProductLine(productlineID);