我的 xsd,如附加文件中所示,报告关系 ROOT 1-->1 标头,但是当我使用 hyperjaxb3 构建项目时,它创建了一个错误的 @ManyToOne 注释,而不是 @OneToOne,因为 xsd 有默认序列约束(1): 创建的代码是:
@ManyToOne(targetEntity = HeaderType.class, cascade = {
CascadeType.ALL
})
@joincolumn(name = "HEADER_ROOT_HJID")
public HeaderType getHeader() {
摘自 XSD:
摘录自 XSD 的文字(针对 rick)
<xs:element name="ROOT">
<xs:complexType>
<xs:sequence maxOccurs="1">
<xs:element name="Header" type="tns:HeaderType" maxOccurs="1"/>
<xs:element name="Data_Block" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="Sensing_Start_Time" type="xs:string"/>
<xs:element name="Sensing_Stop_Time" type="xs:string"/>
<xs:element name="List_of_Acquisitions" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="Acquisition" type="tns:AcquisitionType" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="count" type="xs:int" use="required"/>
</xs:complexType>
</xs:element>
<xs:element name="List_Of_Dumps" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="Dump" type="tns:DumpType" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="count" use="required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="type" type="xs:string" use="required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
HiSrc HyperJAXB Maven Plugin 会生成
@ManyToOne
JPA 注释。这是预期的行为。在没有其他信息的情况下,这种选择提供了外国参考,但不推断所有权。当所有权is存在时,目标实体的生命周期就绑定到源,这是一个更强的选择。
当然,您的设计可以在适当的时候选择将所有权应用于这种类型的关系。要生成
@OneToOne
关系,您可以定义此 JAXB 绑定:
...
<jaxb:bindings node="xs:element[@name='Root']//xs:element[@name='header']">
<hj:one-to-one>
<!-- Optional, custom column name.
<orm:join-column name="HEADER_ROOT_HJID"/>
-->
</hj:one-to-one>
</jaxb:bindings>
...
使用来自 HyperJAXB 命名空间的自定义将上述绑定应用于目标
header
元素。或者,您可以使用 orm
命名空间来自定义 JPA 用于将源实体 Root
连接到目标实体 Header
的数据库列;否则,HyperJAXB 将选择适当的列名称来表示连接。
JAXB 绑定文件 RootHeader.xjb 应用于 XML 模式文件 RootHeader.xsd 以生成 JAXB/JPA 实体。这些类生成为
target/generated-sources/xjc/org/example/root_header/
并包含在类路径中。
下载此 demo (zip) 并将其解压到本地文件夹后,您可以使用两个 JPA 提供程序之一运行测试和/或应用程序:
注意: 该演示是一个独立的 Maven 项目。
mvn -Peclipselink clean test
mvn -Peclipselink clean compile exec:java
或
mvn -Phibernate clean test
mvn -Phibernate clean compile exec:java
此输出显示使用Hibernate的测试结果。
默认情况下,该项目使用本地 H2 数据库。当应用程序创建其
EntityManagerFactory
时,H2 数据库会自动创建。
或者,可以重新配置该项目以使用您自己的 PostgreSQL 数据库服务器。
hisrc-hyperjaxb-maven-plugin 配置为使用提供的 RootHeader.xsd 模式生成 JPA/JAXB 类。该模式提供了命名空间
"http://org.example/root_header"
,JAXB 使用它来使用自己的命名约定创建 Java package
名称。
作为默认选项,使用这些
XJChisrc-basicjaxb-plugins 生成 Java 内置
Object
方法的更高级实现。特别是,示例项目使用 toString
插件来显示未编组的 Root
对象的人类可读表示。
注意: hisrc-hyperjaxb-maven-plugin 扩展了 hisrc-higherjaxb-maven-plugin 但预配置 几个 XJC hisrc-basicjaxb-plugins;因此,运行时类路径需要 hisrc-basicjaxb-runtime 依赖项。有关配置详细信息的更多帮助,请参阅...
mvn hisrc-hyperjaxb:help -Ddetail=true
JUnit 测试类 RoundtripTest.java 扫描示例文件并调用方法
super.checkSample(File samle)
将每个文件提供给测试人员。对于此项目,创建了 EntityManagerFactory
和 JAXBContext
,并且 samples 路径中的每个文件为:
Root
对象Root
对象EntityManager
,em,实例
加载持久化的
Root
Root
对象是否相等Root
对象都被编组以供在日志中查看成功后,每个对象都会被编组用于日志记录和您的审查。
具有
main(...)
方法的 Java 标准引擎应用程序位于 org.example.root_header.Main
。该应用程序使用以下命令执行:
mvn -Peclipselink clean compile exec:java -Dexec.args="src/test/samples/root-header-01.xml"
OR
mvn -Phibernate clean compile exec:java -Dexec.args="src/test/samples/root-header-01.xml"
免责声明:我是HiSrc项目的维护者。
作为 Rick 答案的补充,您可以从高源原始文档中找到以下内容(将在 jaxb-tools 的 github wiki 中反向移植)
一对一映射
您可以使用
自定义元素将复杂的单一属性映射为hj:one-to-one
而不是@OneToOne
:@ManyToOne
来自此处的示例(请参阅前缀的标头声明)
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:jaxb="https://jakarta.ee/xml/ns/jaxb"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
xmlns:hj="urn:hyperjaxb3.jvnet.org:ejb:schemas:customizations"
xmlns:orm="https://jakarta.ee/xml/ns/persistence/orm"
<xs:element name="one-to-one-join-column" type="test:three" minOccurs="0">
<xs:annotation>
<xs:appinfo>
<hj:one-to-one>
<orm:join-column name="O2OJC_THREE_ID"/>
</hj:one-to-one>
</xs:appinfo>
</xs:annotation>
</xs:element>
这将在 JPA 实体之间生成预期的
@OneToOne
关系,代码如下:
@XmlElement(name = "one-to-one-join-column")
protected Three oneToOneJoinColumn;
@OneToOne(targetEntity = Three.class, cascade = {
CascadeType.ALL
})
@JoinColumn(name = "O2OJC_THREE_ID")
public Three getOneToOneJoinColumn() {
return oneToOneJoinColumn;
}
public void setOneToOneJoinColumn(Three value) {
this.oneToOneJoinColumn = value;
}