{"id":112,"date":"2024-10-30T17:43:49","date_gmt":"2024-10-30T09:43:49","guid":{"rendered":"https:\/\/zhoujibin.com\/?p=112"},"modified":"2024-10-31T10:10:11","modified_gmt":"2024-10-31T02:10:11","slug":"jpa%e8%bf%9b%e9%98%b6-%e5%ae%9e%e7%8e%b0%e5%ae%a1%e8%ae%a1%e6%97%a5%e5%bf%97","status":"publish","type":"post","link":"https:\/\/zhoujibin.com\/?p=112","title":{"rendered":"JPA\u8fdb\u9636-\u5b9e\u73b0\u5ba1\u8ba1\u65e5\u5fd7"},"content":{"rendered":"\n<h1 class=\"wp-block-heading\">\u524d\u8a00<\/h1>\n\n\n\n<p>\u4e0a\u4e00\u7bc7\u6587\u7ae0<a href=\"https:\/\/zhoujibin.com\/?p=108\">JPA\u7684\u7b80\u5355\u4f7f\u7528<\/a> \u8bb2\u4e86JPA\u7684\u57fa\u672c\u4f7f\u7528\u65b9\u6cd5\uff0c\u4e5f\u5b9e\u73b0\u4e86\u57fa\u672c\u7684\u5ba1\u8ba1\u65e5\u5fd7\uff0c\u4f46\u53ea\u8bb0\u5f55\u4e86\u64cd\u4f5c\u4eba\u3001\u64cd\u4f5c\u65f6\u95f4\u3001\u4fee\u6539\u4eba\u3001\u4fee\u6539\u65f6\u95f4\uff0c\u4e0d\u592a\u4eba\u6027\u5316\u3002\u6bd4\u5982\uff1a\u5177\u4f53\u4fee\u6539\u4e86\u4ec0\u4e48\u4fe1\u606f\uff0c\u8bef\u5220\u9664\u7684\u8bdd\u6709\u6ca1\u6709\u529e\u6cd5\u6062\u590d\uff0c\u4fee\u6539\u7684\u6570\u636e\u662f\u5426\u80fd\u56de\u6eda\uff0c\u8fd9\u4e9b\u95ee\u9898\u5728\u7cfb\u7edf\u5b9e\u9645\u4f7f\u7528\u8fc7\u7a0b\u4e2d\u90fd\u4f1a\u9047\u5230\u3002\u90a3\u4e48\uff0c\u5bf9\u4e8e\u7b80\u5355\u7684\u65b0\u589e\u3001\u4fee\u6539\u3001\u5220\u9664\u80fd\u4e0d\u80fd\u505a\u5230\u4ee5\u4e0a\u51e0\u70b9\u5462\uff1f\u5f88\u663e\u7136\uff0c\u5b8c\u5168\u6ca1\u95ee\u9898\uff0c\u6765\uff0c\u54b1\u4eec\u770b\u770b\u7b80\u5355\u7684\u5b9e\u73b0\u65b9\u5f0f\u3002<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">\u51c6\u5907\u5de5\u4f5c<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">\u7f16\u5199\u64cd\u4f5c\u8bb0\u5f55\u7684\u5b9e\u4f53\u7c7b<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\u64cd\u4f5c\u8bb0\u5f55<\/h3>\n\n\n\n<p>\u4e3b\u8981\u8bb0\u5f55\u64cd\u4f5c\u7684\u4e1a\u52a1\u8868\u3001\u4e3b\u952e\u7b49\u76f8\u5173\u4fe1\u606f\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@Data\npublic class PoEntity implements Serializable {\n\n    private static final long serialVersionUID = -4080920498644273280L;\n\n    \/**\n     * \u5b9e\u4f53\u7c7b\u5168\u8def\u5f84\n     *\/\n    private String entityName;\n    \/**\n     * \u8868\u540d\n     *\/\n    private String tableName;\n    \/**\n     * \u4e3b\u952e\u5b57\u6bb5\n     *\/\n    private String&#91;] pkFields;\n    \/**\n     * \u4e3b\u952e\u5b57\u6bb5\u503c\uff0c\u4e0e pkFields \u4e0b\u6807\u4e00\u4e00\u5bf9\u5e94\n     *\/\n    private Serializable&#91;] pkValues;\n    \/**\n     * \u8868\u5bf9\u5e94\u7684\u5217\u8be6\u60c5\n     *\/\n    private List&lt;PoEntityField&gt; fields;\n    \/**\n     * \u64cd\u4f5c\u6807\u8bc6\n     *\/\n    private String operateFlag;\n\n    \/**\n     * \u5f53\u524d\u64cd\u4f5c\u6267\u884c\u7684SQL\n     *\/\n    private String executeSql;\n\n    \/**\n     * \u56de\u6eda\u5f53\u524d\u64cd\u4f5c\u9700\u8981\u6267\u884c\u7684SQL\n     *\/\n    private String rollbackSql;\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\u64cd\u4f5c\u8bb0\u5f55\u8be6\u60c5<\/h3>\n\n\n\n<p>\u4e3b\u8981\u8bb0\u5f55\u6bcf\u6b21\u64cd\u4f5c\u65f6\u524d\u540e\u66f4\u6539\u8bb0\u5f55\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@Data\npublic class PoEntityField implements Serializable {\n\n    private static final long serialVersionUID = -3510567803633570818L;\n    \/**\n     * \u5b57\u6bb5\u540d\n     *\/\n    private String fieldName;\n    \/**\n     * \u5bf9\u4e8e\u7684java\u683c\u5f0f\u7684\u5b57\u6bb5\u7c7b\u578b\n     *\/\n    private String fieldType;\n    \/**\n     * \u5b57\u6bb5\u64cd\u4f5c\u524d\u7684\u503c\n     *\/\n    private Object oldFieldValue;\n    \/**\n     * \u5b57\u6bb5\u64cd\u4f5c\u540e\u7684\u503c\n     *\/\n    private Object newFieldValue;\n    \/**\n     * \u64cd\u4f5c\u524d\u540e\u7684\u503c\u662f\u5426\u66f4\u6539\n     *\/\n    private Boolean isChange;\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">\u7f16\u5199\u64cd\u4f5c\u5bf9\u5e94\u7684\u76d1\u542c<\/h2>\n\n\n\n<p>\u6211\u4eec\u5728\u6bcf\u6b21\u65b0\u589e\u3001\u5220\u9664\u3001\u4fee\u6539\u524d\u8c03\u7528\u6211\u4eec\u7684\u76d1\u542c\u65b9\u6cd5\uff0c\u8fd9\u4e2a\u53ef\u4ee5\u6839\u636e\u5b9e\u9645\u60c5\u51b5\u8c03\u6574\u3002\u6ce8\uff1a\u4ee5\u4e0b\u76d1\u542c\u5bf9\u5e94\u7684\u7c7b\u90fd\u6765\u6e90\u4e8eorg.hibernate.event.spi\u5305\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@Slf4j\n@Component\npublic class JpaBaseOperateListener implements\n        PostInsertEventListener\n        , PreDeleteEventListener\n        , PreUpdateEventListener {\n    @Resource\n    private EntityManagerFactory entityManagerFactory;\n\n    \/**\n     * \u76d1\u542c\u65b0\u589e\u64cd\u4f5c\n     * @param event\n     *\/\n    @Override\n    public void onPostInsert(PostInsertEvent event) {\n        this.formatPoEntity(event, OPERATE.INSERT);\n    }\n\n    \/**\n     * \u76d1\u542c\u5220\u9664\u64cd\u4f5c\uff0c\u6279\u91cf\u64cd\u4f5c\u65f6\u4f1a\u8c03\u7528\u591a\u6b21\uff08\u6ce8\uff1a\u8c03\u7528\u5b9e\u4f53\u7c7b\u5220\u9664\u65b9\u6cd5\u65f6\u624d\u80fd\u76d1\u542c\u5230\uff0c\u6839\u636eid\u5220\u9664\u65e0\u6cd5\u76d1\u542c\u5230\uff09\n     * @param event\n     * @return\n     *\/\n    @Override\n    public boolean onPreDelete(PreDeleteEvent event) {\n        this.formatPoEntity(event, OPERATE.DELETE);\n        return false;\n    }\n\n    \/**\n     * \u76d1\u542c \u4fee\u6539\u64cd\u4f5c \uff0c\u6279\u91cf\u64cd\u4f5c\u65f6\u4f1a\u8c03\u7528\u591a\u6b21\n     * @param event\n     * @return\n     *\/\n    @Override\n    public boolean onPreUpdate(PreUpdateEvent event) {\n        this.formatPoEntity(event, OPERATE.UPDATE);\n        return false;\n    }\n\n    \/**\n     * \u8c03\u7528\u65b9\u6cd5\u5bf9\u5e94\u7684\u679a\u4e3e\u7c7b\n     *\/\n    private enum CallMethod {\n        getEntity,\n        getOldState,\n        getState,\n        getPersister,\n        getDeletedState\n    }\n\n    \/**\n     * \u683c\u5f0f\u5316 \u5b57\u6bb5\u4fe1\u606f\n     *\n     * @param eventObj\n     *\/\n    private void formatPoEntity(Object eventObj, OPERATE operate) {\n        Object entityObj = ReflectUtil.invoke(eventObj, CallMethod.getEntity.name());\n        Method oldStateMethod = ReflectUtil.getMethod(eventObj.getClass(), ObjectUtil.equal(OPERATE.DELETE, operate) ? CallMethod.getDeletedState.name() : CallMethod.getOldState.name());\n        Object&#91;] oldValueArr = null;\n        if (ObjectUtil.isNotNull(oldStateMethod)) {\n            oldValueArr = ReflectUtil.invoke(eventObj, oldStateMethod);\n        }\n        Method stateMethod = ReflectUtil.getMethod(eventObj.getClass(), CallMethod.getState.name());\n        Object&#91;] newValueArr = null;\n        if (ObjectUtil.isNotNull(stateMethod)) {\n            newValueArr = ReflectUtil.invoke(eventObj, stateMethod);\n        }\n        Method getEpMethod = ReflectUtil.getMethod(eventObj.getClass(), CallMethod.getPersister.name());\n        SingleTableEntityPersister ep = null;\n        if (ObjectUtil.isNotNull(getEpMethod)) {\n            ep = ReflectUtil.invoke(eventObj, getEpMethod);\n        }\n        PoEntity entity = new PoEntity();\n        String operateName = operate.name();\n        entity.setOperateFlag(operateName);\n        \/\/ \u8868\u540d\n        String tableName = ep.getTableName();\n        entity.setTableName(tableName);\n        List&lt;PoEntityField&gt; poEntityFields = new ArrayList&lt;&gt;();\n        String&#91;] pkFields = ep.getIdentifierColumnNames();\n        if (ArrayUtil.isNotEmpty(pkFields)) {\n            Serializable&#91;] pkValues = new Serializable&#91;pkFields.length];\n            for (int i = 0; i &lt; pkFields.length; i++) {\n                pkValues&#91;i] = (Serializable) ReflectUtil.getFieldValue(entityObj, pkFields&#91;i]);\n            }\n            entity.setPkValues(pkValues);\n        }\n        entity.setPkFields(pkFields);\n        \/\/ \u5b9e\u4f53\u7c7b\u7684\u5168\u8def\u5f84\n        String entityName = ep.getEntityName();\n        entity.setEntityName(entityName);\n        \/\/ \u83b7\u5f97\u5b9e\u4f53\u7c7b\u7684\u6240\u6709\u5c5e\u6027\n        String&#91;] propertyNames = ep.getPropertyNames();\n        Object tempOldValue = null;\n        Object tempNewValue = null;\n        List&lt;String&gt; newValueList = new ArrayList&lt;&gt;();\n        for (int i = 0; i &lt; propertyNames.length; i++) {\n            String propertyName = propertyNames&#91;i];\n            PoEntityField field = new PoEntityField();\n            Type propertyType = ep.getPropertyType(propertyName);\n            field.setFieldName(propertyName);\n            String fieldType = propertyType.getReturnedClass().getName();\n            field.setFieldType(fieldType);\n            if (i &lt; ArrayUtil.length(oldValueArr)) {\n                tempOldValue = oldValueArr&#91;i];\n            }\n            field.setOldFieldValue(tempOldValue);\n            if (i &lt; ArrayUtil.length(newValueArr)) {\n                tempNewValue = newValueArr&#91;i];\n            }\n            newValueList.add(String.valueOf(tempNewValue));\n            field.setNewFieldValue(tempNewValue);\n            field.setIsChange(!ObjectUtil.equal(field.getOldFieldValue(), field.getNewFieldValue()));\n            poEntityFields.add(field);\n        }\n        \/\/ \u65b0\u589e\u4e3b\u952e\u5bf9\u5e94\u7684\u5217\n        PoEntityField pkEntityField = new PoEntityField();\n        pkEntityField.setFieldName(entity.getPkFields()&#91;0]);\n        pkEntityField.setOldFieldValue(entity.getPkValues()&#91;0]);\n        pkEntityField.setNewFieldValue(entity.getPkValues()&#91;0]);\n        pkEntityField.setIsChange(Boolean.FALSE);\n        poEntityFields.add(0, pkEntityField);\n        entity.setFields(poEntityFields);\n        this.formatExecuteAndRollbackSql(entity);\n    }\n\n    \/**\n     * \u5220\u9664 sql \u6a21\u677f\n     *\/\n    private String DELETE_SQL_TEMPLATE = \"delete from {} where {} = '{}';\";\n    private String INSERT_SQL_TEMPLATE = \"insert into {} (`{}`) values ('{}');\";\n    private String UPDATE_SQL_TEMPLATE = \"update {} set {} where {} = '{}';\";\n\n    \/**\n     * \u5f97\u5230\u6267\u884csql\u4ee5\u53ca\u56de\u6edasql\n     *\/\n    private void formatExecuteAndRollbackSql(PoEntity entity) {\n        String operateFlag = entity.getOperateFlag();\n        String tableName = entity.getTableName();\n        String&#91;] pkFields = entity.getPkFields();\n        Serializable&#91;] pkValues = entity.getPkValues();\n        List&lt;PoEntityField&gt; fields = entity.getFields();\n        String executeSql = \"\";\n        String rollbackSql = \"\";\n        String firstPkField = pkFields&#91;0];\n        String firstPkValue = String.valueOf(pkValues&#91;0]);\n        List&lt;String&gt; fieldNameList = fields.parallelStream().map(f -&gt; StrUtil.toUnderlineCase(f.getFieldName())).collect(Collectors.toList());\n        List&lt;Object&gt; oldValueList = fields.parallelStream().map(PoEntityField::getOldFieldValue).collect(Collectors.toList());\n        List&lt;Object&gt; newValueList = fields.parallelStream().map(PoEntityField::getNewFieldValue).collect(Collectors.toList());\n        if (StrUtil.equals(OPERATE.INSERT.name(), operateFlag)) {\n            executeSql = StrUtil.format(INSERT_SQL_TEMPLATE, tableName,\n                    CollUtil.join(fieldNameList,\"`,`\"),\n                    CollUtil.join(newValueList,\"','\")\n                    );\n            rollbackSql = StrUtil.format(DELETE_SQL_TEMPLATE, tableName, firstPkField, firstPkValue);\n        } else if (StrUtil.equals(OPERATE.UPDATE.name(), operateFlag)) {\n            executeSql = StrUtil.format(UPDATE_SQL_TEMPLATE, tableName,\n                    CollUtil.join(fields.parallelStream().map(f -&gt; {\n                        Object newFieldValue = f.getNewFieldValue();\n                        return \" `\" + StrUtil.toUnderlineCase(f.getFieldName()) + \"` = '\" + newFieldValue + \"'\";\n                    }).collect(Collectors.toList()),\",\")\n                    , firstPkField, firstPkValue);\n            rollbackSql = StrUtil.format(UPDATE_SQL_TEMPLATE, tableName,\n                    CollUtil.join(fields.parallelStream().map(f -&gt; {\n                        Object oldFieldValue = f.getOldFieldValue();\n                        return \" `\" + StrUtil.toUnderlineCase(f.getFieldName()) + \"` = '\" + oldFieldValue + \"'\";\n                    }).collect(Collectors.toList()),\",\")\n                    , firstPkField, firstPkValue);\n        } else if (StrUtil.equals(OPERATE.DELETE.name(), operateFlag)) {\n            executeSql = StrUtil.format(DELETE_SQL_TEMPLATE, tableName, firstPkField, firstPkValue);\n            rollbackSql= StrUtil.format(INSERT_SQL_TEMPLATE, tableName,\n                    CollUtil.join(fieldNameList,\"`,`\"),\n                    CollUtil.join(oldValueList,\"','\")\n            );\n        } else {\n            throw new RuntimeException(\"Nonsupport operate flag\");\n        }\n        \/\/ \u8fd9\u91cc\u7684\u64cd\u4f5c\u8be6\u60c5\u53ea\u662f\u505a\u4e86\u90e8\u5206\u6570\u636e\u6253\u5370\uff0c\u5b9e\u9645\u5e94\u7528\u65f6\u53ef\u4ee5\u76f4\u63a5\u5b58\u50a8\u53ea\u8868\u4e2d\n        entity.setExecuteSql(executeSql);\n        log.info(\"executeSql = &gt; {}\", executeSql);\n        entity.setRollbackSql(rollbackSql);\n        log.info(\"rollbackSql = &gt; {}\", rollbackSql);\n    }\n\n    \/**\n     * \u53c2\u8003\uff1ahttps:\/\/www.coder.work\/article\/6818980\n     *\/\n    @PostConstruct\n    protected void regListener() {\n        SessionFactoryImpl sessionFactory = entityManagerFactory.unwrap(SessionFactoryImpl.class);\n        EventListenerRegistry registry = sessionFactory.getServiceRegistry().getService(EventListenerRegistry.class);\n        \/\/ \u6ce8\u518c \u65b0\u589e \u540e\u7684\u64cd\u4f5c\u76d1\u542c\n        registry.getEventListenerGroup(EventType.POST_INSERT).appendListener(this);\n        \/\/ \u6ce8\u518c \u4fee\u6539 \u524d\u7684\u64cd\u4f5c\u76d1\u542c\n        registry.getEventListenerGroup(EventType.PRE_UPDATE).appendListener(this);\n        \/\/ \u6ce8\u518c \u5220\u9664 \u524d\u7684\u64cd\u4f5c\u76d1\u542c\n        registry.getEventListenerGroup(EventType.PRE_DELETE).appendListener(this);\n    }\n\n    @Override\n    public boolean requiresPostCommitHanding(EntityPersister persister) {\n        log.info(\"=====requiresPostCommitHanding======\");\n        return false;\n    }\n\n    @Override\n    public boolean requiresPostCommitHandling(EntityPersister persister) {\n        log.info(\"=====requiresPostCommitHandling======\");\n        return false;\n    }\n\n    \/**\n     * \u64cd\u4f5c\u7b26\u6807\u8bc6\n     *\/\n    private enum OPERATE {\n        INSERT,\n        UPDATE,\n        DELETE;\n    }\n\n}<\/code><\/pre>\n\n\n\n<h1 class=\"wp-block-heading\">\u6d4b\u8bd5<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">\u65b0\u589e<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\u6d4b\u8bd5\u4ee3\u7801<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>    @Test\n    void insertOne() {\n        String password = SecureUtil.md5(\"user\");\n        UserPO userPO = new UserPO()\n                .setAccount(\"user\")\n                .setPassword(password)\n                .setUserName(\"\u6d4b\u8bd5\u7528\u6237\")\n                .setAge(20)\n                .setGender(1)\n                .setDeleteFlag(\"0\");\n        this.userDao.save(userPO);<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\u65e5\u5fd7<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code> executeSql = &gt; insert into user (`id`,`account`,`age`,`create_time`,`create_user`,`delete_flag`,`gender`,`password`,`update_time`,`update_user`,`user_name`) values ('c6d51d34edb4456e991be767b670501f','user','20','2022-03-03T21:44:10.216','operateId','0','1','ee11cbb19052e40b07aac0ca060c23ee','2022-03-03T21:44:10.216','operateId','\u6d4b\u8bd5\u7528\u6237');\nrollbackSql = &gt; delete from user where id = 'c6d51d34edb4456e991be767b670501f';<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">\u4fee\u6539<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\u6d4b\u8bd5\u4ee3\u7801<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>    @Test\n    public void update() {\n        String userId = \"38f9303f2616413dbb600305b208f241\";\n        Optional&lt;UserPO&gt; opt = this.userDao.findById(userId);\n        UserPO userPO = new UserPO();\n        if (opt.isPresent()) {\n            BeanUtil.copyProperties(opt.get(), userPO);\n        }\n        userPO.setUserName(\"777\").setAccount(\"user777\");\n        UserPO save = this.userDao.save(userPO);\n        System.out.println(save.toString());\n    }<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\u65e5\u5fd7<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>executeSql = &gt; insert into user (`id`,`account`,`age`,`create_time`,`create_user`,`delete_flag`,`gender`,`password`,`update_time`,`update_user`,`user_name`) values ('6dec8d86f8c242f6ab148ca82dcd2d1f','user777','null','2022-03-03T21:50:04.516','operateId','null','null','null','2022-03-03T21:50:04.516','operateId','777');\nrollbackSql = &gt; delete from user where id = '6dec8d86f8c242f6ab148ca82dcd2d1f';<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">\u5220\u9664<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\u6d4b\u8bd5\u4ee3\u7801<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>    @Test\n    public void deleteOne() {\n        String userId = \"38f9303f2616413dbb600305b208f241\";\n        this.userDao.deleteById(userId);\n    }<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\u65e5\u5fd7<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>executeSql = &gt; delete from user where id = '38f9303f2616413dbb600305b208f241';\nrollbackSql = &gt; insert into user (`id`,`account`,`age`,`create_time`,`create_user`,`delete_flag`,`gender`,`password`,`update_time`,`update_user`,`user_name`) values ('38f9303f2616413dbb600305b208f241','user888','20','2022-03-02T22:51:07.841','operateId','0','1','ee11cbb19052e40b07aac0ca060c23ee','2022-03-02T23:17:26.389','operateId','888');<\/code><\/pre>\n\n\n\n<p>\u81f3\u6b64\uff0c\u57fa\u7840\u7684\u5ba1\u8ba1\u65e5\u5fd7\u529f\u80fd\u4ee5\u53ca\u5b8c\u6210\u5566\uff0c\u503c\u5f97\u4e00\u63d0\u7684\u662f\uff1a\u672c\u6587\u4e2d\u7684\u64cd\u4f5c\u8bb0\u5f55\u53ca\u8be6\u60c5\u53ea\u662f\u5b58\u50a8\u81f3\u5728\u5b9e\u4f53\u7c7b\u4e2d\u5e76\u672a\u505a\u6301\u4e45\u5316\u64cd\u4f5c\uff0c\u5b9e\u51b5\u5f00\u53d1\u8fc7\u7a0b\u4e2d\u53ef\u80fd\u9700\u8981\u4fdd\u5b58\u81f3\u6570\u636e\u5e93\u3002<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">\u603b\u7ed3<\/h1>\n\n\n\n<p>\u672c\u6587\u4e2d\u7684\u793a\u4f8b\u53ea\u662f\u5bf9JPA\u7684\u90e8\u5206\u64cd\u4f5c\u505a\u4e86\u76d1\u542c\uff0c\u5176\u4ed6\u76d1\u542c\u64cd\u4f5c\u53ef\u67e5\u770b\u6e90\u7801\uff1aorg.hibernate.event.spi.EventType\u3002<\/p>\n\n\n\n<p>\uff08\u6ce8\uff1a\u76f8\u5173\u7684\u7c7b\u5728org.hibernate:hibernate-core:5.6.5.Final2.jar\u5305\u4e2d\uff09<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u524d\u8a00 \u4e0a\u4e00\u7bc7\u6587\u7ae0JPA\u7684\u7b80\u5355\u4f7f\u7528 \u8bb2\u4e86JPA\u7684\u57fa\u672c\u4f7f\u7528\u65b9\u6cd5\uff0c\u4e5f\u5b9e\u73b0\u4e86\u57fa\u672c\u7684\u5ba1\u8ba1\u65e5\u5fd7\uff0c\u4f46\u53ea\u8bb0\u5f55\u4e86\u64cd\u4f5c\u4eba\u3001\u64cd\u4f5c\u65f6\u95f4 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[21,23],"class_list":["post-112","post","type-post","status-publish","format-standard","hentry","category-java","tag-jpa","tag-23"],"_links":{"self":[{"href":"https:\/\/zhoujibin.com\/index.php?rest_route=\/wp\/v2\/posts\/112"}],"collection":[{"href":"https:\/\/zhoujibin.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/zhoujibin.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/zhoujibin.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/zhoujibin.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=112"}],"version-history":[{"count":2,"href":"https:\/\/zhoujibin.com\/index.php?rest_route=\/wp\/v2\/posts\/112\/revisions"}],"predecessor-version":[{"id":195,"href":"https:\/\/zhoujibin.com\/index.php?rest_route=\/wp\/v2\/posts\/112\/revisions\/195"}],"wp:attachment":[{"href":"https:\/\/zhoujibin.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=112"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/zhoujibin.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=112"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/zhoujibin.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=112"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}