属性覆盖:具有不同类型的MappedSuperClass属性

huangapple go评论62阅读模式
英文:

AttributeOverride MappedSuperClass attribute with a different type

问题

我有一个作为MappedSuperclass使用的抽象类,如下所示:

@MappedSuperclass
@IdClass(LogId.class)
public abstract class Log {
    private LocalDateTime moment;
    private String pid;
    // attributes omitted
    private String type;
    private String message;

    @Id
    public LocalDateTime getMoment() { return moment; }
    @Id
    public String getPid() { return pid; }
    // getters/setters omitted
}

我的Log类为每个实体提供相同的结构,具有标准属性typemessage。每个实体表示数据库中的一张表,共享每个属性(@Id// omitted部分)。列typemessage可能具有不同的名称和类型。

我的第一个尝试是:

@Entity
@Table(name = "flow_catcher")
public class FlowCatcher extends Log {
    @Override
    @Column(name = "message_type")
    public String getType() {
        return super.getType();
    }

    @Override
    @Column(name = "count")
    @Convert(converter = StringToIntegerDbConverter.class)
    public String getMessage() {
        return super.getMessage();
    }

}

根据这个帖子,我使用了@AttributeOverride,像这样:

@Entity
@Table(name = "flow_catcher")
@AttributeOverride(name = "type", column = @Column(name = "message_type"))
@AttributeOverride(name = "message", column = @Column(name = "count"))
public class FlowCatcher extends Log {

}

但似乎不可能使用任何转换器将count数据作为字符串而不是整数。以下是我的错误日志:

无法构建Hibernate SessionFactory嵌套异常是
org.hibernate.tool.schema.spi.SchemaManagementException:
    Schema-validation: 在表 [flow_catcher] 的列 [count] 中遇到错误的列类型
    发现 [int (Types#INTEGER)]但期望 [varchar(255) (Types#VARCHAR)]

有没有办法将我的count列作为String而不是Integer获取?

附注:Hibernate的hbm2ddl.auto设置为validate,数据库模式无法更改。


编辑 1:我找到了一个有效的解决方案,但它使用了数据库中的另一列other_string_column(未使用),这在我看来不太干净:

@Entity
@Table(name = "flow_catcher")
@AttributeOverride(name = "type", column = @Column(name = "message_type"))
@AttributeOverride(name = "message", column = @Column(name = "other_string_column"))
public class FlowCatcher extends Log{

    private Integer count;

    @Override
    public String getMessage() {
        return this.count.toString();
    }

    public Integer getCount() { return count; }
    public void setCount(Integer count) { this.count = count; }
}
英文:

I have an Abstract class used as MappedSuperclass like :

@MappedSuperclass
@IdClass(LogId.class)
public abstract class Log {
    private LocalDateTime moment;
    private String pid;
    // attributes omitted
    private String type;
    private String message;

    @Id
    public LocalDateTime getMoment() { return moment; }
    @Id
    public String getPid() { return pid; }
    // getters/setters omitted
}

My Log class provides to every entity the same structure with standard attributes type and message. Each entity represents a table in my database which share every attributes (@Id and // omitted ones). Columns type and message might have different names & types.
My first attempt was :

@Entity
@Table(name = "flow_catcher")
public class FlowCatcher extends Log {
    @Override
    @Column(name = "message_type")
    public String getType() {
        return super.getType();
    }

    @Override
    @Column(name = "count")
    @Convert(converter = StringToIntegerDbConverter.class)
    public String getMessage() {
        return super.getMessage();
    }

}

Following this post I used @AttributeOverride like :

@Entity
@Table(name = "flow_catcher")
@AttributeOverride(name = "type", column = @Column(name = "message_type"))
@AttributeOverride(name = "message", column = @Column(name = "count"))
public class FlowCatcher extends Log {

}

But it seems impossible to use any converter to get data count as a String and not an Integer.
Here is my error log:

Unable to build Hibernate SessionFactory; nested exception is
org.hibernate.tool.schema.spi.SchemaManagementException:
    Schema-validation: wrong column type encountered in column [count] in table [flow_catcher];
    found [int (Types#INTEGER)], but expecting [varchar(255) (Types#VARCHAR)]

Is there any way to get my column count as a String and not an Integer ?

PS: Hibernate hbm2ddl.auto is set on validate and database scheme can't change.


EDIT 1: I found a working solution but it uses another (unused) column in my database other_string_column which doesn't sound clean to me :

@Entity
@Table(name = "flow_catcher")
@AttributeOverride(name = "type", column = @Column(name = "message_type"))
@AttributeOverride(name = "message", column = @Column(name = "other_string_column"))
public class FlowCatcher extends Log{

    private Integer count;

    @Override
    public String getMessage() {
        return this.count.toString();
    }

    public Integer getCount() { return count; }
    public void setCount(Integer count) { this.count = count; }
}

答案1

得分: 3

可以使用通用方式

    @MappedSuperclass
    @IdClass(LogId.class)
    public class Log<T extends Comparable> implements Serializable {
         @Id
         private LocalDateTime moment;
         @Id
        private String pid;
        //此处添加所需的附加字段
        
        // 不要指定映射
        private T message;
    
    }
    
    
    @Entity
    @Table(name = "flow_catcher")
    @AttributeOverride(name = "type", column = @Column(name = "message_type"))
    @AttributeOverride(name = "message", column = @Column(name = "count", columnDefinition = "BIGINT(15)"))
    public class FlowCatcher extends Log<Integer> {
        private static final long serialVersionUID = -3629698185247120860L;
    }
    
    
    
    @Entity
    @Table(name = "flow_catcher_another_sample")
    @AttributeOverride(name = "type", column = @Column(name = "message_type"))
    @AttributeOverride(name = "message", column = @Column(name = "message", columnDefinition = "VARCHAR(20)"))
    public class FlowCatcherString extends Log<String> {
        private static final long serialVersionUID = -3629698185247120860L;
    }
英文:

You can go with generic

@MappedSuperclass
@IdClass(LogId.class)
public class Log&lt;T extends Comparable&gt; implements Serializable {
     @Id
     private LocalDateTime moment;
     @Id
    private String pid;
    //additional required fields here
    
    // Do NOT  SPECIFY MAPPING
    private T message;

}


@Entity
@Table(name = &quot;flow_catcher&quot;)
@AttributeOverride(name = &quot;type&quot;, column = @Column(name = &quot;message_type&quot;))
@AttributeOverride(name = &quot;message&quot;, column = @Column(name = &quot;count&quot;, columnDefinition = &quot;BIGINT(15)&quot;))
public class FlowCatcher extends Log&lt;Integer&gt; {
    private static final long serialVersionUID = -3629698185247120860L;
}



@Entity
@Table(name = &quot;flow_catcher_another_sample&quot;)
@AttributeOverride(name = &quot;type&quot;, column = @Column(name = &quot;message_type&quot;))
@AttributeOverride(name = &quot;message&quot;, column = @Column(name = &quot;message&quot;, columnDefinition = &quot;VARCHAR(20)&quot;))
public class FlowCatcherString extends Log&lt;String&gt; {
    private static final long serialVersionUID = -3629698185247120860L;
}

huangapple
  • 本文由 发表于 2020年9月16日 19:51:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/63919475.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定