如何将现有 Id 设置为 HyperJaxb3 Cxf 项目中的主键(从 wsdl 生成代码)?

How to set existing Id as primary key in HyperJaxb3 Cxf project, (code generation from wsdl)?

我正在尝试将主键重新定义为现有 ID,但使用从 wsdl 文件生成的 Apache CXF 插件。 wsdl 文件在这里 - https://api.mindbodyonline.com/0_5/ClientService.asmx?wsdl

我的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/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>MindBodyCXF</groupId>
  <artifactId>CXFSpring</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>CXFSpring Maven Webapp</name>
  <url>http://maven.apache.org</url>
    <properties>
        <cxf.version>2.5.6</cxf.version>
        <hibernate-jpa-2.1-api.version>1.0.0.Final</hibernate-jpa-2.1-api.version>
        <hibernate-entitymanager.version>4.3.8.Final</hibernate-entitymanager.version>
        <hyperjaxb3-ejb.version>0.5.5</hyperjaxb3-ejb.version>
        <hsqldb.version>2.3.2</hsqldb.version>
        <hibernate.maven.plugin.version>2.2</hibernate.maven.plugin.version>
    </properties>
    <dependencies>
        <!-- Spring -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>3.0.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>3.0.1.RELEASE</version>
        </dependency>

        <!-- Apache CXF -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-frontend-jaxws</artifactId>
            <version>${cxf.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-core</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-beans</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-context</artifactId>
                </exclusion>

            </exclusions>

        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http</artifactId>
            <version>${cxf.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-web</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-databinding-jaxb</artifactId>
            <version>${cxf.version}</version>
        </dependency>
        <!-- Hibernate -->
        <dependency>
            <groupId>org.hibernate.javax.persistence</groupId>
            <artifactId>hibernate-jpa-2.1-api</artifactId>
            <version>${hibernate-jpa-2.1-api.version}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>${hibernate-entitymanager.version}</version>
        </dependency>
        <!-- Hyperjaxb3 -->
        <dependency>
            <groupId>org.jvnet.hyperjaxb3</groupId>
            <artifactId>hyperjaxb3-ejb-runtime</artifactId>
            <version>${hyperjaxb3-ejb.version}</version>
        </dependency>
        <!-- HSQLDB -->
        <dependency>
            <groupId>org.hsqldb</groupId>
            <artifactId>hsqldb</artifactId>
            <version>${hsqldb.version}</version>
            <scope>runtime</scope>
        </dependency>

        <!--PostgresSQL-->
        <dependency>
            <groupId>postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>9.1-901.jdbc4</version>
        </dependency>
        <!-- Logging -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.6.1</version>
        </dependency>

        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.1.1</version>
            <exclusions>
                <exclusion>
                    <groupId>log4j</groupId>
                    <artifactId>log4j</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>logkit</groupId>
                    <artifactId>logkit</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>avalon-framework</groupId>
                    <artifactId>avalon-framework</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>javax.servlet</groupId>
                    <artifactId>servlet-api</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- Testing -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.7</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>3.0.1.RELEASE</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.hisrc.hifaces20</groupId>
            <artifactId>hifaces20-testing</artifactId>
            <version>0.1.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>1.1.0.Final</version>
        </dependency>

        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-core</artifactId>
            <version>3.0.4</version>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-rs-client</artifactId>
            <version>3.0.4</version>
        </dependency>
        <!--String processing-->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>18.0</version>
        </dependency>
        <dependency>
            <groupId>org.jadira.usertype</groupId>
            <artifactId>usertype.core</artifactId>
            <version>3.0.0.CR1</version>
        </dependency>
        <dependency>
            <groupId>joda-time</groupId>
            <artifactId>joda-time</artifactId>
            <version>2.7</version>
        </dependency>


    </dependencies>
    <build>
        <finalName>MindBodyCXF</finalName>
        <plugins>
            <!--hibernate plugin for ddl creation-->
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>hibernate3-maven-plugin</artifactId>
                <version>${hibernate.maven.plugin.version}</version>
                <executions>
                    <execution>
                        <phase>process-classes</phase>
                        <goals>
                            <goal>hbm2ddl</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <components>
                        <component>
                            <name>hbm2ddl</name>
                            <implementation>jpaconfiguration</implementation>
                            <outputDirectory>src/main/resources/hbm2ddl</outputDirectory>
                        </component>
                    </components>
                    <componentProperties>
                        <persistenceunit>integration.mindbody</persistenceunit>
                        <propertyfile>src/test/resources/persistence.properties</propertyfile>
                        <outputfilename>schema.ddl</outputfilename>

                        <drop>true</drop>
                        <create>true</create>
                        <export>true</export>
                        <format>true</format>
                    </componentProperties>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>postgresql</groupId>
                        <artifactId>postgresql</artifactId>
                        <version>9.1-901.jdbc4</version>
                    </dependency>
                </dependencies>
            </plugin>

            <!--cxf plugin for wsdl 2 java-->
            <plugin>
                <groupId>org.apache.cxf</groupId>
                <artifactId>cxf-codegen-plugin</artifactId>
                <version>${cxf.version}</version>
                <executions>
                    <execution>
                        <id>generate-sources</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>wsdl2java</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <sourceRoot>${project.build.sourceDirectory}</sourceRoot>
                   
                    <wsdlOptions>
                        <wsdlOption>
                           
                            <wsdl>${basedir}/src/main/wsdl/ClientService.xml</wsdl>

                           
                            <bindingFiles>
                                <!-- JAX-WS bindings -->
                                <bindingFile>${basedir}/src/main/wsdl/binding.xml</bindingFile>
                               
                            </bindingFiles>
                            <extraargs>
                                <!-- Turns on the hashCode plugin -->
                                <extraarg>-xjc-XhashCode</extraarg>
                                <!-- Turns on the equals plugin -->
                                <extraarg>-xjc-Xequals</extraarg>
                                <extraarg>-xjc-XtoString</extraarg>
                                <!-- Turns on the Hyperjaxb3 EJB plugin -->
                                <extraarg>-xjc-Xhyperjaxb3-ejb</extraarg>
                                <!--<extraarg>-xjc-Xinheritance</extraarg>-->
                                <extraarg>-xjc-XfixJAXB1058</extraarg>
                                <extraarg>-xjc-enableIntrospection</extraarg>
                                <extraarg>-impl</extraarg>
                                <!--<extraarg>-verbose</extraarg>-->

                            </extraargs>
                        </wsdlOption>
                    </wsdlOptions>

                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.jvnet.jaxb2_commons</groupId>
                        <artifactId>jaxb2-basics</artifactId>
                        <version>0.9.3</version>
                    </dependency>
                    <dependency>
                        <groupId>org.jvnet.hyperjaxb3</groupId>
                        <artifactId>hyperjaxb3-ejb-plugin</artifactId>
                        <version>${hyperjaxb3-ejb.version}</version>

                    </dependency>
                </dependencies>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.2</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>
        </plugins>
        <!--to allow hbm generation-->
        <resources>
            <resource>
                <directory>src/main/wsdl</directory>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>META-INF/persistence.xml</include>
                </includes>
            </resource>
        </resources>
    </build>
</project>

我的binding.xml在这里-

<jaxws:bindings

        xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
        xmlns:s="http://www.w3.org/2001/XMLSchema"
        xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
        xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
        xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
        xmlns:hj="http://hyperjaxb3.jvnet.org/ejb/schemas/customizations"
        xmlns:orm="http://java.sun.com/xml/ns/persistence/orm"
        jaxb:extensionBindingPrefixes="xjc hj orm"
        xmlns:test="urn:test">



    <jaxws:bindings node="wsdl:definitions/wsdl:types/s:schema" >
        <jaxb:globalBindings generateElementProperty="false" localScoping="toplevel" generateIsSetMethod="false" >
            <jaxb:javaType name="java.util.Date" xmlType="s:dateTime"
                           parseMethod="org.apache.cxf.tools.common.DataTypeAdapter.parseDateTime"
                           printMethod="org.apache.cxf.tools.common.DataTypeAdapter.printDateTime" />
            <jaxb:javaType name="java.util.Date" xmlType="s:date"
                           parseMethod="org.apache.cxf.tools.common.DataTypeAdapter.parseDate"
                           printMethod="org.apache.cxf.tools.common.DataTypeAdapter.printDate" />
            <jaxb:serializable uid="1"/>
        </jaxb:globalBindings>
        <jaxws:enableWrapperStyle>
            false
        </jaxws:enableWrapperStyle>
        <hj:persistence>
            <hj:default-one-to-many fetch="EAGER"/>

        </hj:persistence>

        <jaxb:bindings node="s:complexType/s:complexContent/s:extension/s:sequence/s:element[@name='Description']">
            <hj:basic>
                <orm:column length="2500"/>
            </hj:basic>
        </jaxb:bindings>
        <jaxb:bindings node="s:complexType/s:complexContent/s:extension/s:sequence/s:element[@name='Bio']">
            <hj:basic>
                <orm:column length="750"/>
            </hj:basic>
        </jaxb:bindings>
        <jaxb:bindings node="s:complexType/s:complexContent/s:extension/s:sequence/s:element[@name='ID']">
        <hj:id/>
    </jaxb:bindings>


    </jaxws:bindings>
</jaxws:bindings>

但选择的 ID 未转换为 @Id。

如何更改我的 binding.xml 以进行转换?

对 Aleksei 1 条评论的回答:

我添加了更多通用请求以涵盖所有需要的 ID 并通过 FindPath Mozilla Extension 验证所有结果 - 只选择了需要的元素 `

<jaxb:bindings node="//s:element[@name='ID']">
            <hj:id/>
        </jaxb:bindings>

`

类生成了,但是当我运行'mvn process-classes'的时候却收到一个错误:

Caused by: org.hibernate.AnnotationException: Unable to define/override @Id(s) on a subclass: integration.mindbody.Appointment

我认为它是对 ArrayOfAppointment 中生成的 Hjid 和 Appointment 中的 Id 抛出的;

ArrayOfAppointment.java: `

 @Id
    @Column(name = "HJID")
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Long getHjid() {
        return hjid;
    }

`

Appointment.java:
`

 @Id
    @Column(name = "ID", scale = 0)
    public Long getID() {
        return id;
    }

`

I have such annotations in several places:
` 

 @ManyToOne(targetEntity = SessionType.class, cascade = {
        CascadeType.ALL
    })
    @JoinColumns({
        @JoinColumn(name = "SESSIONTYPE_APPOINTMENT_ID"),
        @JoinColumn(name = "SESSIONTYPE_APPOINTMENT_HJID")
    })
    public SessionType getSessionType() {
        return sessionType;
    }

`

I think this is the reason of an exception.

All code is available here - [bitbucket repository][1] https://bitbucket.org/sergiishapoval/mindbodyintegrationtestproject/src/179b133cf3a730c718de329c694b311347e16984/?at=mindbodyPrototype 

完整的堆栈跟踪 -

Execution default of goal org.codehaus.mojo:hibernate3-maven-plugin:2.2:hbm2ddl failed: [PersistenceUnit: integration.mindbody] Unable to c
onfigure EntityManagerFactory
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:224)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
        at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:116)
        at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:80)
        at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:51)
        at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:120)
        at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:347)
        at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:154)
        at org.apache.maven.cli.MavenCli.execute(MavenCli.java:582)
        at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:214)
        at org.apache.maven.cli.MavenCli.main(MavenCli.java:158)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:483)
        at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
        at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
        at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
        at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)
Caused by: org.apache.maven.plugin.PluginExecutionException: Execution default of goal org.codehaus.mojo:hibernate3-maven-plugin:2.2:hbm2ddl failed: [Pe
rsistenceUnit: integration.mindbody] Unable to configure EntityManagerFactory
        at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:143)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:208)
        ... 19 more
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: integration.mindbody] Unable to configure EntityManagerFactory
        at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:265)
        at org.codehaus.mojo.hibernate3.configuration.JPAComponentConfiguration.createConfiguration(JPAComponentConfiguration.java:28)
        at org.codehaus.mojo.hibernate3.configuration.AbstractComponentConfiguration.getConfiguration(AbstractComponentConfiguration.java:51)
        at org.codehaus.mojo.hibernate3.exporter.Hbm2DDLExporterMojo.doExecute(Hbm2DDLExporterMojo.java:87)
        at org.codehaus.mojo.hibernate3.HibernateExporterMojo.execute(HibernateExporterMojo.java:152)
        at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:132)
        ... 20 more
Caused by: org.hibernate.AnnotationException: Unable to define/override @Id(s) on a subclass: integration.mindbody.Appointment
        at org.hibernate.cfg.AnnotationBinder.bindId(AnnotationBinder.java:1860)
        at org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:1279)
        at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:754)
        at org.hibernate.cfg.AnnotationConfiguration.processArtifactsOfType(AnnotationConfiguration.java:546)
        at org.hibernate.cfg.AnnotationConfiguration.secondPassCompile(AnnotationConfiguration.java:291)
        at org.hibernate.cfg.Configuration.buildMappings(Configuration.java:1148)
        at org.hibernate.ejb.Ejb3Configuration.buildMappings(Ejb3Configuration.java:1226)
        at org.hibernate.ejb.EventListenerConfigurator.configure(EventListenerConfigurator.java:173)
        at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:854)
        at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:191)
        at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:253)
        ... 25 more

这应该确实有效,这里是 one example from tests

理论:

  • 根本没有应用自定义。
  • hj:id应用于错误的ID。您似乎有几个元素与 XPath 表达式匹配。尝试更具体,即将复杂类型的名称添加到 XPath 表达式。
  • 你有 nillable="true"。也许您会生成一个额外的包装器 属性(由于 nillableID 可能是 JAXBContext<Long>)。所以你实际上可能需要自定义生成的属性。这里是 an example.

看到生成的代码可能会给出更多提示,考虑发布它。

披露:我是 Hyperjaxb3 的作者。

Update

我刚成功mvn clean install

问题是您的 XPath //s:element[@name='ID'] 选择了几个 ID 元素,而不是一个。它实际上选择了架构中的所有 ID 元素。

这会与继承自其他复杂类型的复杂类型发生冲突(例如,MBObject)。父 compex 类型已经有 id(自动生成),但您的自定义点无论如何都要使用 ID 元素作为 id。这会导致问题。看起来 HJ3 试图生成一个复杂的 ID(通过 @IdClass),但这在 Hibernate 中失败了。

解决方法是不覆盖 sub类 中的 id 属性。这可以通过两种方式实现:

  • 仅在非子类(根类)中自定义ID个元素。
  • 自定义父级 类 为 hj:mapped-subclass

我选择了最后一个解决方案并使 MBObjectScheduleItem 映射为 super类:

https://github.com/highsource/hyperjaxb3-support/blob/master/m/MindBody/src/main/wsdl/binding.xml#L60-L65

因此 类 像 Appointment 成为(在 JPA 意义上)层次结构的根并且 id 自定义工作正常(映射的 supper类 没有 id)。所以我得到了一个成功的构建(数据库测试失败但没有破坏构建)。