orm jpa_Spring ORM示例– JPA,Hibernate,事务

orm jpa

Welcome to the Spring ORM Example Tutorial. Today we will look into Spring ORM example using Hibernate JPA transaction management. I will show you a very simple example of Spring standalone application with following features.

欢迎使用Spring ORM示例教程。 今天,我们将研究使用Hibernate JPA事务管理的Spring ORM示例。 我将向您展示一个具有以下功能的Spring独立应用程序的非常简单的示例。

  • Dependency Injection (@Autowired annotation)

    依赖注入(@Autowired注释)
  • JPA EntityManager (provided by Hibernate)

    JPA EntityManager(由Hibernate提供)
  • Annotated transactional methods (@Transactional annotation)

    带注释的事务方法(@Transactional注释)

Spring ORM示例 (Spring ORM Example)

I have used in-memory database for Spring ORM example, so no need for any database setup (but you can change it to any other database in the spring.xml datasource section). This is a Spring ORM standalone application to minimize all dependencies (but you can easily change it to a web project by configuration if you get familiar with spring).

我已经在Spring ORM示例中使用了内存数据库,因此不需要任何数据库设置(但是您可以在spring.xml数据源部分中将其更改为任何其他数据库)。 这是一个Spring ORM独立应用程序,用于最小化所有依赖性(但是,如果您熟悉spring,可以通过配置轻松地将其更改为Web项目)。

NOTE: For Spring AOP based Transactional (without @Transactional annotation) method resolution approach please check this tutorial: Spring ORM AOP Transaction Management.

注意 :对于基于Spring AOP的Transactional(无@Transactional批注)方法解析方法,请检查此教程: Spring ORM AOP事务管理

Below image shows our final Spring ORM example project.

下图显示了我们最终的Spring ORM示例项目。

Let’s go through each of the Spring ORM example project components one by one.

让我们一一遍历每个Spring ORM示例项目组件。

Spring ORM Maven依赖项 (Spring ORM Maven dependencies)

Below is our final pom.xml file having Spring ORM dependencies. We have used Spring 4 and Hibernate 4 in our Spring ORM example.

以下是具有Spring ORM依赖项的最终pom.xml文件。 我们在Spring ORM示例中使用了Spring 4和Hibernate 4。

<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>hu.daniel.hari.learn.spring</groupId>
	<artifactId>Tutorial-SpringORMwithTX</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>

		<!-- JPA Vendor -->
		<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>
  • We need spring-context and spring-orm as Spring dependencies.

    我们需要spring-contextspring-orm作为Spring依赖项。
  • We use hibernate-entitymanager for Hibernate as JPA implementation. hibernate-entitymanager is dependent on hibernate-core this why we don’t have to put hibernate-core in pom.xml explicitly. It’s being pulled into our project through maven transitive dependencies.

    我们将Hibernate的hibernate-entitymanager用作JPA实现。 hibernate-entitymanager依赖于hibernate-core这就是为什么我们不必将hibernate-core显式放入pom.xml的原因。 它通过Maven传递依赖项被拉入我们的项目。
  • We also need JDBC driver as dependency for database access. We are using HSQLDB that contains the JDBC driver and a working in memory database.

    我们还需要JDBC驱动程序作为数据库访问的依赖项。 我们正在使用包含JDBC驱动程序和内存数据库的HSQLDB。

Spring ORM模型类 (Spring ORM Model Class)

We can use standard JPA annotations for mapping in our model beans because Hibernate provides JPA implementation.

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

package hu.daniel.hari.learn.spring.orm.model;

import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class Product {

	@Id
	private Integer id;
	private String name;

	public Product() {
	}

	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;
	}

	@Override
	public String toString() {
		return "Product [id=" + id + ", name=" + name + "]";
	}

}

We use @Entity and @Id JPA annotations to qualify our POJO as an Entity and to define it’s primary key.

我们使用@Entity@Id JPA批注将POJO限定为实体并定义其主键。

SpringORM DAO班 (Spring ORM DAO Class)

We create a very simple DAO class that provides persist and findALL methods.

我们创建了一个非常简单的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 {

	@PersistenceContext
	private EntityManager em;

	public void persist(Product product) {
		em.persist(product);
	}

	public List<Product> findAll() {
		return em.createQuery("SELECT p FROM Product p").getResultList();
	}

}
  • @Component is Spring annotation that tell the Spring container that we can use this class through Spring IoC (Dependency Injection).

    @Component是Spring注释,它告诉Spring容器我们可以通过Spring IoC(依赖注入)使用此类。
  • We use JPA @PersistenceContext annotation that indicate dependency injection to an EntityManager. Spring injects a proper instance of EntityManager according to the spring.xml configuration.

    我们使用JPA @PersistenceContext批注来指示对EntityManager的依赖项注入。 Spring根据spring.xml配置注入适当的EntityManager实例。

SpringORM服务类别 (Spring ORM Service Class)

Our simple service class has 2 write and 1 read methods – add, addAll and listAll.

我们的简单服务类具有2个写入方法和1个读取方法-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;
import org.springframework.transaction.annotation.Transactional;

@Component
public class ProductService {

	@Autowired
	private ProductDao productDao;

	@Transactional
	public void add(Product product) {
		productDao.persist(product);
	}
	
	@Transactional
	public void addAll(Collection<Product> products) {
		for (Product product : products) {
			productDao.persist(product);
		}
	}

	@Transactional(readOnly = true)
	public List<Product> listAll() {
		return productDao.findAll();

	}

}
  • We use Spring @Autowired annotation to inject ProductDao in our service class.

    我们使用Spring @Autowired批注将ProductDao注入我们的服务类中。
  • We want to use transaction management, so methods are annotated with @Transactional Spring annotation. The listAll method only reads the database so we set the @Transactional annotation to read-only for optimisation.

    我们要使用事务管理,因此方法使用@Transactional Spring注释进行注释。 listAll方法仅读取数据库,因此我们将@Transactional批注设置为只读以进行优化。

Spring ORM示例Bean配置XML (Spring ORM Example Bean Configuration XML)

Our spring ORM example project java classes are ready, let’s look at our spring bean configuration file now.

我们的Spring ORM示例项目Java类已经准备就绪,现在让我们看一下我们的spring bean配置文件。

spring.xml

spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans" 
	xmlns:p="https://www.springframework.org/schema/p"
	xmlns:context="https://www.springframework.org/schema/context" 
	xmlns:tx="https://www.springframework.org/schema/tx" 
	xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="
		https://www.springframework.org/schema/beans
		https://www.springframework.org/schema/beans/spring-beans-3.0.xsd
		https://www.springframework.org/schema/context
		https://www.springframework.org/schema/context/spring-context-3.0.xsd
		https://www.springframework.org/schema/tx
		https://www.springframework.org/schema/tx/spring-tx.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 />

	<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>
	
	<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>

	<!-- Transactions -->
	<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
		<property name="entityManagerFactory" ref="entityManagerFactory" />
	</bean>
	<!-- enable the configuration of transactional behavior based on annotations -->
	<tx:annotation-driven transaction-manager="transactionManager" />

</beans>
  1. First we tell spring that we want to use classpath scanning for Spring components (Services, DAOs) rather than defining them one by one in spring xml. We have also enabled Spring annotation detection.

    首先,我们告诉spring我们要对Spring组件(服务,DAO)使用类路径扫描,而不是在spring xml中一个接一个地定义它们。 我们还启用了Spring注释检测。
  2. Adding the datasource, that is currently HSQLDB in-memory database.

    添加数据源,即当前的HSQLDB内存数据库。
  3. We set up a JPA EntityManagerFactory that will used by the application to obtain an EntityManager. Spring supports 3 different ways to do this, we have used LocalContainerEntityManagerFactoryBean for full JPA capabilities.

    We set LocalContainerEntityManagerFactoryBean attributes as:

    1. packagesToScan attribute that points to our model classes package.
    2. datasource defined earlier in spring configuration file.
    3. jpaVendorAdapter as Hibernate and setting some hibernate properties.

    我们设置了一个JPA EntityManagerFactory ,应用程序将使用它来获取EntityManager。 Spring支持3种不同的方法来执行此操作,我们已使用LocalContainerEntityManagerFactoryBean来实现完整的JPA功能。

    我们将LocalContainerEntityManagerFactoryBean属性设置为:

    1. 指向我们的模型类包的packagesToScan属性。
    2. 弹簧配置文件中前面定义的数据源。
    3. jpaVendorAdapter作为Hibernate并设置一些hibernate属性。
  4. We create Spring PlatformTransactionManager instance as a JpaTransactionManager. This transaction manager is appropriate for applications that use a single JPA EntityManagerFactory for transactional data access.

    我们将Spring PlatformTransactionManager实例创建为JpaTransactionManager。 该事务管理器适用于使用单个JPA EntityManagerFactory进行事务数据访问的应用程序。
  5. We enable the configuration of transactional behavior based on annotations, and we set the transactionManager we created.

    我们启用基于注释的事务行为配置,并设置我们创建的transactionManager。

Spring ORM Hibernate JPA示例测试程序 (Spring ORM Hibernate JPA Example Test Program)

Our spring ORM JPA Hibernate example project is ready, so let’s write a test program for our application.

我们的SpringORM JPA Hibernate示例项目已经准备就绪,因此让我们为我们的应用程序编写一个测试程序。

public class SpringOrmMain {
	
	public static void main(String[] args) {
		
		//Create Spring application context
		ClassPathXmlApplicationContext 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 operation
		
		productService.add(new Product(1, "Bulb"));
		productService.add(new Product(2, "Dijone mustard"));
		
		System.out.println("listAll: " + productService.listAll());
		
		//Test transaction rollback (duplicated key)
		
		try {
			productService.addAll(Arrays.asList(new Product(3, "Book"), new Product(4, "Soap"), new Product(1, "Computer")));
		} catch (DataAccessException dataAccessException) {
		}
		
		//Test element list after rollback
		System.out.println("listAll: " + productService.listAll());
		
		ctx.close();
		
	}
}

You can see how easily we can start the Spring container from a main method. We are getting our first dependency injected entry point, the service class instance. ProductDao class reference injected to the ProductService class after the spring context is initialized.

您会看到我们可以很容易地从main方法启动Spring容器。 我们正在获得第一个依赖注入的入口点,即服务类实例。 在弹簧上下文初始化之后,将ProductDao类引用注入到ProductService类。

After we got ProducService instance, we can test it’s methods, all method call will be transactional due to Spring’s proxy mechanism. We also test rollback in this example.

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

If you run above spring ORM example test program, you will get below logs.

如果您在spring ORM示例测试程序之上运行,则将获得以下日志。

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]]

Note that the second transaction is rolled back, this why product list didn’t changed.

请注意,第二笔交易已回滚,这就是为什么产品列表未更改的原因。

If you use log4j.properties file from attached source, you can see what’s going on under the hood.

如果使用附件中的log4j.properties文件,则可以查看实际情况。

References:
https://docs.spring.io/spring/docs/current/spring-framework-reference/html/orm.html

参考文献:
https://docs.spring.io/spring/docs/current/spring-framework-reference/html/orm.html

You can download the final Spring ORM JPA Hibernate Example project from below link and play around with it to learn more.

您可以从下面的链接下载最终的Spring ORM JPA Hibernate Example项目,并进行试用以了解更多信息。

翻译自: https://www.journaldev.com/7655/spring-orm-example-jpa-hibernate-transaction

orm jpa

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值