Hibernate with Panache - Quarkus - java

I have started to use Hibernate with Panache in my projects.
Basic I have two entities QuestionGroup and Question.
#Entity
#Table(name = "tb006_question_groups")
public class QuestionGroup {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "question_group_id")
#Getter #Setter
private Long id;
#Column(name = "question_group_code")
#Getter #Setter
private String code;
#Column(name = "question_group_name")
#Getter #Setter
private String name;
#CreationTimestamp
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "question_group_createdAt")
#Getter #Setter
private Date createdAt;
#UpdateTimestamp
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "question_group_updatedAt")
#Getter #Setter
private Date updatedAt;
#Column(name = "question_group_enabled")
#Getter #Setter
private Integer enabled;
#OneToMany(mappedBy="questionGroup", cascade = CascadeType.PERSIST)
#Getter #Setter
private List<Question> questions;
#Entity
#Table(name = "tb007_questions")
public class Question {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "question_id")
#Getter #Setter
private Long id;
#Column(name = "question_name")
#Getter #Setter
private String name;
#Column(name = "question_answer")
#Getter #Setter
private String answer;
#CreationTimestamp
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "question_createdAt")
#Getter #Setter
private Date createdAt;
#UpdateTimestamp
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "question_updatedAt")
#Getter #Setter
private Date updatedAt;
#Column(name = "question_enabled")
#Getter #Setter
private Integer enabled;
#ManyToOne
#JoinColumn(name="question_group_id", nullable=false)
#Getter #Setter
private QuestionGroup questionGroup;
This below, the method to insert the datas
#Transactional
#Override
public QuestionGroup createQuestionGroup(QuestionGroupCreateRequestDTO questionGroupCreate) {
QuestionGroup questionGroup =
this.convertQuestionGroupCreateToQuestionGroup(questionGroupCreate);
if (questionGroupCreate.getQuestions() != null) {
List<Question> questions = questionGroupCreate.getQuestions().stream().map(question -> this.convertQuestionCreateToQuestion(question)).collect(Collectors.toList());
questionGroup.setQuestions(questions);
}
questionGroupRepository.persist(questionGroup);
return questionGroup;
}
In my case, the entity QuestionGroup is persist correctly, after that my questions are not persisting and I am receiving this message: Column 'question_group_id' cannot be null
I am imaging the id from QuestionGroup not propagating to Question
How to resolve this problem without persist QuestionGroup and after create the Question objects?

Please initialize your list inside QuestionGroup:
#OneToMany(mappedBy="questionGroup", cascade = CascadeType.PERSIST)
#Getter #Setter
private List<Question> questions = new ArrayList<>();
Inside your QuestionGroup class put a helper method like this:
public void addQuestion(Question question) {
questions.add(question);
question.setQuestionGroup(this);
}
And change this line in your createQuestionGroup:
List<Question> questions = questionGroupCreate.getQuestions().stream().map(question -> this.convertQuestionCreateToQuestion(question)).collect(Collectors.toList());
to:
List<Question> questions = questionGroupCreate.getQuestions().stream().map(question -> {
var questionConverted = this.convertQuestionCreateToQuestion(question);
questionGroup.addQuestion(questionConverted);
}).collect(Collectors.toList());

Related

Convert a Json(Geojson) to WKB in JAVA

I need to convert a geojson to a WKB. Main Entity has now a field "Geojson" which is stored in Database(postgreSQL) as a String and I need another one "Geojson_WKB" or something similarly where I save the converted one.
Main Entity code:
#Getter
#Setter
#ToString
#RequiredArgsConstructor
#Entity
public class MainEntity extends BaseEntity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private int id;
#Column(name = "name")
private String name;
#Type(type = "json")
#Column(name = "geojson", columnDefinition = "jsonb")
private Geojson geojson;
//"Here should be another field with geojson_WKB"
GeoJson entity:
#Getter
#Setter
#ToString
#RequiredArgsConstructor
public class Geojson implements Serializable {
#Column(name = "type")
private String type;
#Type(type = "json")
#Column(name = "feature", columnDefinition = "jsonb")
private List<Feature> features;
}

How to use multiple #Onetoone & #OnetoMany annotation

I'm newbie in Spring boot and making first time an experimental app. This app consist on 3 classes / tables:
Account:
has an account numbers that can be call by JournalEntryDetail, so I get #onetoone relation
JournalEntryMaster:
can have many JournalEntryDetail
I use here #OnetoMany annotation
JournalEntryDetail:
can have one JournalEntryMaster
Foreign key to Account, as Account number should be equal b/w JournalEntDetail & Account table
I get an error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name
'entityManagerFactory' defined in class path resource
[org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation
of init method failed; nested exception is org.hibernate.AnnotationException: #Column(s) not
allowed on a #OneToOne property: com.accounts.entity.JournalEntryMaster.jvNumber
I can understand what does error means but unfortunately I did not find solution, so I came here. Any one could advise will be appreciated.
I copy entities hereunder:
accountnumber
public class Account {
#Id
#GeneratedValue
#Column(name="account_id")
private Long id;
#Column(name="account_number")
private Long accountNumber;
#Column(name="account_name")
private String accountName;
#Enumerated(EnumType.STRING)
#Column(name="dr_or_credit")
private DrOrCrSide drOrCrSide;
#Enumerated(EnumType.STRING)
#Column(name="account_type")
private AccountType accountType;
#ManyToOne(cascade = CascadeType.ALL)
private JournalEntryDetail journalEntryDetail;
JournalEntryMaster
#Entity
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#EqualsAndHashCode
#ToString
public class JournalEntryMaster {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="id")
private Long id;
#OneToOne
#Column(name="jv_number")
private Long jvNumber;
#Column(name="jv_master_date")
private Date Date;
#Column(name="jv_reference_no")
private String ReferenceNo;
#Column(name="memo")
private String Memo;
#Column(name="posted")
private boolean Posted;
#OneToMany(targetEntity = JournalEntryDetail.class, cascade = CascadeType.ALL)
private Set<JournalEntryDetail> journalEntryDetail = new HashSet<>();
}
JourEntryDetail
#Entity
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#EqualsAndHashCode
#ToString
public class JournalEntryDetail {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name="account_number")
private Long accountNumber;
#Enumerated(EnumType.STRING)
#Column(name="jv_detail_drcr")
private DrOrCrSide DrCr;
#Column(name="amount")
private Double Amount;
#Column(name="memo")
private String Memo;
#ManyToOne
#JoinColumn(name = "jv", referencedColumnName = "id")
private JournalEntryMaster jv;
#JoinColumn(name = "account_fk_jv", referencedColumnName = "account_number")
#OneToOne(targetEntity = Account.class, cascade = CascadeType.ALL)
private Account account_number;
#JoinColumn(name = "jvnumber_fk", referencedColumnName = "jv_number")
#OneToOne(targetEntity = JournalEntryMaster.class, cascade = CascadeType.ALL)
private JournalEntryMaster jvNumber;
In
public class JournalEntryMaster {
...
#OneToOne <-- remove this annotation
#Column(name="jv_number")
private Long jvNumber;
You use Long for the jvNumber. If this is just a database column and its not related to an entity, don't use #OneToOne. You can remove the annotation and your error #Column(s) not allowed on a #OneToOne property: com.accounts.entity.JournalEntryMaster.jvNumber will disappear.
On the other hand, if it is related to an entity, you have to use JoinColumn instead of Column and use your EntityClass instead of Long.
Remove #OneToOne from JournalEntryMaster above #Column(name="jv_number") private Long jvNumber and relation of JournalEntryDetail with JournalEntryMaster
is #ManyToOne not #OneToOne. you give two relation together for one table in JournalEntryDetail
remove:
#JoinColumn(name = "jvnumber_fk", referencedColumnName = "jv_number")
#OneToOne(targetEntity = JournalEntryMaster.class, cascade = CascadeType.ALL)
private JournalEntryMaster jvNumber;
Here down modified code:
JournalEntryMaster
#Entity
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#EqualsAndHashCode
#ToString
public class JournalEntryMaster {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="id")
private Long id;
#Column(name="jv_number")
private Long jvNumber;
#Column(name="jv_master_date")
private Date Date;
#Column(name="jv_reference_no")
private String ReferenceNo;
#Column(name="memo")
private String Memo;
#Column(name="posted")
private boolean Posted;
#OneToMany(targetEntity = JournalEntryDetail.class, cascade = CascadeType.ALL)
private Set<JournalEntryDetail> journalEntryDetail = new HashSet<>();
}
JourEntryDetail
#Entity
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#EqualsAndHashCode
#ToString
public class JournalEntryDetail {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name="account_number")
private Long accountNumber;
#Enumerated(EnumType.STRING)
#Column(name="jv_detail_drcr")
private DrOrCrSide DrCr;
#Column(name="amount")
private Double Amount;
#Column(name="memo")
private String Memo;
#ManyToOne
#JoinColumn(name = "jv", referencedColumnName = "id")
private JournalEntryMaster jv;
#JoinColumn(name = "account_fk_jv", referencedColumnName = "account_number")
#OneToOne(targetEntity = Account.class, cascade = CascadeType.ALL)
private Account account_number;

How to handle nullPointer in Spring Data JPA projections

Any thoughts if there's a way to have a custom method for handling null or any other exceptions happening during projection creation?
In the below JPQL query I'm trying to compose a custom object, but when there's no data under column updatedBy (it's null in database) - then it fails internally since cannot proceed with null object any further (getUpdatedBy -> getProfile -> getName).
#Query("select new john.home.com.demo.repository.projections.AgreementType(agreement.name, " +
"agreement.type, " +
"agreement.audit.createdBy.profile.name, " +
"agreement.audit.updateDate, " +
"agreement.audit.updatedBy.profile.name) from Agreement agreement")
List<AgreementType> findAgreementTypes();
Here are my entities:
Agreement:
#Setter
#Getter
#NoArgsConstructor
#Entity
#Table(name = "AGREEMENT")
public class Agreement {
#Id
#Column(name = "AGREEMENT_ID")
private Long id;
#Column(name = "NAME")
private String name;
#Column(name = "TYPE")
private String type;
#Embedded
Audit audit;
Embeddable Audit
#Getter
#Setter
#Embeddable
public class Audit {
#OneToOne
#JoinColumn(name = "CREATED_BY")
private SystemProcess createdBy;
#Column(name = "CREATION_DATE")
private LocalDate creationDate;
#Column(name = "UPDATE_DATE")
private LocalDate updateDate;
#OneToOne
#JoinColumn(name = "UPDATED_BY")
private SystemProcess updatedBy;
SystemProcess:
#Getter
#Setter
#Entity
#Table(name = "sys_process")
public class SystemProcess {
#Id
#Column(name = "PROCESS_ID")
private Integer id;
#Column(name = "PROCESS_MSG_TXT")
private String messageText;
#OneToOne
#JoinColumn(name = "PROFILE_ID")
private SystemProfile profile;
SystemProfile:
#Getter
#Setter
#Entity
#Table(name = "sys_profile")
public class SystemProfile {
#Id
#Column(name = "PROFILE_ID")
private Integer id;
#Column(name = "PROFILE_NM")
private String name;
}
Here's the JPQL query I've used, however it doesn't work due to unknown reason
#Query("select new dan.home.pl.demo.repository.projections.AgreementType(" +
"agreement.name, " +
"agreement.audit.createdBy.profile.name, " +
"case when (agreement.audit.updatedBy is null) then 'Dummy Name' else agreement.audit.updatedBy.profile.name end" +
") from Agreement agreement")
List<AgreementType> findAgreementTypes();
You can use the case statement to achieve this
Check the documentation here
https://docs.jboss.org/hibernate/orm/4.3/devguide/en-US/html/ch11.html
Something like
case when agreement.audit is not null then agreement.audit.updatedBy.profile.name end

How can update list entities like field in another entity?(remove all old and save all new values)

I have 2 entity with MAnyToMany relationship.
#Entity
#Table(name = "PP_CONFIG")
public class PricePlanConfig {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
#Getter #Setter private Long id;
#Getter #Setter private String Name;
#Getter #Setter private String wfaId;
#Getter #Setter private Integer status;
#ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#Getter #Setter private List<PricePlanCrm> ppCrm;
and
#Entity
#Table(name = "PP_CRM")
#EqualsAndHashCode(exclude={"id", "ppConfig"})
public class PricePlanCrm {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Getter #Setter private Long id;
#Getter #Setter private String rkId;
#Getter #Setter private String name;
#Getter #Setter private String priceplantype;
#Getter #Setter private String enabled;
#ManyToMany(mappedBy = "ppCrm")
#Getter #Setter private List<PricePlanConfig> ppConfig;
I want update
#Getter #Setter private List<PricePlanCrm> ppCrm;
And i do it
public void updatePricePlainsToCurrentPricePlaneConfig(){
List<PricePlanCrm> pricePlansClear = getPricePlansClear();
currentPricePlanConfig.setPpCrm(pricePlansClear);
PricePlanCrmDaoImpl.me().merge(currentPricePlanConfig);
}
in pricePlansClear I have 3 new values and in currentPricePlanConfig.setPpCrm() I have 7 old values. Ifter update/merge I want 3 new values in my currentPricePlanConfig. But not happend. I do not have errors but new values not set to currentPricePlanConfig.
If I add new value to current - it added.
But I want remove all old values and set all new values.

Mapping a bidirectional One-to-Many Hibernate Entity with JPA

I am trying to map a bidirectional One-to-Many relationship in Hibernate. In the build logs I receive the error "repeated column in mapping for entity."
What is generating the error?
The entity source code is below. One has a compound primary key. I am using Lombok to generate getters and setters.
The relationship: Award (One) --> AwardReceived (Many)
Award Entity
#Entity
#Table(name = "awards")
#JsonInclude(JsonInclude.Include.NON_NULL)
#Data
public class Award implements Serializable {
#Id
#Column(name = "award_id")
private Long awardId;
#OneToMany(cascade=CascadeType.ALL, mappedBy = "award")
private Set<AwardReceived> awardsReceived;
#Column(name = "award_type")
private String awardType;
#Column(name = "award")
private String award;
#Column(name = "description")
private String description;
}
AwardReceived Entity
#Entity
#Table(name = "awards_received")
#JsonInclude(JsonInclude.Include.NON_NULL)
#Data
public class AwardReceived implements Serializable{
#EmbeddedId
#JsonUnwrapped
private AwardReceivedPk awardReceivedPk;
#ManyToOne(cascade=CascadeType.ALL)
#JoinColumn(name = "award_id")
private Award award;
#Column(name = "award_name")
private String awardName;
#Column(name = "citation")
private String citation;
}
AwardReceivedPk
#Embeddable
#JsonInclude(JsonInclude.Include.NON_NULL)
#Data
public class AwardReceivedPk implements Serializable{
#JsonIgnore
#Column(name = "client_no")
private String clientNo;
#Column(name = "award_id")
private Long awardId;
#Column(name = "year")
private Long year;
}
Please try
#ManyToOne(cascade=CascadeType.ALL)
private Award award;
instead of
#ManyToOne(cascade=CascadeType.ALL)
#JoinColumn(name = "award_id")
private Award award;

Categories