JPA 入门实战(3)--Spring Boot 中使用 JPA
本文主要介绍在 Spring Boot 中使用 JPA 的方法(暂不使用 spring-data-jpa),相关的环境及软件信息如下:Spring Boot 2.6.10、JPA 2.2、eclipselink 2.7.10。
1、原生使用
该使用方法与 Spring Boot 的关系不是很大,一般 Java 项目都可以这么使用。工程目录结构如下:
1.1、引入依赖
这里使用 eclipselink 作为 JPA 的实现框架。
<dependency> <groupId>org.eclipse.persistence</groupId> <artifactId>org.eclipse.persistence.jpa</artifactId> <version>2.7.10</version> </dependency>
其他的依赖可自行引入,如数据库驱动、lombok 等。
1.2、创建实体类
package com.abc.demojpa.entity; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import javax.persistence.*; @NoArgsConstructor @AllArgsConstructor @Data @Entity @Table(name = "a_student") public class Student { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String name; private Integer age; @Column(name = "home_address") private String homeAddress; }
1.3、编写 JPA 配置文件 (persistence.xml)
<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.2" 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"> <persistence-unit name="myUnit"> <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> <exclude-unlisted-classes>false</exclude-unlisted-classes> <properties> <property name="javax.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/> <property name="javax.persistence.jdbc.url" value="jdbc:mysql://10.49.196.10:3306/test?useUnicode=true&characterEncoding=UTF-8"/> <property name="javax.persistence.jdbc.user" value="root"/> <property name="javax.persistence.jdbc.password" value="123456"/> <property name="eclipselink.logging.level" value="INFO" /> <property name="eclipselink.ddl-generation" value="create-or-extend-tables" /> </properties> </persistence-unit> </persistence>
eclipselink 开头的配置是 eclipselink 自带的扩展配置,用于实现功能的增强;详细的扩展配置说明可参考官网说明:https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/toc.htm。
1.4、配置 EntityManager
package com.abc.demojpa.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; @Configuration public class EntityManagerConfig { @Bean public EntityManagerFactory entityManagerFactory() { return Persistence.createEntityManagerFactory("myUnit"); } @Bean public EntityManager entityManager() { return entityManagerFactory().createEntityManager(); } }
1.5、使用例子
package com.abc.demojpa.service; import com.abc.demojpa.entity.Student; import org.junit.Test; import org.junit.runner.RunWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import javax.persistence.EntityManager; @RunWith(SpringRunner.class) @SpringBootTest public class TestService { private static final Logger logger = LoggerFactory.getLogger(TestService.class); @Autowired private EntityManager entityManager; //插入实体 @Test public void persist() { entityManager.getTransaction().begin(); Student student = new Student(); student.setName("小明"); student.setAge(15); student.setHomeAddress("江苏"); Student student2 = new Student(); student2.setName("小红"); student2.setAge(18); student2.setHomeAddress("广东"); entityManager.persist(student); entityManager.persist(student2); entityManager.getTransaction().commit(); } //查询实体 @Test public void find() { Student student = entityManager.find(Student.class, 1501L); logger.info("student={}", student); } //更新实体(先查再更新) @Test public void modify() { entityManager.getTransaction().begin(); Student student = entityManager.find(Student.class, 1501L); student.setName("小明2"); entityManager.getTransaction().commit(); } //更新实体(直接根据id更新) @Test public void merge() { entityManager.getTransaction().begin(); Student student = new Student(); student.setId(1501L); student.setName("小明3"); student.setAge(16); entityManager.merge(student); entityManager.getTransaction().commit(); } //删除实体 @Test public void remove() { entityManager.getTransaction().begin(); Student student = entityManager.find(Student.class, 1501L); entityManager.remove(student); entityManager.getTransaction().commit(); } }
2、使用 Spring 提供的 JPA 辅助功能
Sping 提供了对 EntityManagerFactory 的管理,使得 JPA 和 Spring 可以作为一个整体在工作;详细可参考:https://blog.csdn.net/lijia791541916/article/details/49181603。
工程目录结构如下:
2.1、引入依赖
<dependency> <groupId>org.eclipse.persistence</groupId> <artifactId>org.eclipse.persistence.jpa</artifactId> <version>2.7.10</version> </dependency>
2.2、创建实体类
package com.abc.demojpa.entity; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import javax.persistence.*; @NoArgsConstructor @AllArgsConstructor @Data @Entity @Table(name = "a_student") public class Student { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String name; private Integer age; @Column(name = "home_address") private String homeAddress; }
2.3、编写 Spring Boot 配置文件 (application.yml)
server: port: 8080 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://10.255.1.96:3306/cqt?useUnicode=true&characterEncoding=UTF-8 username: root password: Root12#$
2.4、配置 EntityManagerFactory
package com.abc.demojpa.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter; import org.springframework.transaction.PlatformTransactionManager; import javax.persistence.EntityManagerFactory; import javax.sql.DataSource; import java.util.Properties; @Configuration public class EntityManagerFactoryConfig { @Bean public LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean(@Autowired DataSource dataSource) { LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean(); localContainerEntityManagerFactoryBean.setDataSource(dataSource); localContainerEntityManagerFactoryBean.setPersistenceUnitName("myUnit"); localContainerEntityManagerFactoryBean.setPackagesToScan("com.abc"); localContainerEntityManagerFactoryBean.setJpaVendorAdapter(new EclipseLinkJpaVendorAdapter()); Properties properties = new Properties(); properties.setProperty("eclipselink.logging.level", "INFO"); properties.setProperty("eclipselink.ddl-generation", "create-or-extend-tables"); properties.setProperty("eclipselink.weaving", "false"); localContainerEntityManagerFactoryBean.setJpaProperties(properties); return localContainerEntityManagerFactoryBean; } @Bean public PlatformTransactionManager platformTransactionManager(@Autowired EntityManagerFactory entityManagerFactory) { return new JpaTransactionManager(entityManagerFactory); } }
2.5、使用例子
package com.abc.demojpa.service; import com.abc.demojpa.entity.Student; import org.junit.Test; import org.junit.runner.RunWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.annotation.Commit; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.transaction.annotation.Transactional; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; @RunWith(SpringRunner.class) @SpringBootTest public class TestService { private static final Logger logger = LoggerFactory.getLogger(TestService.class); @PersistenceContext private EntityManager entityManager; /** * 增加数据 * Spring Boot 事务测试时默认会回滚操作避免产生测试数据,如果不需要回滚可使用 @Commit 注解 */ @Test @Transactional @Commit public void add() { Student student = new Student(); student.setName("小明"); student.setAge(15); student.setHomeAddress("江苏"); Student student2 = new Student(); student2.setName("小红"); student2.setAge(18); student2.setHomeAddress("广东"); entityManager.persist(student); entityManager.persist(student2); } //查询实体 @Test public void find() { Student student = entityManager.find(Student.class, 1L); logger.info("student={}", student); } //更新实体(先查再更新) @Test @Transactional @Commit public void modify() { Student student = entityManager.find(Student.class, 1L); student.setName("小明2"); } //更新实体(直接根据id更新) @Test @Transactional @Commit public void merge() { Student student = new Student(); student.setId(1L); student.setName("小明3"); student.setAge(16); entityManager.merge(student); } //删除实体 @Test @Transactional @Commit public void remove() { Student student = entityManager.find(Student.class, 1L); entityManager.remove(student); } }