JPA
- 前言
- 概述
- ORM 映射元数据
- JPQL
- JPA API
- 附
- Spring Data JPA
前言
了解 JPA 框架对后续使用 Spring Boot 是有很大帮助的,下面简单介绍 JPA 框架的基础知识。
概述
JPA( Java 对象持久化 API ,Java Persistence API ),是 JDK 5.0 平台的标准 ORM(对象关系映射)规范。其核心思想是将运行期的实体对象持久化到数据库中,实现了 Java 对象和数据库表之间的映射关系,使得 Java 开发者能够以面向对象的方式来操作数据库。其主要目标是为 Java 开发者提供一种简单、标准的方式来管理数据库操作,同时避免了手动编写 JDBC 代码和 SQL 语句的繁琐工作,简化了 Java 数据库开发,提高了开发效率和代码质量。通过 JPA ,开发者可以使用高级的 Java 对象来代表数据库中的记录,并使用 JPA 提供的 API 来执行 CRUD(创建、读取、更新、删除)操作。
JPA 框架主要为三个方面的技术:
- ORM 映射元数据:JPA 支持使用 XML 或 JDK 5.0 注解来描述 Java 对象与数据库表之间的映射关系。这些元数据定义了如何将 Java 对象(实体)映射到关系型数据库中的表,以及如何将表中的记录映射回 Java 对象
- JPQL:JPA 提供了一种面向对象的查询语言( JPQL ),使开发者可以通过面向对象的方式来查询数据,避免了程序的 SQL 语句紧密耦合
- JPA API:JPA API 用于操作实体对象,执行 CRUD(创建、读取、更新、删除)操作。开发者可以使用这个 API 进行数据库操作,而无需关心底层的 JDBC 和 SQL 代码
另外,JPA 还提供了事务管理、缓存等高级功能,以支持复杂的应用程序需求。
注:
JPA 本身并不是一个完整的 ORM 框架,而是一个规范。具体的 JPA 实现由不同的 ORM 框架提供,如 Hibernate 、EclipseLink 等。这些实现框架遵循 JPA 规范,为开发者提供了具体的 JPA API 实现和额外的功能。
ORM 映射元数据
在 JPA 中,ORM(对象关系映射)映射元数据是一个核心概念。这通常是通过注解( Annotations )和 XML 映射文件的方式来实现。注解通常更简洁,并且与代码紧密集成;而 XML 映射文件则提供了更丰富的配置选项和更好的可读性。在实际应用中,开发者可以根据个人偏好和项目需求来选择其中一种方式来描述 ORM 映射元数据。
简单示例:
1.注解( Annotations )方式
JPA 提供的注解可以直接应用于 Java 类的字段、方法或类级别上。如注解 @Entity 、@Table 、@Column 、@Id 、@GeneratedValue 、@Access 等,这些注解允许开发者直接在 Java 代码中指定实体类与数据库表、实体类字段与数据库列之间的映射关系,而无需编写额外的配置文件。
- @Entity:用于标识一个 Java 类作为 JPA 实体,即该类将被映射到数据库中的一个表。一个实体类通常代表数据库中的一个表
- @Table:用于指定实体类映射的数据库表的信息。如果不使用 @Table 注解,则默认使用实体类的名称作为表名,并且表名会转换为小写(根据 JPA 提供商的实现和配置可能会有所不同)。@Table 注解允许明确指定表名、目录、模式等
- @Column:用于指定实体类属性映射到数据库表中的列的信息。其可以应用于实体类的字段或 getter 方法上。@Column 注解允许指定列名、数据类型、是否可空等
- @Id:用于标识实体类的主键字段或属性。一个实体类必须有一个或多个 @Id 注解的字段或属性,这些字段或属性将映射到数据库表的主键列
- @GeneratedValue:用于指定主键的生成策略。如是否由数据库自动生成还是由应用程序在插入前指定。常见的策略包括 GenerationType.IDENTITY(数据库自增)、GenerationType.SEQUENCE(使用序列)、GenerationType.TABLE(使用 JPA 提供的表来生成主键值)等
- @Access:用于指定访问类型,即 JPA 如何访问实体类的字段或属性。默认情况下,JPA 使用字段访问(即直接访问类的字段),但也可以通过 @Access( AccessType.PROPERTY ) 指定使用属性访问(即通过 getter 和 setter 方法访问)
//@Entity 注解表示 User 类是一个实体类
//@Table 注解定义了实体类映射到哪个数据库表
//@Id 和 @GeneratedValue 注解则标识了主键生成策略
//@Column 注解指定了 name 字段映射到数据库表中的列名为 name
package com.example;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Column;
// 用户实体类,表示数据库中的用户
@Entity
@Table(name = "users")
public class User {
// 用户的唯一标识符
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) //自增
@Column(name = "id")
private Long id;
// 用户的名字
@Column(name = "name")
private String name;
// 构造函数
public User() {
// JPA所需的默认构造函数
}
// 获取 id 的方法
public Long getId() {
return id;
}
// 设置 id 的方法
public void setId(Long id) {
this.id = id;
}
// 获取 name 的方法
public String getName() {
return name;
}
// 设置 name 的方法
public void setName(String name) {
this.name = name;
}
// 重写 toString 方法,以便更好地调试
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
// 重写 equals 和 hashCode 方法,以便正确比较 User 对象
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return id != null ? id.equals(user.id) : user.id == null;
}
@Override
public int hashCode() {
return id != null ? id.hashCode() : 0;
}
}
2.XML 映射文件方式
JPA 也支持使用 XML 映射文件来描述实体类与数据库表之间的映射关系。这些 XML 文件放置在类路径下的 META-INF 目录中。XML 映射文件提供了更灵活和详细的配置选项,特别是对于复杂的映射场景。
<entity class="com.example.User">
<!-- 指定实体类映射的数据库表名 -->
<table name="users"/>
<!-- 定义主键映射 -->
<id name="id" type="java.lang.Long">
<!-- 指定主键生成策略为自增 -->
<generated-value strategy="IDENTITY"/>
<!-- 指定实体类属性映射到数据库表的列名 -->
<column name="id"/>
</id>
<!-- 定义非主键字段映射 -->
<basic name="name" type="java.lang.String">
<!-- 指定实体类属性映射到数据库表的列名 -->
<column name="name"/>
</basic>
</entity>
JPQL
JPQL(Java Persistence Query Language),是一种面向对象的查询语言,其允许开发人员使用实体类和属性来编写查询,而不是直接使用 SQL 语句。这种抽象方式使得应用程序的代码更加简洁、可维护,并且与数据库的具体实现解耦。使用 JPQL ,开发者可以编写类型安全的查询,这些查询在编译时进行检查,从而减少了运行时错误的可能性。JPQL 还支持各种查询操作,如选择、过滤、排序、分组和连接等,这些操作都是使用实体类和属性来完成的。
简单示例:
// 假设有一个名为 User 的实体类,并且已经配置了 JPA
EntityManager entityManager = entityManagerFactory.createEntityManager();
// 开启事务
entityManager.getTransaction().begin();
// 创建 JPQL 查询
String jpql = "SELECT u FROM User u WHERE u.name = :name";
TypedQuery<User> query = entityManager.createQuery(jpql, User.class);
// 设置查询参数
query.setParameter("name", "John Doe");
// 执行查询并获取结果
List<User> users = query.getResultList();
// 处理查询结果
for (User user : users) {
System.out.println("Found user: " + user);
}
// 提交事务
entityManager.getTransaction().commit();
// 关闭 EntityManager
entityManager.close();
注:
示例中使用了 JPQL 查询语句来选择名为 “John Doe” 的用户。但没有直接编写 SQL 语句,而是使用了实体类 User 和实体属性 name 来构建查询。这种方式使代码更加面向对象,并且更加容易理解和维护。
JPA API
JPA API 的具体用法主要涉及以下方面:
实体定义
- 使用
@Entity
注解来标记一个 Java 类作为实体类- 使用
@Table
注解来指定实体类映射的数据库表- 使用
@Column
注解来指定实体类属性映射的数据库列- 使用
@Id
注解来标记实体类的主键属性配置持久化单元
- 在
persistence.xml
配置文件中定义持久化单元,包括指定实体类、数据源、事务管理器等创建 EntityManager
- 通过
EntityManagerFactory
来创建EntityManager
实例。EntityManager
是 JPA 的核心接口,用于执行数据库操作执行 CRUD 操作
- 使用
EntityManager
的persist()
方法将实体对象保存到数据库中- 使用
EntityManager
的find()
、getReference()
等方法从数据库中查询实体对象- 使用
EntityManager
的merge()
方法将实体对象合并到持久化上下文中,实现更新操作- 使用
EntityManager
的remove()
方法从数据库中删除实体对象管理事务
- 使用
EntityManager
的事务管理功能来执行事务操作。可以通过getTransaction()
方法获取EntityTransaction
实例,然后调用begin()
、commit()
、rollback()
等方法来管理事务查询操作
- 使用 JPQL 编写查询语句,通过
EntityManager
的createQuery()
方法创建查询对象,然后执行查询并获取结果缓存和性能优化
- JPA 提供了内置的缓存机制,可以通过配置缓存属性来优化性能
- 使用批量操作、延迟加载等优化手段来进一步提高数据库访问性能
关闭资源
- 在使用完
EntityManager
后,需要调用其close()
方法来关闭,释放相关资源。同时,也需要关闭EntityManagerFactory
以上是 JPA API 的基本用法,实际上 JPA 还提供了更多高级功能和配置选项,如实体监听器、实体图、自定义查询等。可以根据自己的需求深入学习 JPA API ,并灵活运用到实际项目中。
简单示例:
首先,定义 User 实体类,并且这个类将映射到数据库中的一个表
import javax.persistence.*;
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "name")
private String name;
@Column(name = "email")
private String email;
// 省略构造函数、getter和setter方法
// ...
}
接着,在 persistence.xml 文件中配置 JPA 的持久化单元
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd"
version="2.2">
<persistence-unit name="my-persistence-unit" transaction-type="RESOURCE_LOCAL">
<class>com.example.User</class>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/mydatabase"/>
<property name="javax.persistence.jdbc.user" value="username"/>
<property name="javax.persistence.jdbc.password" value="password"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/>
<!-- 其他配置属性 -->
</properties>
</persistence-unit>
</persistence>
最后,编写一个简单的 JPA 实用类来执行 CRUD 操作
import javax.persistence.*;
import java.util.List;
public class JpaUtil {
private static final String PERSISTENCE_UNIT_NAME = "my-persistence-unit";
public static void main(String[] args) {
// 创建 EntityManagerFactory
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
// 创建 EntityManager
EntityManager entityManager = entityManagerFactory.createEntityManager();
try {
// 开启事务
entityManager.getTransaction().begin();
// 创建新用户
User newUser = new User();
newUser.setName("John Doe");
newUser.setEmail("john.doe@example.com");
entityManager.persist(newUser);
// 读取用户
String jpqlSelect = "SELECT u FROM User u WHERE u.name = :name";
TypedQuery<User> selectQuery = entityManager.createQuery(jpqlSelect, User.class);
selectQuery.setParameter("name", "John Doe");
List<User> users = selectQuery.getResultList();
for (User user : users) {
System.out.println("Found user: " + user);
}
// 更新用户
User userToUpdate = users.get(0);
userToUpdate.setEmail("john.doe@updated.com");
// 删除用户
User userToDelete = users.get(1);
entityManager.remove(userToDelete);
// 提交事务
entityManager.getTransaction().commit();
} catch (Exception e) {
// 处理异常
if (entityManager.getTransaction().isActive()) {
entityManager.getTransaction().rollback();
}
e.printStackTrace();
} finally {
// 关闭 EntityManager 和 EntityManagerFactory
if (entityManager.isOpen()) {
entityManager.close();
}
if (entityManagerFactory.isOpen()) {
entityManagerFactory.close();
}
}
}
}
注:
在实际的应用程序中,可能会使用 Spring 等框架来管理事务和 EntityManager 的生命周期,而不是手动创建和关闭。此外,异常处理也会更加复杂。
附
Spring Data JPA
Spring Data ,是 Spring 框架的一个子项目,是一个用于简化数据库访问,并支持云服务的开源框架。其支持多种数据存储技术,包括 JDBC 、JPA 、MongoDB 、 Neo4j 、Redis 和 Hbase 等。Spring Data 通过提供基于 CRUD 操作、查询方法、排序和分页方法等层面的统一接口(如 CrudRepository 和 PagingAndSortingRepository ),来简化对数据持久化层的访问。同时,Spring Data 还通过其 Repository 抽象来减少数据访问层的开发量。这个抽象允许开发者定义接口,而不需要实现,在 Spring Data 运行时会为这些接口生成实现。这极大地简化了数据访问层的开发,提高了开发效率。另外,Spring Data 包含多个子项目(如 Commons 、JPA 、Hadoop 等),每个子项目都针对特定的数据存储技术。这些子项目通过与各种公司和开发者的合作进行开发,以确保其能够满足广泛的需求。
Spring Data JPA ,是 Spring 框架基于 JPA 规范封装的一套 JPA 应用框架,其提供了更加简洁、易用的数据库访问和操作方式,使得开发者能够更加方便地使用 JPA 进行数据库开发。
Spring Data JPA 主要特点:
- Repository 抽象:Spring Data JPA 提供的 Repository 接口,是用于访问数据的通用接口。通过继承或实现这个接口,开发者可以定义数据访问方法,而无需编写具体的实现代码。Spring Data JPA 会在运行时为这些方法生成实现,大大简化了数据访问层的开发
- 自定义查询:Spring Data JPA 支持使用 JPQL 或原生 SQL 来定义自定义查询。开发者可以通过在 Repository 接口中定义方法,并使用特定的命名约定(如 findBy 、readBy 、getBy 等),来使 Spring Data JPA 自动生成相应的查询
- 分页和排序:Spring Data JPA 内置了对分页和排序的支持。开发者可以通过在 Repository 接口中定义方法,并使用 Pageable 参数,来实现数据的分页和排序。
- 事务管理:Spring Data JPA 集成了 Spring 的事务管理功能,使得开发者可以轻松地管理数据库事务
- 审计和日志:Spring Data JPA 还支持审计和日志功能,可以帮助开发者跟踪数据的修改历史和操作日志
- 集成 Spring Boot:Spring Data JPA 与 Spring Boot 框架完美集成,使得开发者可以通过简单的配置和注解,快速搭建起一个功能强大的数据访问层
简单示例:
首先,创建一个 Maven 工程( Java 项目)后,在 pom.xml 中添加依赖
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.25</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.3.25</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-orm -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>5.3.25</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-nop -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-nop</artifactId>
<version>2.0.6</version>
<type>jar</type>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.20.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.mchange/mchange-commons-java -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>mchange-commons-java</artifactId>
<version>0.2.20</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.25</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-entitymanager -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>5.6.15.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-ehcache -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-ehcache</artifactId>
<version>5.6.15.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.data/spring-data-jpa -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>2.7.8</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>compile</scope>
</dependency>
</dependencies>
接着,在 resources 目录下分别创建 jdbc.properties 和 log4j.properties,并且进行相关配置
jdbc.driverClass=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/springdatajpademo?useSSL=false&serverTimezone=UTC
jdbc.user=root
jdbc.password=0123
acquireIncrement=5
initialPoolSize=10
minPoolSize=5
maxPoolSize=100
maxStatements=2
maxStatementsPerConnection=5
#日志级别,分为八个级别( Off-关闭日志记录 > Fatal-严重错误 > Error-错误 > Warn-警告 > Info-运行信息 > Debug-调试 > Trace-低级信息 > All-所有日志记录)
#日志级别越高,过滤的信息越多
#配置根节点
log4j.rootLogger=Debug,stdout,D
#配置控制台输出
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.Threshold=INFO
##输出格式(%d %p [%1] %m %n——日期时间 类 路径 信息 换行)
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%l] %m %n
#配置文件输出
log4j.appender.D=org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.Append=true
log4j.appender.D.File=./log4j.log
log4j.appender.D.Threshold=Debug
#输出格式
log4j.appender.D.layout=org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern=%d %p [%l] %m %n
同时,在 resources 目录下创建 spring.xml ,分别进行 spring 配置、spring 与 jpa 整合配置、spring data jpa 配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
<!-- spring.xml -->
<!-- 扫描 SpringDataJPADemo 包 -->
<context:component-scan base-package="cn.edu.SpringDataJPADemo" />
<!-- 在 Bean 的外部属性文件的使用中有所提及 -->
<!-- 使用context命名空间,通过 location 属性指定 properties 文件位置 -->
<context:property-placeholder location="classpath:jdbc.properties" />
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!-- 连接 MySQL 数据库的基本信息的配置 -->
<!-- 驱动程序类名:com.mysql.jdbc.Driver -->
<property name="driverClass" value="${jdbc.driverClass}" />
<!-- JDBC URL:jdbc:mysql://<host>:<port>/<database_name> -->
<property name="jdbcUrl" value="${jdbc.url}" />
<!-- 数据库用户名 -->
<property name="user" value="${jdbc.user}" />
<!-- 数据库用户密码 -->
<property name="password" value="${jdbc.password}" />
<!-- 若数据库中的连接数量不足时,向数据库申请的连接数量 -->
<property name="acquireIncrement" value="${acquireIncrement}" />
<!-- 初始化数据库连接池时连接的数量 -->
<property name="initialPoolSize" value="${initialPoolSize}" />
<!-- 数据库连接池最小的数据库连接数 -->
<property name="minPoolSize" value="${minPoolSize}" />
<!-- 数据库连接池最大的数据库连接数 -->
<property name="maxPoolSize" value="${maxPoolSize}" />
<!-- C3P0 数据库连接池可以维护的 Statement 数量 -->
<property name="maxStatements" value="${maxStatements}" />
<!-- 每个连接同时可以使用 Statement 的数量 -->
<property name="maxStatementsPerConnection" value="${maxStatementsPerConnection}" />
</bean>
<!-- 整合 JPA 的配置 -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- JPA 实现产品 -->
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<!-- 实体类所在的包 -->
<property name="packagesToScan" value="cn.edu.SpringDataJPADemo.model" />
<!-- JPA 实现产品的基本属性 -->
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.enable_lazy_load_no_trans">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
<!-- 配置 JPA 事务 -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" >
<!-- 配置 dataSource -->
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<!-- 配置事务属性 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager" >
<tx:attributes>
<tx:method name="get*" read-only="true"/>
<tx:method name="load*" read-only="true"/>
<tx:method name="find*" read-only="true"/>
<tx:method name="read*" read-only="true"/>
<tx:method name="select*" read-only="true"/>
<tx:method name="*" read-only="false"/>
</tx:attributes>
</tx:advice>
<!-- 配置事务切入点 -->
<aop:config>
<aop:pointcut id="txPointcut" expression="execution(* cn.edu.ssmdemo.service.*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut" />
</aop:config>
<!-- 配置 Spring Data JPA -->
<!-- 将包里的接口自动创建实现类,并把这些实现类放在 Spring IoC 容器中,而在其他层便可以使用 Spring 注解注入对象 -->
<jpa:repositories base-package="cn.edu.SpringDataJPADemo.dao" entity-manager-factory-ref="entityManagerFactory"></jpa:repositories>
</beans>
然后,在 MySQL 中创建一个名为 springdatajpademo 的数据库(后面数据表会自动生成)
随之,创建一个 User 实体类和声明一个持久层接口 UserRepository(继承 Repository ,在接口中声明所需方法,而无需去实现)
package cn.edu.SpringDataJPADemo.model;
import javax.persistence.*;
import java.util.Date;
@Entity
@Table(name = "user") // 自动生成数据表
public class User {
private int id;
private String name;
private String password;
private Date regDate;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) // 自增
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Column(name = "reg_date") // 设置数据表的字段名
public Date getRegDate() {
return regDate;
}
public void setRegDate(Date regDate) {
this.regDate = regDate;
}
public User() {
super();
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", password='" + password + '\'' +
", regDate=" + regDate +
'}';
}
}
package cn.edu.SpringDataJPADemo.dao;
import cn.edu.SpringDataJPADemo.model.User;
import org.springframework.data.repository.Repository;
public interface UserRepository extends Repository<User,Integer> {
public User getById(int id);
}
最后,创建 UserRepositoryTest 测试类
package cn.edu.SpringDataJPADemo.test;
import cn.edu.SpringDataJPADemo.dao.UserRepository;
import cn.edu.SpringDataJPADemo.model.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class UserRepositoryTest {
@Test
public void test(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
UserRepository userRepository = applicationContext.getBean(UserRepository.class);
// 运行后,数据表自动生成,自行插入一条信息测试
User user = userRepository.getById(1);
System.out.println(user);
}
}
结果如图: