【问题标题】:does lombok have side effects on jpalombok对jpa有副作用吗
【发布时间】: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 之前的所有内容粘贴到谷歌 - 没有看到任何内容)

注意:

  1. 为了简洁和隐私,已重命名字段并省略了看起来不相关的方面。如果某些东西看起来像一个错字,它可能是。如果您发现了什么,请告诉我,以便我解决。

  2. 描述该字段的 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 只是编译时的东西。

标签: java jpa lombok


【解决方案1】:

这很奇怪。你能显示更多代码吗? 我正在尝试使用您的问题中的部分代码编写一个简单的项目,并且它有效。我使用了 Spring Boot 和 MySQL。尝试检查您的配置。有我的代码:

枚举:

public enum FormatType {

    FIRST_TYPE, SECOND_TYPE
}

MySQL 中的表:

create table TEST
(
    ID int auto_increment primary key,
    FORMATTING int not null
);

实体:

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.*;

@Entity
@Table(name = "TEST")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Test {

    @Id
    @Column(name = "ID")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    @Column(name = "FORMATTING")
    @Enumerated(EnumType.ORDINAL)
    private FormatType formatType;
}

存储库:

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface TestRepository extends JpaRepository<Test, Integer> {
}

服务:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class TestService {

    private TestRepository repository;

    @Autowired
    public TestService(TestRepository repository) {
        this.repository = repository;
    }

    public List<Test> getAllTestEntities() {
        return repository.findAll();
    }
}

【讨论】:

  • 在处理新示例时遇到了一些麻烦。
  • 但是是的,这几乎就是我的示例的目的。感谢您加倍努力
【解决方案2】:

lombok 不太可能导致运行时问题,因为它在预编译时工作,你可能会发现反编译生成的代码很有用,我有时发现 lombok 注释在源代码中的放置顺序会影响最终结果,所以,您使用 @Data 和 @NoArgsConstructor ,我想您可以删除 @NoArgsConstructor 尝试看看是否可以解决您的问题。

【讨论】:

  • 编译时问题
  • 是的,这对我也有用 - 删除了 NoArgsConstructor 和 RequiredArgsConstructor - 我在运行时受到重复的 NotNull 约束定义错误的困扰
【解决方案3】:

我在使用 Lombok 和 JPA 时遇到了同样的问题,但我设置了 Lombok 并且它按预期工作。下面是代码:

控制器

package com.sms.controller;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import com.sms.model.StudentModel;
import com.sms.persistance.StudentRepository;

@RestController
public class StudentController {

    @Autowired
    private StudentRepository sr;

    @PostMapping("/addstudent")
    public String addStudent(@Valid @RequestBody StudentModel studentModel) {
        StudentModel result = sr.save(studentModel);
        return result.equals(null)?"Failed":"Successfully Saved student data";
    }

}

型号

package com.sms.model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

import lombok.Data;
import lombok.RequiredArgsConstructor;

@Data
@RequiredArgsConstructor
@Entity
@Table(name="student", schema="development")
public class StudentModel {

    @Id
    @Column(name="student_id")
    private int id;
    @Column(name="student_name")
    private String studentname;
    @Column(name="student_address")
    private String studentaddress;



}

存储库

package com.sms.persistance;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.sms.model.StudentModel;

@Repository
public interface StudentRepository extends JpaRepository<StudentModel, Integer>{

}

【讨论】:

  • 我已经把@Data放在第一个之前的任何其他JPA注释,不知何故它工作,但我还不确定它是关于实体类中的注释顺序还是它那种间歇性的事情当lombok和JPA一起使用时
猜你喜欢
  • 2013-11-03
  • 2019-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多