java lombok对jpa有副作用吗

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/46062927/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 09:02:14  来源:igfitidea点击:

does lombok have side effects on jpa

javajpalombok

提问by chrisgotter

I am working on converting a jpa entity to use lombok. The resulting code is the following:

我正在将 jpa 实体转换为使用 lombok。结果代码如下:

@Entity
@Table(name = "TEST")
@Data
@NoArgsConstructor
@AllArgsConstructor
class Test {
   ...
   @Column(name = "FORMATTING")
   @Enumerated(EnumType.ORDINAL)
   private FormatType formatType;
   ...
}

The resulting error message contains the following

生成的错误消息包含以下内容

Caused by: org.hibernate.HibernateException: Missing column: formatType in TEST

I am really not sure what to google here. (I tried pasting everything before formatTypeinto google - didn't see anything)

我真的不知道在这里谷歌什么。(我之前尝试将所有内容粘贴formatType到谷歌中 - 什么也没看到)

NOTE:

笔记:

  1. fields have been renamed and aspects which do not appear relevant have been omitted, for the sake of brevity and privacy. if something looks like a typo, it probably is. please let me know if you notice something so that i can address it.

  2. the 3 lines describing the field are unchanged from the code i'm working with

  1. 为简洁和隐私起见,已重命名字段并省略了看起来不相关的方面。如果有些东西看起来像是打字错误,那可能是。如果您注意到某些事情,请告诉我,以便我可以解决。

  2. 描述该字段的 3 行与我正在使用的代码相同

EDIT:

编辑:

I just noticed this right before the error message

我刚刚在错误消息之前注意到了这一点

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

Should be functional

应该是功能性的

  @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
  }

I have rolled back the lombok changes, I would still like to know what the issue is, but there is no rush. Also, thanks to this lovely little bug i am about 4 hours behind so i may be a little slow on the responses.

我已经回滚了 lombok 的更改,我仍然想知道是什么问题,但不着急。另外,多亏了这个可爱的小错误,我大约落后了 4 个小时,所以我的反应可能有点慢。

The pk of the child table is an fk to the parent table, and without lombok everything appears to work, despite the fact that the Childclass has no id.

子表的 pk 是父表的 fk,如果没有 lombok,一切似乎都可以工作,尽管Child该类没有 id。

SOLUTION:

解决方案:

I completely forgot about asking this. Not long ago I revizited this problem. To explain the solution lets look at a slightly simplified version of the first example i included.

我完全忘记问这个了。不久前,我重新审视了这个问题。为了解释该解决方案,让我们看一下我包含的第一个示例的稍微简化的版本。

@Entity
@Table(name = "TEST")
@Setter
@Getter
class Test {
   ...
   @Column(name = "FORMATTING")
   @Enumerated(EnumType.ORDINAL)
   private FormatType formatType;
   ...
}

It would appear that Lombok will give you this:

看起来 Lombok 会给你这个:

@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;
   }
   ...
}

Note that the annotations are still attached to the field. Now, I am not certain if it is just the version or implementation of JPA that we are using but I gather that if an accessor is defined jpa just ignores any annotations besides @Column(as well as any parameters specified for @Column- which is why jpa was looking for the wrong column name). So we actually need:

请注意,注释仍附加到字段。现在,我不确定它是否只是我们正在使用的 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;
   }
   ...
}

After a great deal of confusion trying to find examples and fill in some specifics regarding how lombok does its thing (to be fair I am very easily confused) i discovered this little gem: onMethod=@__({@AnnotationsHere}). Utilizing this feature I came up with the following:

在试图找到示例并填写有关 lombok 如何做它的事情的一些细节(公平地说我很容易混淆)之后,我发现了这个小宝石:onMethod=@__({@AnnotationsHere}). 利用这个功能,我想出了以下几点:

@Entity
@Table(name = "TEST")
@Setter
class Test {
   ...
   @Getter(onMethod=@__({
         @Column(name = "FORMATTING"),
         @Enumerated(EnumType.ORDINAL)
      }))
   private FormatType formatType;

   ...
}

And presto it works. Now that we have what is apparently the only available solution I would like to address the question we are all pondering at the moment: is that really any cleaner than just writing the method manually and attaching the annotations there? Answer: ... I have no idea. I am just happy I found a solution.

并且很快它就起作用了。现在我们有了显然唯一可用的解决方案,我想解决我们目前都在思考的问题:这真的比手动编写方法并在那里附加注释更干净吗?答:...我不知道。我很高兴我找到了解决方案。

回答by Alexander Yakunin

Its strange. Can you show more code? I'm trying to write a simple project with part of code like in your question and it worked. I used Spring Boot and MySQL. Try to check your configuration. There is my code:

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

Enum:

枚举:

public enum FormatType {

    FIRST_TYPE, SECOND_TYPE
}

Table in MySQL:

MySQL中的表:

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

Entity:

实体:

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;
}

Repository:

存储库:

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

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

Service:

服务:

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();
    }
}

回答by leoconco

Is unlikely that lombok causes runtime problems, as it works on precompile time, you might find useful to decompile the generated code, I sometimes find that the order in which lombok annotations are placed in the source code affect the final result, so, you use @Data and @NoArgsConstructor , I guess you can remove @NoArgsConstructor an try to see if that solves your problem.

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

回答by shaktirath

I faced the same problem with Lombok and JPA but I setup the Lombok and it worked as expected. Below is the code:

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

Controller

控制器

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";
    }

}

Model

模型

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;



}

Repository

存储库

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>{

}