JPA、MySQL、Hibernate 和 Maven 骨架

Posted

技术标签:

【中文标题】JPA、MySQL、Hibernate 和 Maven 骨架【英文标题】:JPA, MySQL, Hibernate & Maven Skeleton 【发布时间】:2011-03-27 06:51:49 【问题描述】:

我一直在尝试使用 JPA、mysql、Hibernate 和 Maven 让一个简单的框架应用程序运行(并提交到数据库),但是我遇到了问题。

下面列出的是我的 2 个微不足道的类,我的 pom.xml 和我的 META-INF/persistence.xml

我可以毫无问题地构建项目(mvn clean install),但是运行它(mvn exec:java -Dexec.mainClass=com.foo.HelloWorld -X)会导致异常,并带有以下 StackTrace。

任何帮助将不胜感激!

堆栈跟踪:

org.apache.maven.lifecycle.LifecycleExecutionException:执行 Java 类时发生异常。空值 在 org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoals(DefaultLifecycleExecutor.java:719) 在 org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeStandaloneGoal(DefaultLifecycleExecutor.java:569) 在 org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoal(DefaultLifecycleExecutor.java:539) 在 org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalAndHandleFailures(DefaultLifecycleExecutor.java:387) 在 org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeTaskSegments(DefaultLifecycleExecutor.java:348) 在 org.apache.maven.lifecycle.DefaultLifecycleExecutor.execute(DefaultLifecycleExecutor.java:180) 在 org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:328) 在 org.apache.maven.DefaultMaven.execute(DefaultMaven.java:138) 在 org.apache.maven.cli.MavenCli.main(MavenCli.java:362) 在 org.apache.maven.cli.compat.CompatibleMain.main(CompatibleMain.java:60) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 在 java.lang.reflect.Method.invoke(Method.java:597) 在 org.codehaus.classworlds.Launcher.launchEnhanced(Launcher.java:315) 在 org.codehaus.classworlds.Launcher.launch(Launcher.java:255) 在 org.codehaus.classworlds.Launcher.mainWithExitCode(Launcher.java:430) 在 org.codehaus.classworlds.Launcher.main(Launcher.java:375) 原因:org.apache.maven.plugin.MojoExecutionException:执行 Java 类时发生异常。空值 在 org.codehaus.mojo.exec.ExecJavaMojo.execute(ExecJavaMojo.java:346) 在 org.apache.maven.plugin.DefaultPluginManager.executeMojo(DefaultPluginManager.java:490) 在 org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoals(DefaultLifecycleExecutor.java:694) ... 17 更多 引起:java.lang.reflect.InvocationTargetException 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 在 java.lang.reflect.Method.invoke(Method.java:597) 在 org.codehaus.mojo.exec.ExecJavaMojo$1.run(ExecJavaMojo.java:291) 在 java.lang.Thread.run(Thread.java:619) 引起:java.lang.NoSuchMethodError: org.hibernate.event.PreInsertEvent.getSource()Lorg/hibernate/engine/SessionImplementor; 在 org.hibernate.validator.event.ValidateEventListener.onPreInsert(ValidateEventListener.java:167) 在 org.hibernate.action.EntityIdentityInsertAction.preInsert(EntityIdentityInsertAction.java:142) 在 org.hibernate.action.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:65) 在 org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279) 在 org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:321) 在 org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:204) 在 org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:130) 在 org.hibernate.event.def.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:154) 在 org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:110) 在 org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:61) 在 org.hibernate.impl.SessionImpl.firePersist(SessionImpl.java:646) 在 org.hibernate.impl.SessionImpl.persist(SessionImpl.java:620) 在 org.hibernate.impl.SessionImpl.persist(SessionImpl.java:624) 在 org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:212) 在 com.foo.HelloWorld.create(HelloWorld.java:32) 在 com.foo.HelloWorld.main(HelloWorld.java:11) ... 6 更多

我有以下两个课程: 要存储的实体。

包 com.foo; 导入 java.io.Serializable; 导入 javax.persistence.Basic; 导入 javax.persistence.Entity; 导入 javax.persistence.GeneratedValue; 导入 javax.persistence.Id; @实体 公共类消息 @ID @GeneratedValue 私人 int id; @基本的 私人字符串消息; 公共消息() 公共消息(字符串消息) this.message = 消息; 公共字符串 toString() return "问候语 id=" + id + ", message=" + message;

应用程序:

包 com.foo; 公共类 HelloWorld 私有 javax.persistence.EntityManagerFactory 电动势; 私有 javax.persistence.EntityManager em; 私有字符串 PERSISTENCE_UNIT_NAME = "hello-world"; 公共静态无效主要(字符串[]参数) HelloWorld 你好 = 新的 HelloWorld(); 你好.initEntityManager(); 你好.create(); // hello.read(); 你好.closeEntityManager(); 私人无效initEntityManager() emf = javax.persistence.Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME); em = emf.createEntityManager(); 私人无效closeEntityManager() em.close(); emf.close(); 私人无效创建() em.getTransaction().begin(); Message hello = new Message("hello world"); Message bye = new Message("再见,世界"); 消息 [] 消息 = 新消息 [] 你好,再见; 对于(消息 m:消息) em.persist(m); em.getTransaction().commit(); // 私有无效读取() // 消息 m = (Message)em.createQuery("从消息 m 中选择 m").getSingleResult(); // System.out.println("查询返回:" + m); //

以下是我的 pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.treocht.hibernate.tutorial</groupId> <artifactId>hibernate-tutorial</artifactId> <version>1.0.0-SNAPSHOT</version> <name>First Hibernate Tutorial</name> <dependencies> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>3.3.2.GA</version> <type>jar</type> <scope>compile</scope> </dependency> <dependency> <groupId>javax.persistence</groupId> <artifactId>persistence-api</artifactId> <version>1.0</version> <type>jar</type> <scope>compile</scope> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.0.4</version> </dependency> <dependency> <groupId>hsqldb</groupId> <artifactId>hsqldb</artifactId> <version>1.8.0.7</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate</artifactId> <version>3.2.2.ga</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-annotations</artifactId> <version>3.2.1.ga</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>3.2.1.ga</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-tools</artifactId> <version>3.2.0.beta9a</version> </dependency> <dependency> <groupId>c3p0</groupId> <artifactId>c3p0</artifactId> <version>0.9.1</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.6.1</version> <type>jar</type> <scope>compile</scope> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.13</version> <type>jar</type> <scope>compile</scope> </dependency> </dependencies> <build> <!-- we dont want the version to be part of the generated war file name --> <finalName>$artifactId</finalName> <pluginManagement> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.6</source> <target>1.6</target> </configuration> </plugin> </plugins> </pluginManagement> </build> </project>

我有这个 META-INF/persistence.xml 文件:

org.hibernate.ejb.HibernatePersistencecom.foo.Message属性> 持久性>

【问题讨论】:

【参考方案1】:

您确实使用了不兼容版本的 Hibernate 工件,因为这可以使用 official Hibernate Compatibility Matrix 进行验证。不要依赖在网上找到的一些随机教程。

但是由于您使用的是 Maven,因此您实际上不需要声明所有 Hibernate 工件,只需利用传递依赖项即可。所以只需hibernate-entitymanager 中声明一个依赖项(尤其是如果您不确定自己在做什么):

<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-entitymanager</artifactId>
  <version>3.4.0.GA</version><!-- for JPA 1.0 -->
</dependency>

并删除这些hibernatehibernate-corehibernate-annotationspersistence-apislf4j 依赖项。

如果您想更改您获得的可传递的 sfl4j-api 工件的版本,您应该在依赖项管理部分执行此操作:

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.6.1</version>
    </dependency>
  </dependencies>
</dependencyManagement>

实际上(我很抱歉这么说)你的整个 pom 是一团糟,试着花一些时间清理它。使用 mvn dependency:tree(或您的 IDE 提供的一些可视化前端)来执行此操作。

让我坚持,不要依赖在网上找到的一些随机(和错误)的教程,利用 Maven 传递依赖机制。

PS:从 Hibernate 3.5 开始,各种项目(Hibernate Annotation、Hibernate EntityManager)已合并回 Hibernate Core,并且它们的版本已同步,这大大简化了版本管理,即使对于 Maven 用户也是如此。

【讨论】:

好的,谢谢。我已经在下面发布了我修改后的(工作)pom 作为答案。【参考方案2】:

可能存在版本冲突。 compare it with this

【讨论】:

这似乎已经修复好了(仍然不能 100% 确定哪个依赖项存在问题,但是一旦我将其减少到它的基本要素,我会发布我修改后的 pom.xml。)谢谢巴里 本教程让事情变得过于复杂,只需声明对 hibernate-entitymanager 的依赖即可。 帕斯卡,请您详细说明一下,下次我会注意的,但是让我知道这里出了什么问题? 没有必要声明所有的hibernate依赖,本教程滥用了Maven(从我目前看到的情况来看,我不能说我认为mkyong.com是一个值得信赖的参考) . 好的,谢谢帕斯卡的信息,下次我会注意的【参考方案3】:

现在可以了,我的 pom.xml 看起来像这样:

4.0.0com.company.hibernate.tutorial休眠教程1.0.0-SNAPSHOT休眠教程JBoss 存储库http://repository.jboss.com/maven2/存储库> org.hibernate休眠实体管理器3.4.0.GA依赖> mysqlmysql-connector-java5.1.13版本> 罐子依赖> log4jlog4j1.2.16版本> 依赖> org.slf4jslf4j-jdk141.6.1版本> 罐子编译依赖> 依赖> org.apache.maven.pluginsmaven-compiler-plugin1.61.6目标> 配置> 插件> 插件> 插件管理> org.slf4jslf4j-api1.6.1版本> 罐子编译依赖> 依赖> 项目>

【讨论】:

以上是关于JPA、MySQL、Hibernate 和 Maven 骨架的主要内容,如果未能解决你的问题,请参考以下文章

使用hibernate与spring数据jpa和mysql组成主键

在 JPA/Hibernate 中持久化映射到 MySQL 视图的实体

如何使用 JPA 和 Hibernate 将 MySQL JSON 列映射到 Java 实体属性

MySQL 使用 JPA + Hibernate 的 9 个高性能技巧

JPA+Hibernate+Mysql查询语言问题

JPA persistence.xml 和 MySQL - 没有采用正确的“hibernate.connection.url”目录