Spring ORM示例 - 带有AOP事务管理

这是一个非常简单的Spring ORM示例,向您展示如何使用Spring配置应用程序

  • 依赖注入(@Autowired annotation),
  • JPA EntityManager(由Hibernate提供),
  • 事务方法(配置AOP)。

目录[ 隐藏 ]

  • 1 AOP事务的Spring ORM示例

    • 1.1 1. Maven依赖
    • 1.2 2.模型类
    • 1.3 3. Dao类
    • 1.4 4.服务等级
    • 1.5 5. Spring配置XML
    • 1.6 6. Spring ORM示例测试类

带有AOP事务的Spring ORM示例

为了配置事务方法,我们现在不使用 @Transactional注释,因为我们现在使用面向方法(例如:我们可以说服务包中以“get”开头的所有方法都是只读事务方法)。我们使用内存数据库来简化此示例,因此无需任何数据库设置。这是一个独立的应用程序示例。

(对于@Transactional注释方法,请查看本教程:https//www.journaldev.com/7655/spring-orm-example-jpa-hibernate-transaction

项目结构:

我们逐个浏览这些文件并解释它们:

1. Maven依赖

我们将首先查看我们的pom.xml文件,了解所有必需的依赖项及其版本。我们在这个例子中使用了Spring 4和Hibernate 4。


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>hu.daniel.hari.learn.spring</groupId><artifactId>Tutorial-SpringORMwithTX-AOP</artifactId><version>0.0.1-SNAPSHOT</version><packaging>jar</packaging><properties><!-- Generic properties --><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><java.version>1.7</java.version><!-- SPRING & HIBERNATE / JPA --><spring.version>4.0.0.RELEASE</spring.version><hibernate.version>4.1.9.Final</hibernate.version></properties><dependencies><!-- LOG --><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency><!-- Spring --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-orm</artifactId><version>${spring.version}</version></dependency><!-- AspectJ (required spring-aop dependency) --><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.5</version></dependency><!-- JPA Implementation (Hibernate)--><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-core</artifactId><version>${hibernate.version}</version></dependency><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-entitymanager</artifactId><version>${hibernate.version}</version></dependency><!-- IN MEMORY Database and JDBC Driver --><dependency><groupId>hsqldb</groupId><artifactId>hsqldb</artifactId><version>1.8.0.7</version></dependency></dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.1</version><configuration><source>${java.version}</source><target>${java.version}</target></configuration></plugin></plugins></build></project>
  • 我们需要spring-contextspring-orm作为Spring依赖项。
  • spring-aop还带有spring-context作为它的依赖库,所以不需要添加它。
  • aspectjweaver是spring-aop的依赖项,但我们必须添加它,因为它没有为spring-aop明确定义。
  • 我们使用hibernate-entitymanager将Hibernate用作JPA供应商。hibernate-entitymanager依赖于hibernate-core这就是为什么我们不必将hibernate-core明确地放在pom.xml中。
  • 我们还需要一个JDBC驱动程序作为Hibernate使用的数据库访问依赖项。在这个例子中,我们使用了包含JDBC驱动程序的hsqldb,以及在本例中也使用了内存数据库。(如果要使用外部数据库,则必须将其更改为该db的JDBC驱动程序,fe:PostgreSQL或mysql-connector-java maven依赖项。)

2.模型类

我们可以使用标准JPA注释在我们的模型中进行映射,因为Hibernate提供了JPA实现。


package hu.daniel.hari.learn.spring.orm.model;import javax.persistence.Entity;
import javax.persistence.Id;@Entity
public class Product {@Idprivate Integer id;private String name;public Product() {//Default constructor needed for JPA.}public Product(Integer id, String name) {this.id = id;this.name = name;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "Product [id=" + id + ", name=" + name + "]";}
}

我们使用@Entity@IdJPA注解资格我们的POJO作为一个实体,它定义的主键。

道教班

我们创建了一个非常简单的DAO类,它具有persist和findALL方法。


package hu.daniel.hari.learn.spring.orm.dao;import hu.daniel.hari.learn.spring.orm.model.Product;import java.util.List;import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;import org.springframework.stereotype.Component;@Component
public class ProductDao {@PersistenceContextprivate EntityManager em;public void persist(Product product) {System.out.println("persist:"+product);em.persist(product);}public List<Product> findAll() {return em.createQuery("SELECT p FROM Product p").getResultList();}
}
  • @Component是Spring注释,告诉Spring容器我们可以通过Spring IoC(依赖注入)使用这个类。
  • 我们使用JPA的@PersistenceContext注释来指示对EntityManager的依赖注入。Spring根据spring.xml配置注入适当的EntityManager实例。

4.服务类

我们的简单服务类有2个write和1个read方法:add,addAll和listAll。


package hu.daniel.hari.learn.spring.orm.service;import hu.daniel.hari.learn.spring.orm.dao.ProductDao;
import hu.daniel.hari.learn.spring.orm.model.Product;import java.util.Collection;
import java.util.List;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class ProductService {@Autowiredprivate ProductDao productDao;public void add(Product product) {productDao.persist(product);}public void addAll(Collection<Product> products) {for (Product product : products) {productDao.persist(product);}}public List<Product> listAll() {return productDao.findAll();}
}

请注意

  • 方法之前没有 @Transactional注释,但我们希望这些方法是事务性的。原因是我们使用AOP方法来配置哪些方法是事务性的,将在下面的spring.xml中配置。
  • 我们使用Spring的@Autowired批注使ProductDao组件被依赖注入。

5. Spring配置XML

现在我们准备好了迷你应用程序中所需的每个工作类。让我们创建Spring的配置文件:


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.0.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><!-- Scans the classpath for annotated components that will be auto-registered as Spring beans --><context:component-scan base-package="hu.daniel.hari.learn.spring" /><!-- Activates various annotations to be detected in bean classes e.g: @Autowired --><context:annotation-config /><!-- JPA --><!-- Datasource, that is currently hsqldb (in-memory database). --><bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="driverClassName" value="org.hsqldb.jdbcDriver" /><property name="url" value="jdbc:hsqldb:mem://productDb" /><property name="username" value="sa" /><property name="password" value="" /></bean><!-- EntityManagerFactory --><bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" p:packagesToScan="hu.daniel.hari.learn.spring.orm.model" p:dataSource-ref="dataSource"><property name="jpaVendorAdapter"><bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"><property name="generateDdl" value="true" /><property name="showSql" value="true" /></bean></property></bean><!-- AOP Configuration for selecting transactional methods --><!-- the transactional advice (what 'happens'; see the <aop:advisor/> ) --><tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><!-- all methods starting with 'list' or 'get' are read-only --><tx:method name="list*" read-only="true"/><tx:method name="get*" read-only="true"/><!-- for other methods use the default transaction settings --><tx:method name="*" /></tx:attributes></tx:advice><!-- ensure that the above transactional advice runs for any executionof a method in the service package --><aop:config><aop:pointcut id="serviceMethods" expression="execution(* hu.daniel.hari.learn.spring.orm.service.*.*(..))" /><aop:advisor pointcut-ref="serviceMethods" advice-ref="txAdvice" /></aop:config><!-- TransactionManager --><bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"><property name="entityManagerFactory" ref="entityManagerFactory" /></bean></beans>
  • 首先我们告诉spring我们想要对Spring组件(服务,DAO等)使用类路径扫描,而不是在这个xml中逐个不方便地定义它们,并且我们还启用了Spring注释检测。
  • 添加数据源,即当前hsqldb(内存数据库)。
  • 我们设置了一个JPA EntityManagerFactory,它将被应用程序用来获取EntityManager。Spring支持3种不同的方法(详见下面的参考资料),我们使用LocalContainerEntityManagerFactoryBean来获得完整的JPA功能。
    我们将其属性设置为:

    • packagesToScan属性指向我们模型的包。(不需要persistence.xml)
    • 数据源(上面定义)
    • jpaVendorAdapter作为Hibernate(也设置了一些hibernate属性)
  • 我们通过以下方式配置Spring-AOP行为:我们希望服务包中的所有方法都是事务性的,对于以“get *”或“list *”开头的方法,我们希望它们是只读事务性的。这很简单。
  • 我们将Spring的PlatformTransactionManager实例创建为JpaTransactionManager。(此事务管理器适用于使用单个JPA EntityManagerFactory进行事务数据访问的应用程序。)

6. Spring ORM示例测试类

我们的设置准备就绪,所以让我们为我们的应用程序编写一个测试类。


package hu.daniel.hari.learn.spring.orm.main;import hu.daniel.hari.learn.spring.orm.model.Product;
import hu.daniel.hari.learn.spring.orm.service.ProductService;import java.util.Arrays;import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.dao.DataAccessException;/** * Simple tester for a Spring application that uses JPA * with AOP based Transactions. **/
public class SpringOrmMain {public static void main(String[] args) {//Create Spring application contextClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:/spring.xml");//Get service from context. (service's dependency (ProductDAO) is autowired in ProductService)ProductService productService = ctx.getBean(ProductService.class);//Do some data operationproductService.add(new Product(1, "Television"));productService.add(new Product(2, "Phone"));System.out.println("listAll: " + productService.listAll());//Test transaction rollback (for duplicated key)try {productService.addAll(Arrays.asList(new Product(3, "Peach"), new Product(4, "Strawberry"), new Product(1, "Melone")));} catch (DataAccessException dataAccessException) {//Do nothing here, we just test rollback}//Test element list after rollback (same two element, 3 more hasn't been added.)System.out.println("listAll: " + productService.listAll());ctx.close();}
}

您可以看到我们从main方法启动Spring容器并获取第一个依赖注入入口点(服务类实例)是多么简单。在初始化上下文后ProductDao注入类的类引用ProductService

在我们获得ProducService实例之后,我们可以测试它的方法,由于Spring的代理机制,所有方法调用都将被转换。我们还在此示例中测试回滚。

如果你跑,你得到以下日志:


Hibernate: insert into Product (name, id) values (?, ?)
Hibernate: insert into Product (name, id) values (?, ?)
Hibernate: select product0_.id as id0_, product0_.name as name0_ from Product product0_
listAll: [Product [id=1, name=Bulb], Product [id=2, name=Dijone mustard]]
Hibernate: insert into Product (name, id) values (?, ?)
Hibernate: insert into Product (name, id) values (?, ?)
Hibernate: insert into Product (name, id) values (?, ?)
Hibernate: select product0_.id as id0_, product0_.name as name0_ from Product product0_
listAll: [Product [id=1, name=Bulb], Product [id=2, name=Dijone mustard]]

请注意,第二个事务已回滚,这就是产品列表未更改的原因。

您可以看到我们制作了事务方法,而没有使用@Transactional注释逐个指定它们,因为我们在AOP方法中对其进行了配置。

如果您使用log4j.properties来自附加源的文件,您可以看到幕后发生了什么。

参考文献:
对象关系映射(ORM)数据访问
面向方面的Spring编程

(对于@Transactional注释方法,请查看本教程:
https://www.journaldev.com/7655/spring-orm-example-jpa-hibernate-transaction)

您可以从下面的链接下载最终的maven项目源,并使用它来了解更多信息。

使用Transaction AOP Project下载Spring ORM

Spring ORM示例 - 带有AOP事务管理相关推荐

  1. spring aop示例_具有AOP事务管理的Spring ORM示例

    spring aop示例 This is a very simple Spring ORM example that shows you how to configure an application ...

  2. Spring AOP事务管理(使用切面把事务管理起来)

    在<Spring Transaction 分析事务属性(事务的基本概念.配置)>基础上 1.使用基于注解的AOP事务管理  <tx:annotation-driven transac ...

  3. Spring ORM示例 - JPA,Hibernate,Transaction

    Spring ORM示例 - JPA,Hibernate,Transaction 欢迎来到Spring ORM示例教程.今天我们将使用Hibernate JPA事务管理来研究Spring ORM示例. ...

  4. 掌握基于AOP事务管理

    一.手动管理和半自动工厂模式 二.AOP事务管理 1.表达式中,第一个※是返回值所有类型,service包下一个点意思是service包下的类,两个点意思是service包下的类和其子包下的类也包含, ...

  5. spring boot配置mybatis和事务管理

    spring boot配置mybatis和事务管理 一.spring boot与mybatis的配置 1.首先,spring boot 配置mybatis需要的全部依赖如下: <!-- Spri ...

  6. 解决在Spring整合Hibernate配置tx事务管理器出现错误的问题

    解决在Spring整合Hibernate配置tx事务管理器出现错误的问题 参考文章: (1)解决在Spring整合Hibernate配置tx事务管理器出现错误的问题 (2)https://www.cn ...

  7. Spring Boot中的多事务管理

    ** 一.多数据源问题 ** 最后一个可以插入一条数据,原因是Transactoinal的事务只针对userMapper有效,因为之前的事务只给test1配置了,而test2并没有配置事务. ** 二 ...

  8. java元婴期(21)----java进阶(spring(5)---事务管理AOP事务管理(全自动)spring整合Junit)

    事务管理 事务:一组业务操作ABCD,要么全部成功,要么全部不成功. 特性:ACID 原子性:整体 一致性:完成 隔离性:并发 持久性:结果 隔离问题: 脏读:一个事务读到另一个事务没有提交的数据 不 ...

  9. Spring JDBC-混合框架的事务管理

    概述 问题 解决方案 示例Hibernate Spring JDBC 概述 Spring 抽象的 DAO 体系兼容多种数据访问技术,它们各有特色,各有千秋. Hibernate 是非常优秀的 ORM ...

最新文章

  1. Java 的toString() 和 equals()函数简单介绍
  2. 常用javascript代码
  3. 列出Sell in application所有可以传输的application object
  4. python读取大数据量xml_多快好省地使用pandas分析大型数据集
  5. iphone 如何成功的把three20成功的添加到xcode中去。
  6. ndk android studio万年坑
  7. 用python制作贺卡_Python:通过邮箱发送贺卡或明信片
  8. Zookeeper的一些概念
  9. OSB格式(REST)转化(XML到JSON,JSON到XML)
  10. 2021-01-11
  11. XRD .txt 格式转 .xrdml格式
  12. 图形图像基础 之 gif介绍
  13. 使用 Matlab 解决数学建模问题
  14. golang map的遍历
  15. android 心跳 简书,如何高效维持网络长连接:手把手教你实现 自适应的心跳保活机制...
  16. [HNOI2012]永无乡
  17. win7系统提示计算机内存不足,Win7系统下提示内存不足的原因及解决方法
  18. Windows下Firefox打开网页出现:此网址已被限制-此网址使用了一个通常用于网络浏览以外目的的端口-firefox取消端口限制方法
  19. 文件服务器资源管理器无法枚举共享路径,Windows文件共享权限如何分配?
  20. 解析美团外卖智能配送的AI技术原理(附PPT)

热门文章

  1. MySQL入门 (二) : SELECT 基础查询
  2. Prefix free:摆脱 CSS3 前缀
  3. Flexslider图片轮播、文字图片相结合滑动切换效果
  4. 二级域名和二级目录的联系与区别
  5. 聊一聊SpringCloudNetflix的五大组件(神兽)
  6. shell脚本中数组的长度表示
  7. nginx fastcgi php-fpm的关系梳理
  8. LeetCode 521. Longest Uncommon Subsequence I
  9. 高可用—Keepalived安装部署使用详解
  10. 办公自动化-python编写ppt-创建第一页-主标题与内容的编写