数据初始化问题 - 使用hibernate.hbm2ddl.auto = create复制密钥条目 - Hibernate JPA

时间:2014-05-03 20:10:40

标签: hibernate jpa

根据my own question我刚刚在Startup Singleton的PostConstruct中发现了数据初始化的另一个问题。该问题是由主键冲突引起的,该冲突是在以下期间生成的:

@Singleton
@Startup
public class DefaultDataIntializer {

  @PostConstruct
  public void init()
  {
    BlinkUser bu = createDefaultUser();
    BlinkGroup bg = createDefaultGroup();
    Link l = createDefaultLink();
    UserLink ul = createDefaultUserLink();

    if(buf.find(bu.getEmail()) != null)
      return;

    bg.addUser(bu);
    ul.setLink(l);
    ul.setOwner(bu);

    lf.create(l);
    bgf.create(bg);
    buf.create(bu);
    ulf.create(ul);     
  } 
}

here是完整部署的日志。问题在于:

Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry 'user@gmail.com' for key 'PRIMARY'

但是当我使用调试器时,问题在创建过程中没有显示出来。也许是由一些缓存引起的?好吧,这是远景,我只是没有发现任何错误,特别是我在创建之前检查示例数据的存在(DefaultDataInitializer :: init():5)。另外,这是我的persistence.xml:

 <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
   <persistence-unit name="BlinkLinkServer-ejbPU" transaction-type="JTA">
   <provider>org.hibernate.ejb.HibernatePersistence</provider>
   <jta-data-source>java:jboss/datasources/BlinkLinkDataSource</jta-data-source>
   <exclude-unlisted-classes>false</exclude-unlisted-classes>
   <properties>
     <property name="hibernate.hbm2ddl.auto" value="create"/>
     <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
   </properties>
 </persistence-unit>

也许某些交易有问题?我不应该这样初始化数据?谢谢你的帮助!

修改 根本原因是重复调用postConstruct方法。即使是同步或附加变量(甚至是静态的)也不能解决问题。甚至调试器也没有显示第二次调用(第二次没有在断点处停止)。那么我怎么弄清楚这是不同的方法呢?

public synchronized void init()
{
            Logger.getAnonymousLogger().warning("Initializing data!" + (new Random()).nextInt());
            //rest of previous code

}

给出了:

 16:08:21,079 WARNING [null] (ServerService Thread Pool -- 424) Initializing data!778044534
 16:08:21,116 WARNING [null] (ServerService Thread Pool -- 423) Initializing data!1060447455

1 个答案:

答案 0 :(得分:0)

好的,所以此问题的真正原因是项目中的重复ejb jar - 一个在WAR中,另一个在EAR中打包。我不知道调试器怎么不让我进入@PostConstruct方法的第二次调用。感谢TomasZ寻求帮助,我没有单独解决这个问题。

解决方案:

检查Maven项目。 WAR中的pom.xml应具有依赖性:

    <dependency>
        <groupId>${project.groupId}</groupId>
        <artifactId>YourProject-ejb</artifactId>
        <version>${project.version}</version>
    </dependency>

据此,带有EJB项目的JAR文件被打包到WAR中。我相信你将拥有一个包含其他依赖项的EJB maven项目:

    <dependency>
        <groupId>com.example.project</groupId>
        <artifactId>YourProject-ejb</artifactId>
        <version>1.0-SNAPSHOT</version>
        <type>ejb</type>
    </dependency>
    <dependency>
        <groupId>com.example.project</groupId>
        <artifactId>YourProject-web</artifactId>
        <version>1.0-SNAPSHOT</version>
        <type>war</type>
    </dependency>

所以还有JAR文件。它是错误的行为(我正在使用NetBeans,因此它是项目创建者的错误)。有一些方法可以避免这种情况:

  1. provided范围添加到WAR项目中的pom.xml:

    <dependency>
        <groupId>${project.groupId}</groupId>
        <artifactId>YourProject-ejb</artifactId>
        <version>${project.version}</version>
        <scope>provided</scope>
    </dependency>
    

    然后jar不会包含在WAR中。

  2. 为maven-war-plugin配置添加skinnyWar选项 described here

  3. 可以出于某种原因希望将您的JAR文件保留在WAR中并从EAR中删除。因此,您可以简单地将提供的选项添加到EAR文件中的依赖项。

    <dependency>
        <groupId>com.example.project</groupId>
        <artifactId>YourProject-ejb</artifactId>
        <version>1.0-SNAPSHOT</version>
        <type>ejb</type>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>com.example.project</groupId>
        <artifactId>YourProject-web</artifactId>
        <version>1.0-SNAPSHOT</version>
        <type>war</type>
    </dependency>