Lombok对jpa有副作用吗?

时间:2017-09-05 20:30:33

标签: java jpa lombok

我正在努力将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

我真的不确定在这里google什么。 (我尝试将formatType之前的所有内容粘贴到谷歌中 - 没有看到任何内容)

注意:

  1. 字段已被重命名,并且为了简洁和隐私,省略了看似不相关的方面。如果看起来像拼写错误,它可能是。如果您发现了我可以解决的问题,请告诉我。

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

  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。

    SOLUTION:

    我完全忘记了这个问题。不久前我复习了这个问题。为了解释这个解决方案,让我们看一下我所包含的第一个例子的略微简化版本。

    @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之外的任何注释(以及为{{指定的任何参数) 1}} - 这就是为什么jpa正在寻找错误的列名称)。所以我们确实需要:

    @Column

    经过大量的混乱,试图找到例子并填写一些关于lombok如何处理它的细节(公平地说我很容易混淆)我发现了这个小宝石:onMethod=@__({@AnnotationsHere})。利用这个功能,我想出了以下内容:

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

    并且它有效。现在我们已经拥有了一个显然唯一可用的解决方案,我想解决这个问题,我们现在都在思考这个问题:除了手动编写方法并在那里附加注释之外,真的更清晰吗?答案:......我不知道。我很高兴我找到了解决方案。

3 个答案:

答案 0 :(得分:2)

奇怪。你能展示更多代码吗? 我试图用你问题中的部分代码编写一个简单的项目并且它有效。我使用了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();
    }
}

答案 1 :(得分:1)

我在使用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>{

}

答案 2 :(得分:0)

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