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&amp;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);
    }
}

 

posted @ 2022-08-27 11:11  且行且码  阅读(990)  评论(0编辑  收藏  举报