flea-db使用之JPA接入

简介: 【4月更文挑战第4天】本篇 Huazie 介绍 Flea 框架下的 flea-db模块中如何接入JPA

jpa.jpeg

引言

本节内容需要了解JPA封装内容,请参见笔者上篇博文《JPA封装介绍》。

1. 准备工作

为了演示JPA接入,需要先准备如下:

  • MySQL 数据库 (客户端可以使用 navicat for mysql)
  • 新建测试数据库 fleajpatest
    image.png

  • 新建测试表 student

    image.png

    建表语句如下:

      DROP TABLE IF EXISTS `student`;
      CREATE TABLE `student` (
        `stu_id` int(10) NOT NULL AUTO_INCREMENT COMMENT '学生编号',
        `stu_name` varchar(255) NOT NULL COMMENT '学生姓名',
        `stu_age` tinyint(2) NOT NULL COMMENT '学生年龄',
        `stu_sex` tinyint(1) NOT NULL COMMENT '学生性别(1:男 2:女)',
        `stu_state` tinyint(2) NOT NULL COMMENT '学生状态(0:删除 1:在用)',
        PRIMARY KEY (`stu_id`)
      ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
    
  • 依赖
    MySQL 的 JDBC 驱动 mysql-connector-java-5.1.25.jar

    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.25</version>
    </dependency>
    

    FLEA DB ECLIPSELINK【这里为 flea-framework 项目下的包,目前版本 2.0.0,暂未发布】

    <dependency>
        <groupId>com.huazie.fleaframework</groupId>
        <artifactId>flea-db-eclipselink</artifactId>
        <version>2.0.0</version>
    </dependency>
    

2. 接入讲解

2.1 实体类

新建如下学生表对应的实体类 Student,对应测试表 student。

@Entity
@Table(name = "student")
public class Student implements FleaEntity {
   

    private static final long serialVersionUID = 1267943552214677159L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY, generator = "STUDENT_SEQ")
    @SequenceGenerator(name = "STUDENT_SEQ")
    @Column(name = "stu_id", unique = true, nullable = false)
    private Long stuId;

    @Column(name = "stu_name", nullable = false)
    private String stuName;

    @Column(name = "stu_age", nullable = false)
    private Integer stuAge; 

    @Column(name = "stu_sex", nullable = false)
    private Integer stuSex;

    @Column(name = "stu_state", nullable = false)
    private Integer stuState;

    // ... 省略get和set方法

    @Override
    public String toString() {
   
        return ToStringBuilder.reflectionToString(this);
    }
}
  • Long stuId : 学生编号【主键】。在笔者的《JPA主键生成策略介绍》 中,介绍了 GenerationType.IDENTITY【适用于支持 主键自增长 的数据库系统,比如 MySQL】,详细内容可自行查看。
  • String stuName : 学生姓名【非空】
  • Integer stuAge : 学生年龄【非空】
  • Integer stuSex : 学生性别(1:男 2:女)【非空】
  • Integer stuState : 学生状态(0:删除 1:在用)【非空】

2.2 持久化单元DAO层实现

上篇博文说到,增加一个持久化单元配置,便需要增加一个持久化单元 DAO 层实现。针对本次演示新增持久化单元 fleajpa,持久化配置文件 fleajpa-persistence.xml, Spring 配置中新增数据库事务管理者配置,相关内容可参考上一篇博文。下面贴出本次演示的持久化单元 DAO 层实现代码:

FleaJpa数据源DAO层父类

public class FleaJpaDAOImpl<T> extends AbstractFleaJPADAOImpl<T> {
   
    @PersistenceContext(unitName="fleajpa")
    protected EntityManager entityManager;

    @Override
    @Transactional("fleaJpaTransactionManager")
    public boolean remove(long entityId) throws Exception {
   
        return super.remove(entityId);
    }

    // ...其他实现省略

    @Override
    protected EntityManager getEntityManager() {
   
        return entityManager;
    }

}

我们来看上面两个注解,分别是:

  • @PersistenceContext(unitName="fleajpa") :持久化上下文注解,其值为持久化单元 unitName ,在持久化配置文件中定义,spring 配置中 JPA 实体管理器工厂初始化该参数。
  • @Transactional("fleaJpaTransactionManager") :事务注解,其值为持久化事务管理器, 在 spring 配置文件中定义。

2.3 配置介绍

详细配置信息,可以参考笔者上篇博文,这里不再赘述。
涉及文件 fleajpa-persistence.xml 和 applicationContext.xml,文章最后会给出示例工程,可自行查看。

2.4 学生DAO层接口

IStudentDAO 继承了抽象 Flea JPA DAO 层接口,并定义了两个方法,分别获取学生信息列表(分页)和学生总数。

学生DAO层接口

public interface IStudentDAO extends IAbstractFleaJPADAO<Student> {
   
    List<Student> getStudentList(String name, Integer sex, Integer minAge, Integer maxAge, int pageNum, int pageCount) throws DaoException;

    int getStudentCount(String name, Integer sex, Integer minAge, Integer maxAge) throws DaoException;

}
  • getStudentList(String name, Integer sex, Integer minAge, Integer maxAge, int pageNum, int pageCount) :获取学生信息列表 (分页),其中参数如下:
    • name : 学生姓名,可以模糊查询
    • sex : 性别
    • minAge : 最小年龄
    • maxAge : 最大年龄
    • pageNum : 查询页
    • pageCount : 每页总数
  • getStudentCount(String name, Integer sex, Integer minAge, Integer maxAge) :获取学生总数
    • name : 学生姓名,可以模糊查询
    • sex : 性别
    • minAge : 最小年龄
    • maxAge : 最大年龄

2.5 学生DAO层实现

StudentDAOImpl 是学生信息的数据操作层实现,继承持久化单元DAO层实现类,并实现了上述学生DAO层接口自定义的两个方法。 具体如何使用 FleaJPAQuery 可以参见下面代码 :

学生DAO层实现类

@Repository("studentDAO")
public class StudentDAOImpl extends FleaJpaDAOImpl<Student> implements IStudentDAO {
   

    @Override
    @SuppressWarnings(value = "unchecked")
    public List<Student> getStudentList(String name, Integer sex, Integer minAge, Integer maxAge, int pageNum, int pageCount) throws DaoException {
   
        FleaJPAQuery query = initQuery(name, sex, minAge, maxAge, null);
        List<Student> studentList;
        if (pageNum > 0 && pageCount > 0) {
   
            // 分页查询
            studentList = query.getResultList4Page(pageNum, pageCount);
        } else {
   
            // 全量查询
            studentList = query.getResultList();
        }
        return studentList;
    }

    @Override
    @SuppressWarnings(value = "unchecked")
    public long getStudentCount(String name, Integer sex, Integer minAge, Integer maxAge) throws DaoException {
   
        Object result = initQuery(name, sex, minAge, maxAge, Long.class).count().getSingleResult();
        return Long.parseLong(StringUtils.valueOf(result));
    }

    private FleaJPAQuery initQuery(String name, Integer sex, Integer minAge, Integer maxAge, Class<?> result) throws DaoException{
   
        return getQuery(result)
                .like("stuName", name)
                .equal("stuSex", sex)
                .ge("stuAge", minAge)
                .le("stuAge", maxAge);
    }
}

上述代码,我们需要重点关注 initQuery 私有方法,它实际上用于返回一个已经组装好查询条件的 FleaJPAQuery 对象:

  • getQuery(result) :在《flea-db使用之JPA封装介绍》 中的抽象 Flea JPA DAO 层实现可以看到,通过 Flea JPA 查询对象池来获取 FleaJPAQuery。
  • like("stuName", name) :根据姓名模糊查询, attrName 为 实体类对应的成员变量名,并非表字段名
  • equal("stuSex", sex) :查询性别(等于)
  • ge("stuAge", minAge) :查询年龄范围 (大于等于)
  • le("stuAge", maxAge) :查询年龄范围 (小于等于)

另外,我们看到 学生DAO层实现类 的上面还有一个注解:

  • @Repository("studentDAO") :在 Spring 框架中,它是用来标注数据访问层(DAO层)的类。Spring 会将 StudentDAOImpl 实例化为一个名为 studentDAO 的Bean;然后,在其他Bean 中通过@Autowired 或者 @Resource 注解来注入这个 Bean。

2.6 学生SV层接口

IStudentSV 继承抽象Flea JPA SV层接口,并定义两个方法,分别获取学生信息列表(分页)和学生总数。

学生SV层接口


public interface IStudentSV extends IAbstractFleaJPASV<Student> {
   
    List<Student> getStudentList(String name, Integer sex, Integer minAge, Integer maxAge, int pageNum, int pageCount) throws DaoException;

    long getStudentCount(String name, Integer sex, Integer minAge, Integer maxAge) throws DaoException;
}

2.7 学生SV层实现

StudentSVImpl 继承抽象Flea JPA SV层实现类,并实现了上述学生SV层接口的两个自定义方法。具体实现参见如下代码:

学生SV层实现类

@Service("studentSV")
public class StudentSVImpl extends AbstractFleaJPASVImpl<Student> implements IStudentSV {
   
    // 注入学生DAO层实现类
    @Autowired
    @Qualifier("studentDAO") 
    private IStudentDAO studentDao; 

    @Override
    public List<Student> getStudentList(String name, Integer sex, Integer minAge, Integer maxAge, int pageNum, int pageCount) throws DaoException {
   
        return studentDao.getStudentList(name, sex, minAge, maxAge, pageNum, pageCount);
    }

    @Override
    public long getStudentCount(String name, Integer sex, Integer minAge, Integer maxAge) throws DaoException {
   
        return studentDao.getStudentCount(name, sex, minAge, maxAge);
    }

    @Override
    protected IAbstractFleaJPADAO<Student> getDAO() {
   
        return studentDao;
    }
}

上述逻辑不复杂,学生SV层实现类中的两个方法均调用 IStudentDAO 接口来查询数据库。

上述代码需要关注三个注解 和 一个方法:

  • @Service("studentSV") :在 Spring 框架中,它通常用于将一个服务层的类标记为 Spring 管理的 Bean。studentSV 是这个 Bean 的名称,可以在其他地方通过这个名称来获取这个 Bean 的实例。当 Spring 容器启动并扫描到带有 @Service 注解的类时,它会创建这个类的实例,并将其注册到Spring应用程序上下文中,使得这个 Bean 可以被依赖注入(DI)到其他组件中。
  • @Autowired :在 Spring 框架中,它用于自动装配 Bean。
  • @Qualifier("studentDAO") :它通常与 @Autowired 一起使用,用于指定 @Autowired 应该注入的特定 Bean。这里就指定了一个名为 studentDAO 的 Bean。如果你不使用 @Qualifier 注解,而是仅仅依赖 @Autowired 来注入 Bean,那么在存在多个相同类型 Bean 的情况下,Spring 容器将无法确定应该注入哪一个,从而导致 NoUniqueBeanDefinitionException 异常。
  • getDAO() :在《flea-db使用之JPA封装介绍》 中的抽象Flea JPA SV层实现,可以看到 getDAO() 用于通过的一些增删改查操作,实际的实现需要子类来返回对应的 DAO层 实现。

2.8 JPA接入自测

首先添加自测类,并注入学生服务类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
   "classpath:applicationContext.xml"})
public class StudentTest {
   

    private static final Logger LOGGER = FleaLoggerProxy.getProxyInstance(StudentTest.class);

    @Resource(name = "studentSV")
    private IStudentSV studentSV;

    // 自测代码详见下面

}

2.8.1 新增学生信息

    @Test
    public void testInsertStudent() {
   
        try {
   
            Student student = new Student();
            student.setStuName("张三");
            student.setStuAge(18);
            student.setStuSex(1);
            student.setStuState(1);
            studentSV.save(student);

            student = new Student();
            student.setStuName("李四");
            student.setStuAge(19);
            student.setStuSex(1);
            student.setStuState(1);
            studentSV.save(student);

            student = new Student();
            student.setStuName("王二麻子");
            student.setStuAge(20);
            student.setStuSex(1);
            student.setStuState(1);
            studentSV.save(student);

        } catch (Exception e) {
   
            LOGGER.error("Exception : ", e);
        }
    }

执行结果:

image.png

2.8.2 更新学生信息

    @Test
    public void testStudentUpdate() {
   
        try {
   
            Student student = studentSV.query(3L);
            LOGGER.debug("Before : {}", student);
            student.setStuName("王三麻子");
            student.setStuAge(19);
            studentSV.update(student);
            student = studentSV.query(3L);
            LOGGER.debug("After : {}", student);
        } catch (Exception e) {
   
            LOGGER.error("Exception : ", e);
        }
    }

上述演示代码逻辑:

  • 首先根据指定主键,调用 query 方法查询学生信息,并打印 Before :XXX;
  • 然后调用 update 方法更新该学生信息;
  • 最后再根据指定主键,调用 query 方法查询学生信息,并打印After : XXX。

运行结果:

image.png

2.8.3 删除学生信息

    @Test
    public void testStudentDelete() {
   
        try {
   
            Student student = studentSV.query(3L);
            LOGGER.debug("Before : {}", student);
            // 
            studentSV.remove(3L);
            // 最后再根据主键查询学生信息
            student = studentSV.query(3L);
            LOGGER.debug("After : {}", student);
        } catch (Exception e) {
   
            LOGGER.error("Exception : ", e);
        }
    }

上述演示代码逻辑:

  • 首先根据指定主键,调用 query 方法查询学生信息,并打印 Before :XXX;
  • 然后调用 remove 方法删除指定主键的学生信息(里面会先去将学生实体信息查出来,然后再删除);
  • 最后再根据指定主键,调用 query 方法查询学生信息,并打印After : XXX.

运行结果:

image.png

2.8.4 查询学生信息(按条件分页查询)

表里自行再插入些数据,用于测试查询,查询结果因各自表数据而异;

目前我表中数据如下:

image.png

      @Test
    public void testStudentQueryPage() {
   
        try {
   

            IStudentSV studentSV = (IStudentSV) applicationContext.getBean("studentSV");
            List<Student> studentList = studentSV.getStudentList("张三", 1, 18, 20, 1, 5);
            LOGGER.debug("Student List = {}", studentList);
        } catch (Exception e) {
   
            LOGGER.error("Exception : ", e);
        }
    }

运行结果:

image.png

2.8.5 查询学生总数(按条件查询)

    @Test
    public void testStudentQueryCount() {
   
        try {
   
            IStudentSV studentSV = (IStudentSV) applicationContext.getBean("studentSV");
            long count = studentSV.getStudentCount("张三", 1, 18, 20);
            LOGGER.debug("Student Count = {}", count);
        } catch (Exception e) {
   
            LOGGER.error("Exception : ", e);
        }
    }

运行结果:

image.png

总结

看到这里,我们的 JPA接入 工作已经成功完成,本篇演示示例可以移步到 GitHub 查看 flea-jpa-test。

在 JPA 封装介绍博文中,针对 Flea JPA 查询对象还存在的一个并发问题,将在后续的博文 《flea-db使用之基于对象池的FleaJPAQuery》 中介绍。

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
目录
相关文章
|
15天前
|
人工智能 JSON API
全网刷屏的 Jev 模型正式开放!一手实战测评 + 保姆级教程
全网爆火的 Jev 模型是什么?有什么用?怎么使用?怎么接入 AI 编程工具?效果真的好么?傻子可懂的 Jev 保姆级实战教程 + 项目实战测评来啦
8198 18
|
14天前
|
人工智能 并行计算 PyTorch
秋叶 ComfyUI 2026 整合包 v3.2 完整部署教程:Python 3.13 + Torch 2.13 全栈升级
秋叶aaaki ComfyUI 2026年8月整合包v3.2正式发布!全面升级Python 3.13.11、PyTorch 2.13.0+cu130及ComfyUI v0.30.2,原生支持MiniMax H3、Wan 2.2、Qwen-Image-2.1等2026主流音视频/图像模型,解压即用,无需环境配置。
2447 13
|
14天前
|
人工智能 测试技术 API
最近全网爆火的 Jev 到底是什么?适合干什么、怎么用,一篇讲透!
Jev是TypeSafe AI推出的“系统一模型”,不生成文本,专做毫秒级结构化决策:Choice(多选)、Score(打分)、Noul(是非概率)。响应快193倍、成本低444倍,适合工单路由、内容审核、测试定级等高频判断场景。
1859 4
最近全网爆火的 Jev 到底是什么?适合干什么、怎么用,一篇讲透!
|
12天前
|
人工智能 编解码 并行计算
MiniMax-H3 一键整合包技术文档:8G 显存运行 AI 漫剧制作 —— 角色替换 / 动作迁移 / 文图生视频部署与调参指南
MiniMax H3 是 MiniMax 开源的全模态视频生成模型,支持文/图/音/视多条件输入,输出最高2K、15秒带双声道音频视频。本文档详述其Int8量化版在8GB显存下的本地一键部署、三段式工作流(EDIT/REPLACE/CONTINUE)、参数调优及常见问题排查。(239字)
|
8天前
|
人工智能 Linux 开发者
【2026国内使用】Codex安装过程一篇讲透(Win/Mac/Linux全支持)
Codex是OpenAI推出的AI编程智能体,可读取本地项目、理解需求并自动修改代码。支持桌面GUI、命令行(CLI)及VS Code/Cursor插件三种形态,覆盖可视化操作、终端高效开发与编辑器无缝集成场景,助开发者用自然语言驱动编码全流程。(239字)
【2026国内使用】Codex安装过程一篇讲透(Win/Mac/Linux全支持)
|
8天前
|
人工智能 JSON 编解码
【2026最新版】ComfyUI本地部署教程,新手也能看懂!
ComfyUI是本地运行的AI绘画工具,采用节点式工作流设计:通过拖拽连接“加载模型”“提示词编码”“采样”“解码”等模块,实现高度可控的文生图。新手推荐使用秋叶整合包,一键启动、内置模型管理与插件安装器,轻松上手。(239字)
|
22天前
|
缓存 IDE Java
【保姆级】Android Studio下载、安装和汉化教程(2026最新)
Android Studio 是 Google 官方推出的免费 Android 应用开发集成环境,基于 IntelliJ IDEA,内置模拟器、调试器、性能分析及 Compose 界面工具,功能全面,文档丰富,是安卓开发首选工具。(239字)
2411 1

热门文章

最新文章