JPA error in kotlin : Class 'Student' should have [public, protected] no-arg constructor - kotlin

Does anyone know how I can solve this problem: 'Class 'Student' should have [public, protected] no-arg constructor'?
It's moaning about the relation to SchoolLesson
import javax.persistence.Entity
import javax.persistence.GeneratedValue
import javax.persistence.GenerationType
import javax.persistence.Id
import javax.persistence.JoinColumn
import javax.persistence.ManyToOne
#Entity
data class Student(
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Long = -1,
#ManyToOne
#NotNull
#JoinColumn(name = "school_lesson_id", referencedColumnName = "id")
val report: SchoolLesson,
)
#EDIT added SchoolLesson on request
import javax.persistence.*
import javax.validation.constraints.NotNull
#Entity
data class SchoolLesson(
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(nullable = false)
val id: Long = -1,
#NotNull
val name: String = "",
)

Never use data classes for #Entities. It causes a bunch of problems later on. Follow best practices listed here: https://www.jpa-buddy.com/blog/best-practices-and-common-pitfalls/.

You can use the no-arg compiler plugin, which will add "an additional zero-argument constructor". Details are in the link.

Do not use #Data, instead declare all the necessary annotations to generate what you need. In this case:
#Entity
#Getter
#Setter
#RequiredArgsConstructor
#NoArgsConstructor
public class SchoolLesson {

when you do not create any constructor for class A but create objects of class A from other place, that time compiler creates a no argument constructor under the hood & executes without error. On the other hand, when you create a constructor having some parameters explicitly but do not create any no arg constructor explicitly with the hope in mind that constructor will create a one for you that time it will give you compile error. So, when you create constructor having some parameters, then you also need to create a no argument constructor explicitly in your class. Ref Links that might help here
Why do we need a default no argument constructor in Java?
https://www.quora.com/Is-it-possible-to-define-a-parameterized-constructor-for-a-class-without-defining-a-parameter-less-constructor-in-Java

You may provide default value for all data class properties:
#Entity
data class Student(
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Long = -1,
#ManyToOne
#NotNull
#JoinColumn(name = "school_lesson_id", referencedColumnName = "id")
val report: SchoolLesson = SchoolLesson()
)

Related

Optaplanner: problems with InverseRelationShadowVariable

have a many-1 relationship pupil-formGroup: pupils are assigned to a formGroup and a formGroup can contain many pupils. I have attempted to implement an InverseRelationShadowVariable having watched your video/tutorial https://www.youtube.com/watch?v=ENKHGBMDaCM (which does not quite correspond with the latest optaplanner documentation I realise)
FormGroup extracts
#Entity
#PlanningEntity
public class FormGroup {
#InverseRelationShadowVariable(sourceVariableName = "formGroup")
#OneToMany(mappedBy = "formGroup", fetch = FetchType.EAGER)
private List<Pupil> pupilList = new ArrayList<Pupil>();
public List<Pupil> getPupilList() {
return pupilList;
}
public Integer getPupilCount() {
return pupilList.size();
}
Pupil extracts
#Entity
#PlanningEntity
public class Pupil
#PlanningVariable(valueRangeProviderRefs = "formGroupRange")
#ManyToOne
private FormGroup formGroup;
Config extracts
<solutionClass>org.acme.optaplanner.domain.Plan</solutionClass>
<entityClass>org.acme.optaplanner.domain.Pupil</entityClass>
<entityClass>org.acme.optaplanner.domain.FormGroup</entityClass>
I believe I've followed the steps in the videoexactly (don't we all say that) but at solve time I get hundreds of errors... Repetitions of the following
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:774)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178)
Any hint gratefully received...
The InverseRelationShadowVariable creates a bi-directional relationship between the genuine planning entity (Pupil) and the planning value (FormGroup). This may become problematic if you re-use your planning domain classes for other purposes, such as ORM persistence or serialization.
In this case, Jackson is unable to serialize Pupil, because it references a FormGroup, which has a List containing a reference back to that Pupil. See? An endless loop.
Solve this issue by adding the #JsonIgnore annotation on top of your inverse relation property and breaking that loop for Jackson:
#Entity
#PlanningEntity
public class FormGroup {
#JsonIgnore // THIS IS THE FIX
#InverseRelationShadowVariable(sourceVariableName = "formGroup")
#OneToMany(mappedBy = "formGroup", fetch = FetchType.EAGER)
private List<Pupil> pupilList = new ArrayList<Pupil>();
public List<Pupil> getPupilList() {
return pupilList;
}
public Integer getPupilCount() {
return pupilList.size();
}
...

Working non-working Hibernate Derby error

I have this very simple entity with the exact same annotations I use prior to adding it to the project. I get the stacktrace below,shown and also, not shown, when adding the FK constaint. The error occurs whether I use the primitive or object for the index. Everything seems correct, can someone edify me? ty.
#Setter
#Getter
#NoArgsConstructor
#Entity
public class User {
#Id
#GeneratedValue
int user_id;
private String name;
private String email;
private String password;
#ManyToMany
#JoinTable(name = "user_role",joinColumns = #JoinColumn(name = "user_id"),inverseJoinColumns = #JoinColumn(name = "role_id"))
private Set<Role> roles;
}
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error
executing DDL "create table user (user_id integer not null, email
varchar(255), name varchar(255), password varchar(255), primary key
(user_id))" via JDBC Statement at
org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:67)
~[hibernate-core-5.4.17.Final.jar:5.4.17.Final]
I know, I know DTFS, Sorry, for the clutter and lost cycles of attention;)

Map values in JPA in native query

I have a spring boot application with JPA.
I need to map a value in a query to entity.
Sample entity
#Entity
#Table(name = "questions")
#DynamicUpdate
public class Question{
#Id
#Column(nullable = false)
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Lob
private String description;
#Transient
private int noOfViews;
}
Sample Query
#Repository
public interface QuestionRepository extends JpaRepository<Question, Long> {
#Query(value = "select q.*, 2 NO_OF_VIEWS from questions q
order by q.id DESC ", countQuery = "select count(*) from questions q order by q.id DESC " ,nativeQuery = true)
Page<Question> findQuestions(Pageable pageable);
}
I need to set the value to noOfViews field. Any idea on this?
Spring has RowMapper interface, but didn't find anything for spring boot.
You may want to look at SqlResultSetMapping Documentation
Also there is a nice example by JPA project. See this example
Excerpt from above link.
JPA 2.1 introduced the new SqlResultSetMapping type ConstructorResult which allows to map columns of a result set row to a constructor invocation which can be nicely used in combination with Value Objects.
TBH, I haven't tried this on #Transient fields but I have used #NamedNativeQuery with Projection DTO.

Hibernate inheritance without table for basic entity

I've never used inheritance in hibernate and I don't know which strategy should I use (or even do I really need to use strategy). I have three tables with the same interface (the same columns) and I want to create three entities with basic interface for them so it will look like this:
#Entity
+ Basic
+ #Entity
#Table(name="TABLE_1")
Table1
+ #Entity
#Table(name="TABLE_2")
Table2
+ #Entity
#Table(name="TABLE_3")
Table3
As you see I don't want to use table for basic entity. If it is possible to do this kind of inheritance, how to do it? Maybe I don't need 'hibernate' inheritance and I should use normal inheritance?
In application it is used like this:
Somewhere in configuration we store information which entity to use (Table1, Table12 or Table3)
Choosen entity is used in our queries (some writen in HQL, some in Criteria) so each query should know which entity to use.
EDIT
What's more each entity can be used as attribute of some entities and we wan't to know which table should be used. For example:
#Entity
#Table(name="USER")
class User {
#Id
private Integer id;
#ManyToOne
#JoinColumn(name = "SOME_ID", referencedColumnName = "ID", nullable = false)
private Basic basicEntity; // how to use proper strategy using some configuration value (eg. class static attribute or configuration value stored in db?)
}
I think this is recommended way of achieving your goal:
#MappedSuperclass
public abstract class BaseEntity {
public static final int SHARED_PAREMETER = 2;
#Column(name = "modified", columnDefinition = "TIMESTAMP DEFAULT NOW()")
protected Date modified;
//... other fields, getters and setters
}
#Entity
#Table(name = "TABLE_1")
public class Table1 {
#Id
private Integer id;
#ManyToOne
#JoinColumn(name = "SOME_ID", referencedColumnName = "ID", nullable = false)
private Table2 table2;
}
#Entity
#Table(name = "TABLE_2")
public class Table2 {
#Id
private Integer id;
}
In this case, we will have only two tables but both would have fields from BaseEntity. You can't, though, make a relation in Entity to an abstract class but in processing you're fully entitled to do something like this:
public void process(BaseEntity entity){
// processing..
}

Synchronize two lucene documents mapped for the same table (entity)

Consider two identical Java entities (PersonM1, PersonM2) mapped for the same table (PERSON) with the same attributes defined as:
#Entity
#Table(name = "PERSON")
#Indexed
public class PersonM1 {
#Id
#DocumentId
private long id;
#Field
#Column
private String name;
//setters, gettes, ...
}
#Entity
#Table(name = "PERSON")
#Indexed
public class PersonM2 {
#Id
#DocumentId
private long id;
#Field
#Column
private String name;
//setters, gettes, ...
}
Is there a way to update PersonM2 indexes when we update a PersonM1 object?
If The object PersonM1 is updated, changes are persisted on the database, but not in PersonM2 index directory, so PersonM2 indexes won't be correct in this case.
Shall I do it manually (update PersonM1 when PersonM2 is updated)?
Note: Java inheritance trick is not relevant!
There is no way currently, as the identity of the indexed type is represented directly the the class instance of the model. This will change in Hibernate Search 5, so in that version you might have a "clean" solution for such a scenario but I don't know yet if we will expose an API for this, and how this would look like. You'll probably have to provide your custom implementation of "entity identity".