【技术】JavaSE环境下JPA实体类自动注册
在没有容器支持的环境下,JPA的实体类(Entity)一般要在persistence.xml中逐个注册,类似下面这样:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" 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_1.xsd">
<persistence-unit name="security-common">
<class>org.gems.han.security.common.MenuVO</class>
<class>org.gems.han.security.common.MenuItemVO</class>
<class>org.gems.han.security.common.ModuleVO</class>
<class>org.gems.han.security.common.RoleVO</class>
<class>org.gems.han.security.common.UserVO</class>
<class>org.gems.han.security.common.UserRoleVO</class>
</persistence-unit>
</persistence>
不知道大家有没有跟我一样感觉很麻烦,也很疑惑,明明每个实体类都标记了@Entity,为什么还要再注册一遍? 有没有办法利用@Entity标记,免除注册实体类的麻烦?经过研究,找到如下方案,分享给大家。
首先说明一下我使用的JPA实现是Eclipselink,我的方案也只在该实现下进行了验证。
我们知道EntityManagerFactory是由PersistenceProvider创建的,就从它入手设法解决上述问题。这个类在不同JPA实现中有不同的实现类,Eclipselink下是org.eclipse.persistence.jpa.PersistenceProvider,我们首先继承这个类,覆盖其中的方法createEntityManagerFactoryImpl,如下:
@Override
protected EntityManagerFactoryImpl createEntityManagerFactoryImpl(PersistenceUnitInfo puInfo, Map properties,
boolean requiresConnection) {
List<String> classNameList = puInfo.getManagedClassNames();
List<String> entityClassNameList =getManagedClassNames();
classNameList.addAll(entityClassNameList);
return super.createEntityManagerFactoryImpl(puInfo, properties, requiresConnection);
}
原理说明:第4行,如果persistence.xml中没有注册实体类,那么classNameList将是一个空的List(注意是empty list,不是null);第5行,通过方法getManagedClassNames获取实体类;第6行,把实体类增加到列表中;第7行,调用父类方法,实现工厂类的创建。下面关键就是getManagedClassNames方法的实现。这里我使用了google的开源项目guava来扫描java类,然后从中筛选有@Entity标记的实体类,代码如下:
public List<String> getManagedClassNames() {
List<String> managedClassNameList = new ArrayList<>();
ClassLoader loader = Thread.currentThread().getContextClassLoader();
ImmutableSet<ClassInfo> cs = null;
try {
cs = ClassPath.from(loader).getTopLevelClasses();
} catch (IOException e) {
e.printStackTrace();
}
managedClassNameList = new ArrayList<>();
if (cs != null && cs.isEmpty() == false) {
for (ClassInfo ci : cs) {
Class<?> c = null;
try {
c = loader.loadClass(ci.getName());
} catch (Throwable ex) {
}
if (c != null) {
Entity entity = c.getAnnotation(Entity.class);
if (entity != null) {
managedClassNameList.add(c.getName());
}
}
}
}
return managedClassNameList;
}
其中类加载器(loader)根据具体情况使用,但如果使用了特殊的ClassLoader,需要再覆盖org.eclipse.persistence.jpa.PersistenceProvider的getClassLoader方法,以便保证运行时能够正常加载实体类。
另外,在实验中发现PersisitenceProvider是通过SPI的方式加载的,而不是根据配置文件persistence.xml中的设置。因此,需要在META-INF下增加services/javax.persistence.spi.PersistenceProvider文件,在该文件中写入我们自己的PersistenceProvider。这一点我还有些疑惑,请大家在实践中进行验证。
【技术】JavaSE环境下JPA实体类自动注册的更多相关文章
- 在MyEclipse的Maven环境下,使用mybatis-generator插件自动生成映射文件(接口)及实体类
在数据表比较多的情况下,手动编写sql映射文件和实体类,实在太多过繁琐,而mybatis-generator能自动生成这此东西,减少了重复性的工作量.mybatis-generator的配置容易出现问 ...
- idea 从数据库快速生成Spring Data JPA实体类
第一步,调出 Persistence 窗口. File—>Project Structure—>model—> + —>JPA 第二步:打开 Persistence窗口 配置 ...
- Windows环境下Oracle数据库的自动备份脚本
批处理文件(.bat) @echo off echo ================================================ echo Windows环境下Oracle数据 ...
- Jpa实体类生成图解
Jpa实体类生成图解 创建连接 创建项目
- IDEA 生成 JPA实体类
文章目录1.创建工程2.连接数据源3.生成`JPA`实体类4.生成实体类结果1.创建工程使用Maven来构建工程,为了简化创建步骤 创建一个新工程不包含任何Maven模板,[按需添加] 命名 Grou ...
- Windows环境下Oracle数据库的自动备份脚本自动删除30天前的备份
@echo off echo ================================================ echo Windows环境下Oracle数据库的自动备份脚本 echo ...
- IntelliJ IDEA 2017版 spring-boot 实现jpa基本部署,通过实体类自动建立数据库
一.添加Spring Boot JPA-Hibernate步骤 1.在pom.xml添加mysql,spring-data-jpa依赖 2.在application.properties文件 ...
- SpringBoot24 SpringDataJPA环境搭建、实体类注解、关联查询
1 版本说明 JDK:1.8 MAVEN:3.5 SpringBoot:2.0.4 IDEA:旗舰版207.2 MySQL:5.5 2 SpringDataJPA环境搭建(SpringBoot版本) ...
- JPA实体类中常用的注解
这两天在看黎活明老师的JPA的讲解视频,现在只了解这么多,记录备用. import java.util.Date; import javax.persistence.Basic; import jav ...
随机推荐
- 无法连接到WMI提供程序 三种解决办法
无法连接到WMI 提供程序 请注意,你只能使用SQL Server 配置管理器来管理SQL Server 2005服务器.找不到指定的模块.[0x8007007e] 解决方案1: 检查一下 windo ...
- Java api 入门教程 之 JAVA的Random类
在实际的项目开发过程中,经常需要产生一些随机数值,例如网站登录中的校验数字等,或者需要以一定的几率实现某种效果,例如游戏程序中的物品掉落等. 在Java API中,在java.util包中专门提供了一 ...
- x01.os.5: DOS 功能调用
DOS 功能调用(INT 21)-------------------------------AH = 0-2E 适用 DOS 1.0 以上版本AH = 2F-57 适用 DOS 2.0 以上版本AH ...
- WIN 下的超动态菜单(二)用法
WIN 下的超动态菜单(一)简介 WIN 下的超动态菜单(二)用法 WIN 下的超动态菜单(三)代码 作者:黄山松,发表于博客园:http://www.cnblogs.com/tomview/ ...
- hive中的一种假NULL现象
使用hive时,我们偶尔会遇到这样的问题,当你将结果输出到屏幕时,查出的数据往往显示为null,但是当你将结果输出到文本时,却显示为空(即未填充),这是为什么呢? 在hive中有一种假NULL,它看起 ...
- PowerShell命令卸载Win10内置应用
Windows10系统预装了大批的应用,开始菜单右侧的磁贴即显示了其中的大部分,包括:人脉.日历.邮件.资讯.Xbox.Groove音乐.Camera相机.电影和电视.照片.手机助手.天气.OneNo ...
- input文本框和img验证码对齐问题
左边放input,右边img验证码,然后一直不能对齐,如图: img老是比input高出一个头,然后调的头都大了还是不行,照例百度之, 给input和img都加一个 vertical-align:mi ...
- 关于Lucene 3.0升级到Lucene 4.x 备忘
最近,需要对项目进行lucene版本升级.而原来项目时基于lucene 3.0的,很古老的一个版本的了.在老版本中中,我们主要用了几个lucene的东西: 1.查询lucene多目录索引. 2.构建R ...
- 台湾辅仁大学的python教程笔记
散记,因为主讲老师讲得也很乱..说课后的自习才是最重要的- 1.就这样,笔记看下.. 2. Modules 模组 很多模组放在一起就是一个packages 一个packages 一定有有__init_ ...
- 关于using关键字
使用C#访问数据库资源需要如下几步: SqlConnection con=new SqlConnection(str); try { con.Open(); //略 } catch(Exception ...