I am working on converting a jpa entity to use lombok. The resulting code is the following:
@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 formatType
into google - didn't see anything)
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.
the 3 lines describing the field are unchanged from the code i'm working with
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
@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.
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 Child
class has no 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:
@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:
@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:
@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.
Since all the dependency to Lombok is unidirectional i.e. classes depends on Lombok but Lombok doesn't directly depend on the classes, it doesn't create the real tight coupling. Also the compiled code is finally Lombok free hence making it safe to use.
Conclusion. The Lombok library was created to make Java an easier language in which to code. It takes some of the most common boilerplate headaches out of the developer's task list. It can be useful for making your code more concise, reducing the chance for bugs, and speeding up development time.
Spring data jpa- it is same like jpa means we can describe in below way. Spring Data Jpa is jpa data abstraction access which means it likes a jpa but it add some extra functionality, Without jpa we can not implement the spring data jpa.
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:
Enum:
public enum FormatType {
FIRST_TYPE, SECOND_TYPE
}
Table in 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();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With