• 「Java开发指南」如何在MyEclipse中使用JPA和Spring管理事务?(二)


    本教程中介绍一些基于JPA/ spring的特性,重点介绍JPA-Spring集成以及如何利用这些功能。您将学习如何:

    • 为JPA和Spring设置一个项目
    • 逆向工程数据库表来生成实体
    • 实现创建、检索、编辑和删除功能
    • 启用容器管理的事务

    在上文中(点击这里回顾>>),我们为大家介绍了如何用JPA和Spring Facets创建一个Java项目以及逆向工程,本文将继续介绍如何创建一个应用并启用容器管理的事务等。

    MyEclipse v2023.1.2离线版下载

    3. 编写应用程序

    现在MyEclipse已经生成了所有这些代码,您可以快速地专注于编写“业务逻辑”,或者更具体地说,“实际执行任务的代码”。

    JPA教程介绍了每个实体和DAO类的功能,以及运行一个简单场景的主要方法的基本大纲,包括:

    • 创建一个新实体并将其插入数据库
    • 检索实体
    • 更新实体
    • 删除实体

    类似地,在本教程中您将看到如何使用Spring获取和使用DAO以及管理事务。

    这个演示的起点是RunJPA.java类,看看这个类中的main方法。

    1. /* 1. Initialize the transactionManager and DAO */
    2. ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
    3. txManager = ((JpaTransactionManager) ctx.getBean("transactionManager"));
    4. dao = ProductlineDAO.getFromApplicationContext(ctx);
    5. /* 2. Create a reference to our ID */
    6. String productlineID = "Men Shoes";
    7. /* 3. Save a new productline to the DB */
    8. saveProductline(productlineID);
    9. /* 4. Load the productline from DB to make sure it worked */
    10. loadProductline(productlineID);
    11. /* 5. Update the productline in the DB and check it */
    12. updateProductline(productlineID);
    13. /* 6. Delete the productline from the DB */
    14. deleteProductline(productlineID);

    用蓝色标记的代码部分是Spring调用,您可以在其中从bean配置中检索已配置的bean。请注意,由于您正在手动管理事务,因此还需要从bean配置中检索' transactionManager '。

    剩下的项目,#2 - #6,简单地调用每个“做某事”的方法。

    3.1 保存实体

    第一个有趣的方法是“saveProductline”,此方法的目的是创建一个新实体并将其存储在DB中。

    1. /* 1. Create a new Productline instance */
    2. Productline newProductline = new Productline(productlineID,
    3. "Shoes formen.", "MenShoes", null);
    4. /* 2. Store our new product line in the DB */
    5. TransactionStatus status = txManager
    6. .getTransaction(new DefaultTransactionDefinition());
    7. dao.save(newProductline);
    8. txManager.commit(status);

    首先,用一些基本值创建新的Productline实例。其次使用transactionManager,事务在将实体保存到DB之前开始。在保存实体之后,事务被提交。

    手动管理事务的目的是因为作为开发人员,您知道“保存”操作的范围。根据应用程序的编写方式,一些操作的作用域可能包含许多数据库修改,将所有这些都包装在一个事务中是很重要的,以防在工作进行到一半时失败。您肯定不希望让数据处于一种状态,其中一些是正确的,而另一些是过时的。

    3.2 检索实体

    下一个方法使用分配给实体的ID从DB中检索实体,并显示其值,这确认保存操作成功。

    1. /* 1. Now retrieve the new product line, using the ID we created */
    2. Productline loadedProductline = dao.findById(productlineID);
    3. /* 2. Print out the product line information */
    4. System.out.println("*NEW* Product Line [productLine="
    5. + loadedProductline.getProductline() + ", textDescription="
    6. + loadedProductline.getTextdescription() + "]");

    注意在这段代码中,没有使用任何事务。原因是这段代码只执行读操作而不执行写操作,即使操作失败,DB中的任何数据都不会受到影响。因此,不需要使用事务来保护操作。

    3.3 更新实体

    现在下一段代码看起来可能更长,但这是因为它输出了新值,并确认在DB中更新了记录。

    1. /* 1. Now retrieve the new product line, using the ID we created */
    2. Productline loadedProductline = dao.findById(productlineID);
    3. /*
    4. * 2. Now let's change same value on the product line, and save the
    5. * change
    6. */
    7. loadedProductline.setTextdescription("Product line for men's shoes.");
    8. TransactionStatus status = txManager
    9. .getTransaction(new DefaultTransactionDefinition());
    10. dao.update(loadedProductline);
    11. txManager.commit(status);
    12. /*
    13. * 3. Now let's load the product line from the DB again, and make sure
    14. * its text description changed
    15. */
    16. Productline secondLoadedProductline = dao.findById(productlineID);
    17. System.out.println("*REVISED* Product Line [" + "productLine="
    18. + secondLoadedProductline.getProductline()
    19. + ", textDescription="
    20. + secondLoadedProductline.getTextdescription() + "]");

    请注意更新调用被封装在事务中,因为它必须向数据库写入一些内容,并且需要防止失败。

    在上面的第3节中,产品线在更新后立即从数据库加载,并通过打印从数据库返回的值来确认更新。

    3.4 删除实体

    删除实体几乎等同于保存和更新实体,工作被封装在另一个事务中,然后DAO被告知去做这项工作。

    1. /* 1. Now retrieve the new product line,
    2. using the ID we created */
    3. TransactionStatus status = txManager
    4. .getTransaction(new DefaultTransactionDefinition());
    5. Productline loadedProductline = dao.findById(productlineID);
    6. /* 2. Now let's delete the product line from
    7. the DB */
    8. dao.delete(loadedProductline);
    9. txManager.commit(status);
    10. /*
    11. * 3. To confirm the deletion, try and load it again and make sure it
    12. * fails
    13. */
    14. Productline deletedProductline = dao.findById(productlineID);
    15. /*
    16. * 4. We use a simple inline IF clause to test for null and print
    17. * SUCCESSFUL/FAILED
    18. */
    19. System.out.println("Productline deletion: "
    20. + (deletedProductline == null ? "SUCCESSFUL" : "FAILED"));

    与上面的“updateProductline”实现类似,您会注意到一个事务用于封装“delete”调用,然后代码尝试从DB加载实体并确认操作应该失败。

    注意:事务必须封装'findById '和'delete '方法调用的原因是因为JPA管理的对象必须是同一事务的一部分,要擦除已加载的对象,它必须处于加载它并尝试擦除它的同一个事务中。

    3.5 运行程序

    运行此命令的输出如下所示:

    如何在MyEclipse中使用JPA和Spring管理事务?

    输出

    红色文本是可以忽略的默认日志消息(如果希望控制日志记录,您可以设置自定义log4j.properties文件),在日志警告下面,您可以看到来自TopLink (JPA实现库)的两条消息,以及来自实现的另外三条消息。

    第一个消息打印出添加的新产品线信息,第二个消息更新产品线信息并打印新信息,最后一个消息从DB中删除产品线信息并打印确认消息。

    4. 启用Spring容器管理的事务

    除了用户管理的事务之外,Spring还通过@Transactional属性支持容器管理的事务。对于容器管理的事务支持,您必须在添加facet时启用它,这是您在本教程前面所做的。

    如何在MyEclipse中使用JPA和Spring管理事务?

    启用对@Transactional注释的支持

    启用此功能将向bean配置文件添加以下事务元素,您还应该添加一个JPAServiceBean,它用于使用容器管理的事务删除实体。请参阅下面的实现:

    如何在MyEclipse中使用JPA和Spring管理事务?

    注解驱动的配置元素

    JPAServiceBean实现如下所示;注意'deleteProductLine '方法上的'@Transactional '注释和没有任何用户管理的事务语句。

    1. public class JPAServiceBean
    2. { private IProductlineDAO dao; @Transactional public void deleteProductLine(String productlineID)
    3. { /* 1. Now retrieve the new product line, using the ID we created */Productline loadedProductline = dao.findById(productlineID);
    4. /* 2. Now let's delete the product line from the DB */
    5. dao.delete(loadedProductline);
    6. /*
    7. * 3. To confirm the deletion, try and load it again and make sure it * fails
    8. */
    9. Productline deletedProductline = dao.findById(productlineID);
    10. /*
    11. * 4. We use a simple inline IF clause to test for null and print
    12. * SUCCESSFUL/FAILED
    13. */
    14. System.out.println("Productline deletion: " + (deletedProductline == null ? "SUCCESSFUL" : "FAILED"));}
    15. public void setProductLineDAO(IProductlineDAO dao) { this.dao = dao; }
    16. }

    从应用程序上下文中获取JPAServiceBean实例,并按如下方式使用它:

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

  • 相关阅读:
    2023Node.js零基础教程(小白友好型),nodejs新手到高手,(二)NodeJS入门——buffer模块、计算机基础、fs模块、path模块
    反转链表问题的递归解法
    对人脸图像进行性别和年龄的判断
    06 rpm和yum
    Chrome Extensions v3 迁移清单
    数字拼图游戏代码
    也说工厂模式
    JMETER连接数据库
    [De1CTF2019]Babylfsr
    TPS65217DRSLR 电源管理IC 设计用于便携式设备
  • 原文地址:https://blog.csdn.net/AABBbaby/article/details/134030081