# JPA 的 Metamodel

**URL:** <https://www.isharkfly.com/t/jpa-metamodel/13848>\
**Category:** 程序语言\
**Tags:** java\
**Created:** [January 12, 2022, 5:33am UTC](https://www.isharkfly.com/t/jpa-metamodel/13848 "2022-01-12T05:33:14Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![honeymoose](https://www.isharkfly.com/user_avatar/www.isharkfly.com/honeymoose/32/20796_2.png) [@honeymoose](https://www.isharkfly.com/u/honeymoose)\
**Post date:** [January 12, 2022, 5:33am UTC](https://www.isharkfly.com/t/jpa-metamodel/13848/1 "2022-01-12T05:33:14Z")

</div>

JPA 定义了一个可以在运行时查询关于ORM映射信息的元模型（meta-model）。

元模型可以与Criteria API一起使用，而不是使用字符串来引用类属性。

## 什么是 Metamodel

如果你使用 JPA 或者 Hibernate 写 criteriaQuery 的时候。

你可能会遇到下面一句话

```auto
criteriaQuery.where(builder.greaterThan(root.get("dateM"), new DateTime().minusDays(100).toDate()));

```

抛开上面所有的类型定义不说，上面这句话的意思就是创建一个 SQL 查询 dateM 字段更新时间大于当前时间减去 100 天的时间。

如果使用 Metamodel 的话，就可以写成：

```auto
criteriaQuery.where(builder.greaterThan(root.get(MlsListing_.DATE_M), new DateTime().minusDays(100).toDate()));

```

上面这句话查询的是 MlsListing\_ORM 对象中的更新日期，与上面的那句话是等同的。

`MlsListing_.DATE_M` 就是我们说的 Metamodel 了，这个是动态生成的。

并且使用的是 ORM 对象加下划线的表达方式。

## 为什么要 Metamodel

其实我们并不需要使用 Metamodel，你可以直接使用 dateM。

但是，如果有一天你看见 dateM 不顺眼，改了 dateM 这个属性的名字的话，那么你所有程序中有关 dateM 的查询都要改。

因为你使用的是 String 字符串，Java 的编译器是没有办法找到编译错误的。

这个是不是很郁闷。

如果使用 Metamodel，所有的需要修改的地方都会触发编译错误。

这就是为什么我们会使用 Metamodel 的原因

## Metamodel 是在编译时候生成的

Metamodel 不是你代码的一部分。

这个是通过编译的时候生成的，你不需要手动进行代码编写。

你需要做的是，针对 maven 在 pom.xml 文件中

### 添加依赖

```auto
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-jpamodelgen</artifactId>
            <version>5.6.3.Final</version>
        </dependency>

```

 ![jpamodelgen-02](https://com-ossez-www-discourse.s3.dualstack.us-east-2.amazonaws.com/discourse-uploads/original/2X/a/a2458defdc2e3b9c94442c8aa9dba16ce319dc91.png)

上面为添加的依赖。

### 添加编译参数

```auto
  <compilerArguments>
                        <processor>org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor</processor>
                    </compilerArguments>

```

 ![jpamodelgen-01](https://com-ossez-www-discourse.s3.dualstack.us-east-2.amazonaws.com/discourse-uploads/original/2X/2/23467356f1484d75c3b774e4fba1bdab4df2a689.png)

然后你在运行 Maven 编译的时候，将会在动在 target 文件夹中生成对应的文件了。

### 编译后生成的文件

编译后生成的文件位于 target 文件夹中。

 ![jpamodelgen-03](https://com-ossez-www-discourse.s3.dualstack.us-east-2.amazonaws.com/discourse-uploads/original/2X/9/9f38f76ffbc05cf473ec93f21e32290d6b1b786f.png)

当你完成上面的 pom.xml 配置的话，你是完全没有问题来编译你的项目的。
