【问题标题】:Hibernate how to map a String field to a numeric columnHibernate如何将字符串字段映射到数字列
【发布时间】:2018-01-16 02:18:07
【问题描述】:

我正在尝试创建一个 SpringBoot 1.5.6 应用程序,该应用程序需要将一些实体存储到 Oracle 12c 数据库中。这些实体仅可作为 Maven 依赖项使用,因此我无法编辑它们的代码。问题是,这些实体使用通过注释映射到整数列的字符串 ID,但是 Hibernate 尝试生成失败的字符串 ID:

org.hibernate.id.IdentifierGenerationException: Unknown integral data type for ids : java.lang.String

我解决这个问题的方法是用 orm.xml 文件覆盖注释并告诉 Hibernate 使用 Oracle 身份特性。但是现在它尝试将 Identity 列创建为 varchar2 所以我无法测试这是否有效。我尝试搜索如何指定列定义并找到“type”和“sql-type”,但这似乎不起作用。 如何使用 orm.xml 文件将实体的字符串字段映射到 Oracle 中的标识列? Hibernate 甚至可以自动将 Identity 转换为 String 吗?

到目前为止我的 orm.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm    
http://java.sun.com/xml/ns/persistence/orm_1_0.xsd"
    version="1.0">
    <entity class="org.owasp.appsensor.core.Attack" name="ATTACK">
        <attributes>
            <id name="id" type="string">
            <column name="id" sql-type="number"/>
                <generated-value strategy="IDENTITY" />
            </id>
        </attributes>
    </entity>
</entityMapping>

其中一个实体(我无法编辑):

package org.owasp.appsensor.core;

import java.util.ArrayList;
import java.util.Collection;

import javax.persistence.*;

import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.owasp.appsensor.core.rule.Rule;
import org.owasp.appsensor.core.util.DateUtils;

/**
 * An attack can be added to the system in one of two ways:
 * <ol>
 *      <li>Analysis is performed by the event analysis engine and determines an attack has occurred</li>
 *      <li>Analysis is performed by an external system (ie. WAF) and added to the system.</li>
 * </ol>
 *
 * The key difference between an {@link Event} and an {@link Attack} is that an {@link Event}
 * is "suspicous" whereas an {@link Attack} has been determined to be "malicious" by some analysis.
 *
 * @author John Melton (jtmelton@gmail.com) http://www.jtmelton.com/
 */
@Entity
public class Attack implements IAppsensorEntity {

    private static final long serialVersionUID = 7231666413877649836L;

    @Id
    @Column(columnDefinition = "integer")
    @GeneratedValue

    private String id;

    /** User who triggered the attack, could be anonymous user */
    @ManyToOne(cascade = CascadeType.ALL)
    private User user;

    /** Detection Point that was triggered */
    @ManyToOne(cascade = CascadeType.ALL)
    private DetectionPoint detectionPoint;

    /** When the attack occurred */
    @Column
    private String timestamp;

    /**
     * Identifier label for the system that detected the attack.
     * This will be either the client application, or possibly an external
     * detection system, such as syslog, a WAF, network IDS, etc.  */
    @ManyToOne(cascade = CascadeType.ALL)
    private DetectionSystem detectionSystem;

    /**
     * The resource being requested when the attack was triggered, which can be used
     * later to block requests to a given function.
     */
    @ManyToOne(cascade = CascadeType.ALL)
    private Resource resource;

    /** Rule that was triggered */
    @ManyToOne(cascade = CascadeType.ALL)
    private Rule rule;

    /** Represent extra metadata, anything client wants to send */
    @ElementCollection
    @OneToMany(cascade = CascadeType.ALL)
    private Collection<KeyValuePair> metadata = new ArrayList<>();

    public Attack () { }

    public Attack (User user, DetectionPoint detectionPoint, DetectionSystem detectionSystem) {
        this(user, detectionPoint, DateUtils.getCurrentTimestampAsString(), detectionSystem);
    }

    public Attack (User user, DetectionPoint detectionPoint, String timestamp, DetectionSystem detectionSystem) {
        setUser(user);
        setDetectionPoint(detectionPoint);
        setTimestamp(timestamp);
        setDetectionSystem(detectionSystem);
    }

    public Attack (User user, DetectionPoint detectionPoint, String timestamp, DetectionSystem detectionSystem, Resource resource) {
        setUser(user);
        setDetectionPoint(detectionPoint);
        setTimestamp(timestamp);
        setDetectionSystem(detectionSystem);
        setResource(resource);
    }

    public Attack (Event event) {
        setUser(event.getUser());
        setDetectionPoint(event.getDetectionPoint());
        setTimestamp(event.getTimestamp());
        setDetectionSystem(event.getDetectionSystem());
        setResource(event.getResource());
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public User getUser() {
        return user;
    }

    public Attack setUser(User user) {
        this.user = user;
        return this;
    }

    public DetectionPoint getDetectionPoint() {
        return detectionPoint;
    }

    public Attack setDetectionPoint(DetectionPoint detectionPoint) {
        this.detectionPoint = detectionPoint;
        return this;
    }

    public String getTimestamp() {
        return timestamp;
    }

    public Attack setTimestamp(String timestamp) {
        this.timestamp = timestamp;
        return this;
    }

    public DetectionSystem getDetectionSystem() {
        return detectionSystem;
    }

    public Attack setDetectionSystem(DetectionSystem detectionSystem) {
        this.detectionSystem = detectionSystem;
        return this;
    }

    public Resource getResource() {
        return resource;
    }

    public Attack setResource(Resource resource) {
        this.resource = resource;
        return this;
    }

    public Rule getRule() {
        return this.rule;
    }

    public Attack setRule(Rule rule) {
        this.rule = rule;
        return this;
    }

    public Collection<KeyValuePair> getMetadata() {
        return metadata;
    }

    public void setMetadata(Collection<KeyValuePair> metadata) {
        this.metadata = metadata;
    }

    @Override
    public int hashCode() {
        return new HashCodeBuilder(17,31).
                append(user).
                append(detectionPoint).
                append(timestamp).
                append(detectionSystem).
                append(resource).
                append(metadata).
                toHashCode();
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;

        Attack other = (Attack) obj;

        return new EqualsBuilder().
                append(user, other.getUser()).
                append(detectionPoint, other.getDetectionPoint()).
                append(timestamp, other.getTimestamp()).
                append(detectionSystem, other.getDetectionSystem()).
                append(resource, other.getResource()).
                append(metadata, other.getMetadata()).
                isEquals();
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this).
                   append("user", user).
                   append("detectionPoint", detectionPoint).
                   append("rule", rule).
                   append("timestamp", timestamp).
                   append("detectionSystem", detectionSystem).
                   append("resource", resource).
                   append("metadata", metadata).
                   toString();
    }

}

这会在尝试创建架构时产生以下错误:

Hibernate: create table AS_ATTACK (id varchar2(255 char) generated as identity, timestamp varchar2(255 char), detection_point_id varchar2(255 char), detection_system_id varchar2(255 char), resource_id varchar2(255 char), rule_id varchar2(255 char), user_id varchar2(255 char), primary key (id))
14:06:42.880 [main] ERROR o.h.t.h.SchemaExport - HHH000389: Unsuccessful: create table AS_ATTACK (id varchar2(255 char) generated as identity, timestamp varchar2(255 char), detection_point_id varchar2(255 char), detection_system_id varchar2(255 char), resource_id varchar2(255 char), rule_id varchar2(255 char), user_id varchar2(255 char), primary key (id))
 - 14:06:42.881 [main] ERROR o.h.t.h.SchemaExport - ORA-00604: Fehler auf rekursiver SQL-Ebene 1 (= Error on recursive SQL-Level 1)
ORA-06502: PL/SQL: numerischer oder Wertefehler (= numerical or value error)
ORA-06512: in Zeile 17 (= in line 17)
ORA-30675: Identity-Spalte muss einen numerischen Typ aufweisen (= Identity-column must have a numerical type)

【问题讨论】:

    标签: java oracle hibernate spring-boot


    【解决方案1】:

    我通过放弃将字符串 ID 映射到标识列的想法解决了这个问题。对我有用的解决方案是将 varchar2 ID 列与序列和触发器结合使用。

    orm.xml:

    <entity class="org.owasp.appsensor.core.Attack" name="ATTACK">
        <attributes>
            <id name="id">
                <generated-value strategy="IDENTITY" />
            </id>
        </attributes>
    </entity>
    

    【讨论】:

    • 您可以通过单击答案分数下方的灰色勾号将答案标记为解决方案。这将表明它已解决,人们不会浪费时间寻找不同的解决方案。
    猜你喜欢
    • 2016-11-24
    • 2012-09-13
    • 2011-02-10
    • 1970-01-01
    • 1970-01-01
    • 2012-01-23
    • 2017-01-31
    • 2012-08-21
    • 1970-01-01
    相关资源
    最近更新 更多