【发布时间】:2018-02-14 05:15:36
【问题描述】:
我正在努力将 jpa 实体转换为使用 lombok。结果代码如下:
@Entity
@Table(name = "TEST")
@Data
@NoArgsConstructor
@AllArgsConstructor
class Test {
...
@Column(name = "FORMATTING")
@Enumerated(EnumType.ORDINAL)
private FormatType formatType;
...
}
生成的错误消息包含以下内容
Caused by: org.hibernate.HibernateException: Missing column: formatType in TEST
我真的不知道在这里谷歌什么。 (我尝试将 formatType 之前的所有内容粘贴到谷歌 - 没有看到任何内容)
注意:
为了简洁和隐私,已重命名字段并省略了看起来不相关的方面。如果某些东西看起来像一个错字,它可能是。如果您发现了什么,请告诉我,以便我解决。
描述该字段的 3 行与我正在使用的代码没有变化
编辑:
我刚刚在错误消息之前注意到了这一点
13:22:19,967 INFO [org.hibernate.tool.hbm2ddl.TableMetadata] (ServerService Thread Pool -- 57) HHH000261: Table found: TABLE
13:22:19,967 INFO [org.hibernate.tool.hbm2ddl.TableMetadata] (ServerService Thread Pool -- 57) HHH000037: Columns: [..., formatType, ...]
13:22:19,968 ERROR [org.jboss.msc.service.fail] (ServerService Thread Pool -- 57) MSC000001: Failed to start service jboss.persistenceunit."...": org.jboss.msc.service.StartException in service jboss.persistenceunit."...": javax.persistence.PersistenceException: [PersistenceUnit: ...] Unable to build EntityManagerFactory
应该是功能性的
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@Table(name = "PARENT")
public abstract class Parent implements Serializable {
private static final long serialVersionUID = 1;
@Id
@Column(name = "ID")
@GeneratedValue
private long id;
@Column(name = "ENABLED")
private boolean enabled;
}
@Entity
@Table(name = "CHILD")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Child extends Parent {
/** XXX: HERE BE DRAGONS */
@Column(name = "ENUM_1")
@Enumerated(EnumType.STRING)
private Enum1 enum1;
@Column(name = "ENUM_2")
@Enumerated(EnumType.ORDINAL)
private Enum2 enum2;
/** XXX: NO MORE DRAGONS */
@Column(name = "FREQUENCY")
private String frequency;
@Column(name = "EMPTY")
private boolean empty;
@Column(name = "MAX_SIZE")
private int maxSize;
}
public enum Enum1 {
A,
B,
C
}
public enum Enum2 {
X,
Y,
Z
}
我已经回滚了 lombok 更改,我仍然想知道问题是什么,但并不着急。另外,由于这个可爱的小错误,我落后了大约 4 小时,所以我的反应可能有点慢。
子表的 pk 是父表的 fk,没有 lombok,一切似乎都可以工作,尽管 Child 类没有 id。
解决方案:
我完全忘了问这个。不久前,我重新审视了这个问题。为了解释解决方案,让我们看一下我包含的第一个示例的稍微简化的版本。
@Entity
@Table(name = "TEST")
@Setter
@Getter
class Test {
...
@Column(name = "FORMATTING")
@Enumerated(EnumType.ORDINAL)
private FormatType formatType;
...
}
看起来龙目岛会给你这个:
@Entity
@Table(name = "TEST")
class Test {
...
@Column(name = "FORMATTING")
@Enumerated(EnumType.ORDINAL)
private FormatType formatType;
public FormatType getFormatType() {
return formatType;
}
public void setFormatType(FormatType formatType) {
this.formatType = formatType;
}
...
}
请注意,注释仍然附加到 字段。现在,我不确定它是否只是我们正在使用的 JPA 的版本或实现,但我认为如果定义了访问器,jpa 只会忽略除 @Column 之外的任何注释(以及为 @Column 指定的任何参数 -这就是 jpa 查找错误列名的原因)。所以我们实际上需要:
@Entity
@Table(name = "TEST")
class Test {
...
private FormatType formatType;
@Column(name = "FORMATTING")
@Enumerated(EnumType.ORDINAL)
public FormatType getFormatType() {
return formatType;
}
public void setFormatType(FormatType formatType) {
this.formatType = formatType;
}
...
}
在尝试查找示例并填写一些有关 lombok 如何做事的细节(公平地说,我很容易混淆)之后,我发现了这个小宝石:onMethod=@__({@AnnotationsHere})。利用此功能,我想出了以下内容:
@Entity
@Table(name = "TEST")
@Setter
class Test {
...
@Getter(onMethod=@__({
@Column(name = "FORMATTING"),
@Enumerated(EnumType.ORDINAL)
}))
private FormatType formatType;
...
}
然后它就可以工作了。现在我们有了显然是唯一可用的解决方案,我想解决我们目前都在思考的问题:这真的比手动编写方法并在那里附加注释更干净吗?答:……我不知道。我很高兴找到了解决方案。
【问题讨论】:
-
具体什么时候收到错误信息?
-
hibernate 处理持久性信息时
-
发布一个完整的最小示例来重现该问题。发布实际生成的 Java 代码也很有帮助:使用反编译器反编译生成的类,看看它是什么样子。
-
我会努力解决这个问题,但与此同时,我认为这意味着 lombok 不应该有与 jpa 相关的副作用?
-
AFAIK,lombok 只是编译时的东西。