#Formula and PostgreSQL - mysql

I' using Hibernate 5 with PostgreSQL. All is fine but I've a problem with the #Formula annotation.
I've this entity
public class MyImage implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Lob
private byte[] content;
private Boolean favorite;
#ManyToOne
#JoinColumn(name = "father_id", nullable = false, updatable = true, insertable = true)
private Father father;
and this
public class Father implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true,mappedBy = "father")
private Set<MyImage> images;
#Formula("(select ai.content from my_image ai where ai.father_id = id and ai.favorite = 1)")
private byte[] neededBytes;
With MySQL is working fine, but with PostgreSQL I've some SQL Grammar Exception. Testing the #Formula's query inside the SQL editor, seems to be that for PostgreSQL istead of use
ai.favorite = 1
I need to use
ai.favorite = TRUE
but even if I change this query, I always get an SQL Grammar Exception.
Can you help me?

Related

Spring boot, How to perform conditional query on many to many relationship with bridge table?

I have three entity include bridge entity:
Team Entity:
public class Team {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "TEAM_ID")
private Integer id;
#Column(name = "teamname", length = 128, nullable = false, unique = true)
private String teamname;
#Column(name = "delete_date", length = 128, nullable = true)
private Date delete_date;
#Column(name = "description", nullable = true, length = 240)
private String description;
#Column(name = "active", length = 64, nullable = false)
private int active;
#OneToMany(mappedBy = "team", fetch = FetchType.LAZY)
private Set<TeamUsers> team_users = new HashSet<TeamUsers>();
---getter setter constructur
}
User Entity:
#Entity
#Table(name = "tblUsers")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Column(name = "Username", length = 128, nullable = false, unique = true)
private String username;
#Column(name = "FirstName", nullable = false, length = 45)
private String firstName;
#Column(name = "LastName", nullable = false, length = 45)
private String lastName;
#Column(name = "Password", length = 64, nullable = false)
private String password;
#Column(name = "Email", length = 128, nullable = false, unique = true)
private String email;
#Column(name = "Phone", length = 64, nullable = false, unique = true)
private String phoneNumber;
#OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private Set<TeamUsers> team_users = new HashSet<TeamUsers>();
---getter setter constructur
}
TeamUsers - Bridge Entity with extra column(active):
#Entity
#Table(name = "team_users")
public class TeamUsers implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#ManyToOne(fetch = FetchType.LAZY, optional = false, cascade = CascadeType.ALL)
#JoinColumn(name = "TEAM_ID")
private Team team;
#ManyToOne(fetch = FetchType.LAZY, optional = false, cascade = CascadeType.ALL)
#JoinColumn(name = "USER_ID")
private User user;
#Column(name = "active")
private Integer active;
---getter setter constructur
}
In the Team repository I have code:
package com.crmbackend.allService.teamService.repo;
import java.util.List;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.PagingAndSortingRepository;
import com.crmbackend.entity.Team;
public interface TeamRepository extends PagingAndSortingRepository<Team, Integer> {
#Query("select t from Team t")
public List<Team> getAllTeamAndDetails();
}
If I call the getAllTeamAndDetails() method in Junit Test, the result is all team informations:
It basically tells me how many team I have, and team users object who belong to which team.
Now, my question is which I want to get all team information and team user information,
but only their active = 1 in the bridge table.
which means if Team User record has active = 0, then this user should not showing in the result.
How this query should be looks like or what is the best approach?
Thanks
This is not possible with the plain JPA/Hibernate or Spring Data JPA tools available. You have to use a DTO for this purpose. I think this is a perfect use case for Blaze-Persistence Entity Views.
I created the library to allow easy mapping between JPA models and custom interface or abstract class defined models, something like Spring Data Projections on steroids. The idea is that you define your target structure(domain model) the way you like and map attributes(getters) via JPQL expressions to the entity model.
A DTO model for your use case could look like the following with Blaze-Persistence Entity-Views:
#EntityView(Team.class)
public interface TeamDto {
#IdMapping
Integer getId();
String getDescription();
#Mapping("team_users[active = 1].user")
Set<UserDto> getUsers();
#EntityView(User.class)
interface UserDto {
#IdMapping
Integer getId();
String getUsername();
}
}
Querying is a matter of applying the entity view to a query, the simplest being just a query by id.
TeamDto a = entityViewManager.find(entityManager, TeamDto.class, id);
The Spring Data integration allows you to use it almost like Spring Data Projections: https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features
Page<TeamDto> findAll(Pageable pageable);
The best part is, it will only fetch the state that is actually necessary!

Nested one to many relationship jpa spring boot

I have three classes - Document, Page, Sentence. A Document will have multiple Pages & each Page will have multiple Sentences. I'm trying to map One to Many relationship using Spring Data JPA annotation. But it only works when there are only one layer like - Document>Page. Doesn't work while it's Document>Page>Sentence.
Can anyone please give me a solution for how to do it for nested one to many relationship ?
My classes are given below.
#Entity
#Table(name = "DOCUMENT")
public class Document implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "FILEID")
#GeneratedValue(strategy = GenerationType.AUTO)
private long idFile;
#Lob
#Column(name = "CONTENT")
private byte[] content;
#Column(name = "NAME")
private String name;
#Column(name = "ID_MAIL_USER")
private String idMailUser;
#Column(name = "NUM_PAGES")
private int numPages;
#Column(name = "TO_ANALIZE")
private boolean toAnalize;
#Column(name = "HASH")
private String hash;
#Column(name = "EXTENSION")
private String extension;
#Column(name = "SIZE")
private double size;
#Column(name = "LINK_TO_DRIVE_FILE")
private String linkToDriveFile;
#Column(name="PATH")
private String path;
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
#Column(name = "PAGES")
private List<Page> pages = new ArrayList<>();
// Setter Getters
}
.
#Entity
#Table(name = "PAGE")
public class Page implements Serializable {
#Id
#Column(name = "PAGE_ID")
#GeneratedValue(strategy = GenerationType.AUTO)
private long idPage;
#Column(name = "PAGE_NUMBER")
private int pageNum;
#Lob
#Column(name = "CONTENT")
private String content;
#ManyToMany(cascade = CascadeType.ALL)
#Column(name = "SENTENCES")
private List<Sentence> sentences = new ArrayList<>();
// Setter Getters
}
.
#Entity
#Table(name = "SENTENCE")
public class Sentence implements Serializable {
//private long idFile;
//private long idPage;
#Id
#Column(name = "SENTENCE_ID")
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column(name = "PAGE_NUMBER")
private int pageNumber;
#Column(name = "ORDER")
private int ord;
#Column(name = "CONTENT")
private String content;
#Column(name = "HASH")
private String hash;
// Setter Getters
}
Your OneToMany mappings are incorrect. Correct it as follows
#Entity
#Table(name = "DOCUMENT")
public class Document implements Serializable {
......
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
#JoinColumn(name = "DOCUMENT_ID") //Name the foreign key column in PAGE table to DOCUMENT_ID
private List<Page> pages = new ArrayList<>();
}
#Entity
#Table(name = "PAGE")
public class Page implements Serializable {
....
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "PAGE_ID") //Name the forein key column in PAGE table to PAGE_ID
private List<Sentence> sentences = new ArrayList<>();
}
Use #JoinColumn annotation instead of #Column to give the name of the foreign key that do the physical mapping between tables in your database.
#Entity
#Table(name = "DOCUMENT")
public class Document implements Serializable {
private static final long serialVersionUID = 1L;
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy="document")
#Column(name = "PAGES")
private List<Page> pages = new ArrayList<>();
}
#Entity
#Table(name = "PAGE")
public class Page implements Serializable {
#ManyToOne
#JoinColumn(name="DOCUMENT_ID")
private Document document;
#ManyToMany(cascade = CascadeType.ALL, mappedBy="pages")
#Column(name = "SENTENCES")
private List<Sentence> sentences = new ArrayList<>();
}
#Entity
#Table(name = "SENTENCE")
public class Sentence implements Serializable {
#ManyToMany(mappedBy="sentences")
private List<Page> pages;
}
Here a Document One to Many relationship with Pages.
So.. we need define mappedBy in the entity we want to map another entity.. so in this case
#OneToMany(mappedBy="document",cascade = CascadeType.ALL, orphanRemoval = true)
and in referenced entity i.e. Pages we want foreign key DOCUMENT_ID, so we have to define it using
#ManyToOne
#JoinColumn(name="DOCUMENT_ID")

Foreign Keys in Spring Boot (MySQL, Hibernate, JPA)

I am trying to write a RESTful API using Spring Boot and I am not able to figure out a way to map my relations in the database. I have a User and a Reports table. Each User can have multiple Reports, and a single report consists of "FROM USER" and "TO USER" columns to indicate who sent the report and to whom. My User ID is the primary key and for the Report table, I am generating REPORT ID as the primary key using AUTO INCREMENT. Here is my User model class -
#Entity
#Table (name = "user")
#EntityListeners(AuditingEntityListener.class)
public class User {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String firstName;
private String lastName;
private String email;
private String password;
#OneToMany(mappedBy = "user",cascade = CascadeType.ALL)
private List<Report> reportReceivedList;
#OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private List<Report> reportSentList;
/* Getters and setters ..... */
}
Here is my Report Model class -
#Entity
#Table (name = "report")
#EntityListeners(AuditingEntityListener.class)
public class Report {
#Id
#Column (name = "id")
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#ManyToOne()
#JoinColumn(name = "from_user_id")
private Long fromUserId; //THIS SHOULD BE FROM "USER" TABLE
#ManyToOne()
#JoinColumn(referencedColumnName = "to_user_id")
private Long toUserId; //THIS SHOULD BE FROM "USER" TABLE
#Temporal(TemporalType.DATE)
#CreatedDate
private Date createdAt;
private String observation;
private String context;
//Other variables and getters and setters .....
}
Can someone please show me a way to correctly define this relationship. My current model doesn't work. Also, I want rows from REPORT class to be deleted as soon as a user is deleted. Thanks!
I finally fixed it by changing my User class as follows -
#OneToMany(cascade = CascadeType.ALL, targetEntity = Report.class)
#JoinColumn(name = "to_user_id")
private List<Report> reportReceivedList;
#OneToMany(cascade = CascadeType.ALL, targetEntity = Report.class)
#JoinColumn(name = "from_user_id")
private List<Report> reportSentList;
And by changing my Report class as -
#Column(name = "from_user_id")
private Long fromUserId;
#Column(name = "to_user_id")
private Long toUserId;

JPA Hibernate bidirectional relation ends in null pointer

I have 2 entities: Version and Change log.
A Version has N change Logs and a Change Log has one Version.
My Version entity looks like:
#Table(name="change_log_version")
#Entity
public class ChangeLogVersionEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column(name="version")
private String version;
#Column(name="date")
private LocalDateTime date;
#OneToMany(mappedBy = "version", cascade=CascadeType.ALL, fetch =
FetchType.EAGER)
public List<ChangeLogEntity> changeLogEntities;
public void addChangeLog(ChangeLogEntity changeLogEntity) {
this.changeLogEntities.add(changeLogEntity);
changeLogEntity.setVersion(this);
}
...
}
My Change Log entity looks like:
#Table(name="change_log")
#Entity
public class ChangeLogEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column(name="description")
private String description;
#Column(name="added")
private boolean isAdded;
#Column(name="modified")
private boolean isModified;
#Column(name="deleted")
private boolean isDeleted;
#Column(name="public")
private boolean isPublic;
#Column(name="date")
private LocalDateTime date;
#ManyToOne(cascade=CascadeType.ALL, fetch = FetchType.EAGER)
#JoinColumn(name = "version_id")
private ChangeLogVersionEntity version;
...
}
I am kinda new to hibernate and i am stuck in a null pointer by adding a change log to the version. What do i have to change to archive the relation?
Many thanks in advance so far :)
That's because the changeLogEntites List is not initialized.
You should initialize it in the declaration
#OneToMany(mappedBy = "version", cascade=CascadeType.ALL, fetch = FetchType.EAGER)
public List<ChangeLogEntity> changeLogEntities = new ArrayList<>();

com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column in 'field list' using Criteria and mapping annotation

i have criterias to access result by
First Hibernate Dao is
AnswerText answersText = questionManager.getAnswerTextByAnswerIdAndLanguageId(answers.getAnswerId(), 1L);
#Override
public AnswerText getAnswerTextByAnswerIdAndLanguageId(Number answerId,Number languageId) {
Criteria criteria = sessionFactory.getCurrentSession().createCriteria(AnswerText.class);
criteria.add(Restrictions.eq("answer.answerId", answerId));
criteria.add(Restrictions.eq("languageId", languageId));
List<AnswerText> results = criteria.list();
return (results !=null && !results.isEmpty()? results.get(0): null);
}
Answers.java
#Entity
#Table(name = "ANSWERS")
#Cacheable
#JsonIgnoreProperties(ignoreUnknown = true)
public class Answer {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ANSWER_ID")
private Long answerId;
#Column(name = "QUESTION_ID")
private Long questionId;
#Column(name = "DATE_CREATED")
private Timestamp dateCreated;
#Column(name = "CREATED_BY_ID")
private Long creatorId;
#Column(name = "DATE_MODIFIED")
private Timestamp dateModified;
#Column(name = "MODIFIED_BY_ID")
private Long modifierId;
#OneToMany(fetch = FetchType.EAGER,mappedBy = "answer" )
private Set<AnswerText> answerText = new HashSet<AnswerText>();
//getters and setters
AnswerText.java
#Entity
#Table(name = "ANSWERTEXT")
#Cacheable
#JsonIgnoreProperties(ignoreUnknown = true)
public class AnswerText {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ANSWER_TEXT_ID")
private Long answerTextId;
#ManyToOne
#JoinColumn(name="answerId", insertable=false, updatable=false,
nullable=false)
private Answer answer;
#Column(name = "ANSWER_TEXT")
private String answerText;
#Column(name = "LANGUAGE_ID")
private Long languageId;
//getters and setters
When i access the to fetch resultset, it shows below error
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'answertext2_.answerId' in 'field list'
Then i changed to below in
AnswerText.java
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "ANSWER_ID", nullable = false)
private Answer answer;
Answers.java
#OneToMany(fetch = FetchType.EAGER,mappedBy = "answer" )
#Fetch(FetchMode.JOIN)
private Set<AnswerText> answerText = new HashSet<AnswerText>();
This produce no error But fetch results twice on calling
Second HibernateDao call is
List<Answer> answerList = questionManager.getAnswersByQuestionId(Long.parseLong("2"));
System.out.println("answerList :"+answerList1.size());
#Override
public ArrayList<Answer> getAnswersByQuestionId(Number questionId) {
Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Answer.class);
criteria.add(Restrictions.eq("questionId", questionId));
ArrayList<Answer> answerList = (ArrayList) criteria.list();
return answerList;
}
Can Please anyone point me what is going wrong here. PLease help me.
You have done right changing the JoinColumn-name.
Your multiple results in my opinion is bound to:
FetchType.EAGER and the selection of
FetchMode JOIN As indicated you’ll have to worry about duplicated
results. On the other hand JOIN creates the least amount of queries.
In a high latency environment a single JOIN could be considerable
faster then multiple SELECTS. Keep in mind that joining too much data
could put a strain on the database.
from http://www.solidsyntax.be/2013/10/17/fetching-collections-hibernate/
With FetchMode.SELECT you would get the result like you want to have it.