问题 在Java中生成JAXB类时添加toString,hashCode,equals


我正在尝试使用Java以编程方式从XSD文件生成JAXB类。我使用以下代码片段来实现:

....
import java.io.File;
import java.io.IOException;
import org.xml.sax.InputSource;
import com.sun.codemodel.JCodeModel;
import com.sun.tools.xjc.api.S2JJAXBModel;
import com.sun.tools.xjc.api.SchemaCompiler;
import com.sun.tools.xjc.api.XJC;
....
....
public static void generateJaxb(String schemaPath,
                                    String outputDirectory,
                                        String packageName) throws DataLoadingException
{
    try {
        // Setup schema compiler
        SchemaCompiler sc = XJC.createSchemaCompiler();
        sc.forcePackageName(packageName);

        // Setup SAX InputSource
        File schemaFile = new File(schemaPath);
        InputSource is = new InputSource(schemaFile.toURI().toString());

        // Parse & build
        sc.parseSchema(is);
        S2JJAXBModel model = sc.bind();

        JCodeModel jCodeModel = model.generateCode(null, null);
        jCodeModel.build(new File(outputDirectory));
    } catch (IOException exec) {
        LOGGER.error("Error while generating JAXB classes: " + exec);
    }
}

生成的类只包含 getter 这些领域的方法。但是,我想包括 hashCodeequals 和 setter 方法也是如此。生成代码时如何做到这一点?


9337
2017-09-01 14:33


起源



答案:


在Java.net网站上,你会找到 JAXB 2.x Commons项目,它提供了一套共同的 JAXB 实用插件,包括4个应该解决你想要实现的目标:

  1. 等于插件
  2. HashCode插件
  3. Setters插件
  4. ToString插件

还有其他插件可用于覆盖类似的常见方面 Java 域对象。

组态

从一个 XML Schema 配置透视图,您将添加如下所示的引用:

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
    xmlns:basic="http://jaxb2-commons.dev.java.net/basic"
    xmlns:equals="http://jaxb2-commons.dev.java.net/basic/equals"
    xmlns:hashCode="http://jaxb2-commons.dev.java.net/basic/hashCode"
    xmlns:toString="http://jaxb2-commons.dev.java.net/basic/toString"
    jaxb:extensionBindingPrefixes="basic equals hashCode toString">
    <!-- ... -->
</xs:schema>

还有其他可用选项,例如定义在生成时应忽略的对象属性 equals( that ) 实施,a toString() 实施等

Java代码生成

从一个 Java 透视,插件一般都有生成的类实现了 interface;例如,生成的类包含一个 equals( that ) 实施将实施 等于 接口。

插件使用的设计方法通常会产生两种实现方式:

  1. 简单/标准实现,例如 equals( that ) 方法(使用时 Equals Plugin)。
  2. 一个更复杂的实现,包括 locator 和 strategy 参数,允许您实现自定义处理(如果您愿意)。对于这些,您将看到方法签名,例如: equals( thisLocator, thatLocator, that, strategy)

构建/运行

从运行时的角度来看,您必须包含 JAXB2基础知识运行时 jar并提供选项参数,例如: -Xequals-XhashCode, 要么 -XtoString。提供了使用JAXB2 Basics的示例 Ant 和 Maven,如果您正在使用其中任何一个来执行构建,并且提供了更多与构建相关的详细信息 JAXB2基础知识用户指南


10
2017-09-01 16:43



哇,好的答案。小补充:我已将代码移至GitHub: github.com/highsource/jaxb2-basics - lexicore
thnaks @Sean。我知道插件中存在的插件 JAXB2 Basics Runtime jar但无法找到将它们包含在我的代码中的方法,因为它们不是我的代码 com.sun.tools.xjc.Plugin 类。 - Arka Ghosh
@ArkaGhosh他们 是 的子类 Plugin。 - lexicore
@lexicore我不认为有一个SimpleToString插件在工作? - OrangeDog
@OrangeDog不,不 SimpleToString 插入。 - lexicore


答案:


在Java.net网站上,你会找到 JAXB 2.x Commons项目,它提供了一套共同的 JAXB 实用插件,包括4个应该解决你想要实现的目标:

  1. 等于插件
  2. HashCode插件
  3. Setters插件
  4. ToString插件

还有其他插件可用于覆盖类似的常见方面 Java 域对象。

组态

从一个 XML Schema 配置透视图,您将添加如下所示的引用:

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
    xmlns:basic="http://jaxb2-commons.dev.java.net/basic"
    xmlns:equals="http://jaxb2-commons.dev.java.net/basic/equals"
    xmlns:hashCode="http://jaxb2-commons.dev.java.net/basic/hashCode"
    xmlns:toString="http://jaxb2-commons.dev.java.net/basic/toString"
    jaxb:extensionBindingPrefixes="basic equals hashCode toString">
    <!-- ... -->
</xs:schema>

还有其他可用选项,例如定义在生成时应忽略的对象属性 equals( that ) 实施,a toString() 实施等

Java代码生成

从一个 Java 透视,插件一般都有生成的类实现了 interface;例如,生成的类包含一个 equals( that ) 实施将实施 等于 接口。

插件使用的设计方法通常会产生两种实现方式:

  1. 简单/标准实现,例如 equals( that ) 方法(使用时 Equals Plugin)。
  2. 一个更复杂的实现,包括 locator 和 strategy 参数,允许您实现自定义处理(如果您愿意)。对于这些,您将看到方法签名,例如: equals( thisLocator, thatLocator, that, strategy)

构建/运行

从运行时的角度来看,您必须包含 JAXB2基础知识运行时 jar并提供选项参数,例如: -Xequals-XhashCode, 要么 -XtoString。提供了使用JAXB2 Basics的示例 Ant 和 Maven,如果您正在使用其中任何一个来执行构建,并且提供了更多与构建相关的详细信息 JAXB2基础知识用户指南


10
2017-09-01 16:43



哇,好的答案。小补充:我已将代码移至GitHub: github.com/highsource/jaxb2-basics - lexicore
thnaks @Sean。我知道插件中存在的插件 JAXB2 Basics Runtime jar但无法找到将它们包含在我的代码中的方法,因为它们不是我的代码 com.sun.tools.xjc.Plugin 类。 - Arka Ghosh
@ArkaGhosh他们 是 的子类 Plugin。 - lexicore
@lexicore我不认为有一个SimpleToString插件在工作? - OrangeDog
@OrangeDog不,不 SimpleToString 插入。 - lexicore


更新 以下答案不正确。我被界面误导了, generateCode 目前对插件真的没有任何作用。正如@Sidola指出的那样,你应该使用 SchemaCompiler 代替。

除了@SeanMickey的回答,我将解决代码生成问题。

  • 将JAXB2-Basics JAR添加到类路径中。
  • 实例
    • org.jvnet.jaxb2_commons.plugin.tostring.ToStringPlugin
    • org.jvnet.jaxb2_commons.plugin.equals.EqualsPlugin
    • org.jvnet.jaxb2_commons.plugin.hashcode.HashCodePlugin
    • org.jvnet.jaxb2_commons.plugin.setters.SettersPlugin
  • ......或者你需要什么。
  • 将插件传递给 model.generateCode(plugins errorListener) 作为第一个参数。

顺便说一下,为什么要以编程方式生成代码?


4
2017-09-01 21:31



非常感谢@lexicore。这正是我所需要的(儿童) com.sun.tools.xjc.Plugin 类)。 - Arka Ghosh
并回答你的问题 - 我正在尝试构建一个框架,它将XSD作为输入并生成所需的 Entity 用于与Datastax Cassandra交互的类和列族定义。在其中一个步骤中,需要生成JAXB类。 - Arka Ghosh
@ArkaGhosh我之所以要问的是你会得到你需要先编译的Java代码。这通常是在构建中发生的情况,因此通常只有在开发构建工具时才有意义。 - lexicore
@lexicore将插件传递给 generateCode 方法实际上做了什么?今天我解决了这个问题并注意到2.2.11中的JAXBModelImpl没有对该方法中的插件做任何事情,可以看出 这里。我不得不将它们作为选项添加到SchemaCompiler中。 - Sid
@Sidola嗯,你是对的。我被界面误导了。 generateCode 插件真的没有用。 - lexicore