how to write this query using hql - mysql

Thi is my query:
SELECT d.fullName,d.doctorId,d.speciality, t.hospital, t.date, t.time
FROM Doctor d, TimeTable t
WHERE d.doctorId = t.doctorId and d.fullName = 'Subash Nisam' and t.date = '2017.03.02'
ORDER BY t.date;
I've two tables->Doctor and TimeTable
#Entity
public class TimeTable {
private int timeTableId;
private String time;
private String date;
private String hospital;
private Doctor doctor;
#Id
#GeneratedValue(strategy = AUTO)
public int getTimeTableId() {
return timeTableId;
}
public void setTimeTableId(int timeTableId) {
this.timeTableId = timeTableId;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getHospital() {
return hospital;
}
public void setHospital(String hospital) {
this.hospital = hospital;
}
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "doctorId", nullable = false)
public Doctor getDoctor() {
return doctor;
}
public void setDoctor(Doctor doctor) {
this.doctor = doctor;
}
}
//////////////////////////////////////////
#Entity
public class Doctor {
private int doctorId;
private String fullName;
private String regNo;
private String designation;
private String speciality;
private String address;
private String contactNo;
private String email;
private String workingTime;
private String password;
private String branch;
---------------------------------------------
#Id
#GeneratedValue(strategy = AUTO)
public int getDoctorId() {
return doctorId;
}
#OneToMany(cascade = CascadeType.ALL, mappedBy = "doctor")
public Set<TimeTable> getTimeTables() {
return timeTables;
}
public void setTimeTables(Set<TimeTable> timeTables) {
this.timeTables = timeTables;
}
}
I want to write my query using hql. hope your help.

Try this syntax:
select d.fullName, d.doctorId, d.speciality, t.hospital, t.date, t.time
from Doctor as d
inner join d.timeTables t
where d.fullName = 'Subash Nisam' and t.date = '2017-03-02'

Try this one
select Doctor.fullname, Doctor.doctorId, Doctor.speciality, TimeTable.hospital, TimeTable.date, TimeTable.time from Doctor inner join TimeTable on Doctor.doctorId =TimeTable.doctorId where Doctor.fullname='Subash' and Timetable.date='2017-03-02' order by Timetable.date;

#Tim Biegeleisen------->
Here is the output
select
doctor0_.doctorId as doctorId1_3_0_,
timetables1_.timeTableId as timeTabl1_5_1_,
doctor0_.address as address2_3_0_,
doctor0_.branch as branch3_3_0_,
doctor0_.contactNo as contactN4_3_0_,
doctor0_.designation as designat5_3_0_,
doctor0_.email as email6_3_0_,
doctor0_.fullName as fullName7_3_0_,
doctor0_.password as password8_3_0_,
doctor0_.regNo as regNo9_3_0_,
doctor0_.speciality as special10_3_0_,
doctor0_.workingTime as working11_3_0_,
timetables1_.date as date2_5_1_,
timetables1_.doctorId as doctorId5_5_1_,
timetables1_.hospital as hospital3_5_1_,
timetables1_.time as time4_5_1_
from
Doctor doctor0_
inner join
TimeTable timetables1_
on doctor0_.doctorId=timetables1_.doctorId
where
doctor0_.fullName='Subash Nisam'
and timetables1_.date='2017.03.02'
It gives all result of the doctor such as fullname, password, address...
but I want to get fullName and doctorId from doctor table and other data from timetable table.

Related

joining multiple entities in Spring JPA

Have Users, Roles and User Roles tables.
Users
id
username
Roles
role_id
role_name
user_roles
user_id (fk users table)
role_id (fk roles table)
I defined my entities this way
user_roles Entity
#Column(name = "USER_ID")
private int userId;
#Column(name = "ROLE_ID")
private int roleId;
#ManyToOne()
#JoinColumn(name="ROLE_ID", insertable = false, updatable = false)
private RoleGroup userRole;
#ManyToOne()
#JoinColumn(name="id", insertable = false, updatable = false)
private User user;
User entity:
#Id
#Column(name="ID")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(name = "USER_NAME")
private String userName;
Roles Entity:
#Id
#Column(name="ROLE_ID")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "ROLE_NAME")
private String roleName;
#OneToMany(targetEntity=UserRoleGroup.class, mappedBy="userRole",cascade=CascadeType.ALL,
fetch = FetchType.LAZY)
private List<UserRoleGroup> userGroup;
User table will store all lists of users. Roles table is the master table which is having 5 rows - (Admin, Read, manager..)
User Role Table will have user_id from user table and role_id from roles table.
Example
USER:
id user_name
1 test#gmail.com
2 abc#gmail.com
Roles
role_id Name
1 Admin
2 Manager
3 Read
User Roles
User_Id Role_ID
1 1
1 2
2 3
Repository
#Query("FROM UserRoleGroup AS urg LEFT JOIN urg.userRole AS ur LEFT JOIN urg.user AS u WHERE u.userName = ?1")
public List<UserRoleGroup> findAllUserRoles(String userName);
No compilation error, no runtime error, but query isn't returning anything whereas I have data in table. when i run query in MySql I am getting data
I was able to get this working with some minor changes to the entity classes and by adding a DTO. I think its not a good practice to pass around the entity to the client. Below is my implementation.
UserRoleGroup
#Entity
#Table#Data
public class UserRoleGroup {
#EmbeddedId
private UserRoleId id;
#ManyToOne(fetch = FetchType.LAZY)
#MapsId("userId")
private User user;
#ManyToOne(fetch = FetchType.LAZY)
#MapsId("roleId")
private Role role;
}
UserRoleId
#Embeddable
public static class UserRoleId implements Serializable {
private static final long serialVersionUID = 1L;
#Column(name = "user_id")
private Integer userId;
#Column(name = "role_id")
private Integer roleId;
public UserRoleId() {
}
public UserRoleId(Integer userId, Integer roleId) {
super();
this.userId = userId;
this.roleId = roleId;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public Integer getRoleId() {
return roleId;
}
public void setRoleId(Integer roleId) {
this.roleId = roleId;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
UserRoleId that = (UserRoleId) o;
if (!userId.equals(that.userId)) return false;
return roleId.equals(that.roleId);
}
#Override
public int hashCode() {
int result = userId.hashCode();
result = 31 * result + roleId.hashCode();
return result;
}
}
User
import javax.persistence.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
/**
* user can have roles
* */
#Entity
#Table
public class User {
#Id
#Column(name="id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Column(name = "username")
private String userName;
#OneToMany(mappedBy = "user",
cascade = CascadeType.ALL,
orphanRemoval = true)
private Set<UserRoleGroup> roles = new HashSet<>();
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Set<UserRoleGroup> getRoles() {
return roles;
}
public void setRoles(Set<UserRoleGroup> roles) {
this.roles = roles;
}
}
Role
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
#Entity
#Table(name = "roles")
public class Role {
#Id
#Column(name="id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Column(name = "role_name")
private String roleName;
#OneToMany(mappedBy="role",
cascade=CascadeType.ALL,
fetch = FetchType.LAZY)
private List<UserRoleGroup> users = new ArrayList<>();
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
public List<UserRoleGroup> getUsers() {
return users;
}
public void setUsers(List<UserRoleGroup> users) {
this.users = users;
}
}
UserGroupRepository
import com.chait.json.generate.entity.UserRoleGroup;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
#Repository
public interface UserGroupRepository extends JpaRepository<UserRoleGroup,Integer> {
#Query(
"FROM UserRoleGroup AS urg LEFT JOIN urg.role AS ur LEFT JOIN urg.user AS u WHERE u.userName = ?1"
)
List<UserRoleGroup> findAllUserRoles(#Param("userName") String userName);
}
UserRoleDTO
#Data
#AllArgsConstructor
public class UserRoleDTO {
private String username;
private Set<String> roles;
}
UserRestController
#RestController
#RequestMapping("/users")
#RequiredArgsConstructor
public class UserRestController {
private final UserGroupRepository userGroupRepository;
#GetMapping("/{username}")
public ResponseEntity<UserRoleDTO> getUserRoleByUsername(
#PathVariable("username") String username
) {
List<UserRoleGroup> userRoleGroups = userGroupRepository.findAllUserRoles(username);
return ResponseEntity.ok(
new UserRoleDTO(
userRoleGroups.get(0).getUser().getUserName(),
userRoleGroups
.stream()
.map(UserRoleGroup::getRole)
.map(Role::getRoleName)
.collect(Collectors.toSet())
)
);
}
}

Trouble executing an JPQL query

I'm working with spring boot entity manger using JPQL with queries.
The following query is working correctly:
SELECT h, uh FROM Hour h, UserHour uh
But now I want to get a single result for which I use the query:
SELECT h FROM Hour h INNER JOIN UserHour uh WHERE uh.userId = 1
But then the results are zero, which is not expected.
But, when I use the SQL query:
SELECT * FROM hour
INNER JOIN user_hour
ON user_hour.hour_id = hour.hour_id
WHERE user_hour.user_id = '1'
I get the result I want.
Please help me out.
EDIT:
List<Object> result = entityManager.createQuery(
"select distinct hr " +
"from Hour hr " +
"join hr.users hu " +
"where hu.id = :userID")
.setParameter( "userID", 1)
.getResultList();
System.out.println(result);
User Entity:
package com.timely.backend.models;
import javax.persistence.*;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
#Entity
#Table(name = "USER")
public class User implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String username;
private String password;
private String fullname;
private String email;
private String creation_date;
// user roles
#ElementCollection(targetClass = Role.class, fetch = FetchType.EAGER)
#CollectionTable(name = "user_role", joinColumns = #JoinColumn(name = "user_id"))
#Enumerated(EnumType.STRING)
private Set<Role> roles;
#ManyToMany(cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
})
#JoinTable(name = "user_hour",
joinColumns = #JoinColumn(name = "userId"),
inverseJoinColumns = #JoinColumn(name = "hourId")
)
private List<Hour> hours = new ArrayList<>();
public User() {
}
public User(String username, String password, String fullname, String email, String creation_date) {
this.username = username;
this.password = password;
this.fullname = fullname;
this.email = email;
this.roles = getRoles();
this.creation_date = creation_date;
}
//If user is admin
public boolean isAdmin() {
return roles.contains(Role.ADMIN);
}
//region Getters & Setters
public void setId(int id) {
this.id = id;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
public void setFullname(String fullName) {
this.fullname = fullName;
}
public void setEmail(String email) { this.email = email; }
public void setRoles(Set<Role> roles) { this.roles = roles; }
public void setCreation_date(String creation_date) { this.creation_date = creation_date; }
public int getId() { return id; }
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public String getFullname() {
return fullname;
}
public String getEmail() { return email; }
public Set<Role> getRoles() { return roles; }
public String getCreation_date() { return creation_date; }
//endregion
}
UserHour Entity:
package com.timely.backend.models;
import javax.persistence.*;
#Entity
#Table(name = "user_hour")
public class UserHour {
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public int getHourId() {
return hourId;
}
public void setHourId(int hourId) {
this.hourId = hourId;
}
public UserHour(int userId, int hourId) {
this.userId = userId;
this.hourId = hourId;
}
public UserHour(){
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private int userId;
private int hourId;
}
Hour Entity:
package com.timely.backend.models;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
#Entity
#Table(name = "HOUR")
public class Hour {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int hourId;
private String date;
private String startTime;
private String endTime;
public Hour(int hourId, String date, String startTime, String endTime) {
this.hourId = hourId;
this.date = date;
this.startTime = startTime;
this.endTime = endTime;
}
public Hour(){
}
#ManyToMany(mappedBy = "hours")
private List<User> users = new ArrayList<>();
public int gethourId() {
return hourId;
}
public void sethourId(int hourId) {
this.hourId = hourId;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getStartTime() {
return startTime;
}
public void setStartTime(String startTime) {
this.startTime = startTime;
}
public String getEndTime() {
return endTime;
}
public void setEndTime(String endTime) {
this.endTime = endTime;
}
}
MySQL query working:
SELECT id, date, start_time, end_time FROM hour
JOIN user_hour
ON user_hour.hour_id = hour.hour_id
WHERE user_hour.user_id = '1'
Problem:
User Table:
UserHour Table:
Hour Table:

Spring Boot Data JPA - how to get data for the certain id

I have two tables Ticket and Flight. One flight could have many tickets.
I want to show fields departure_date, destination_date from the table Flight and name, surname from the table Ticket. And show data only for the certain flight_id. I use findBy method.
Entity Flight
#Entity
#Table(name = "flight")
public class Flight {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer flight_id;
#Column(name = "departureDate")
private Date departureDate;
#Column(name = "destinationDate")
private Date destinationDate;
#OneToMany(mappedBy = "flight")
#JsonManagedReference("flight")
private List<Ticket> tickets;
Entity Ticket
#Entity
#Table(name = "ticket")
public class Ticket {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int ticket_id;
#Column(name = "name")
private String name;
#Column(name = "surname")
private String surname;
#ManyToOne(targetEntity = Flight.class)
#JoinColumn(name = "flight_id")
#JsonBackReference("flight")
#Fetch(FetchMode.JOIN)
private Flight flight;
I've created file FlightsTicketDto with certain fields:
public class FlightTicketDto {
private Integer flight_id;
private Date departureDate;
private Date destinationDate;
private String name;
private String surname;
public FlightTicketDto() {
}
public FlightTicketDto(Integer flight_id, Date departureDate, Date destinationDate, String name, String surname) {
this.flight_id = flight_id;
this.departureDate = departureDate;
this.destinationDate = destinationDate;
this.name = name;
this.surname = surname;
}
FlightTicketRepository with my Query
public interface FlightTicketRepository extends JpaRepository<Ticket, Integer> {
#Query("SELECT new pl.edu.wat.dto.FlightTicketDto(f.flight_id, f.departureDate, f.destinationDate, t.name, t.surname) "
+ "FROM Flight f INNER JOIN f.tickets t")
List<FlightTicketDto> findByFlightId(Integer flight_id);
}
FlightTicketController
#CrossOrigin(origins = "http://localhost:4200")
#RestController
#RequestMapping("/api")
public class FlightTicketController {
#Autowired
FlightTicketRepository flightTicketRepository;
#GetMapping("/mytickets/{flight_id}")
public List fetchEmpDeptDataInnerJoin(#PathVariable Integer flight_id) {
return flightTicketRepository.findByFlightId(flight_id);
}
Actually whatever flight_id (even not flight_id, but just another number) I write, I've got all my flights
For example I want to get result only for flight_id = 431, result you can see on the picture. What's wrong?
replace
#Query("SELECT new pl.edu.wat.dto.FlightTicketDto(f.flight_id, f.departureDate, f.destinationDate, t.name, t.surname) "
+ "FROM Flight f INNER JOIN f.tickets t")
List<FlightTicketDto> findByFlightId(Integer flight_id);
with
#Query("SELECT new pl.edu.wat.dto.FlightTicketDto(f.flight_id, f.departureDate, f.destinationDate, t.name, t.surname) "
+ "FROM Flight f INNER JOIN f.tickets t where f.flight_id = :flight_id")
List<FlightTicketDto> findByFlightId(#Param("flight_id") Integer flight_id);

The boolean value of the objects coming from a Query is wrong

I have this activity_company table which includes an activity and company. I am trying to order the result of this query by modified_date and id. And in the activity table there is a boolean field such as shared. All the shared values are false in the database but after this query the resulted objects' shared fields are displayed as true even if they are still false in the DB. Any idea what causes this situation ?
SELECT activity.*
FROM activity
INNER JOIN activity_company ON activity.id=activity_company.activity_id
WHERE activity_company.company_id=1
ORDER BY activity.modified_date, activity.id
This is the activity class;
#Entity
public class Activity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(columnDefinition = "TEXT")
private String param;
private Date createdDate;
private int activityType;
private long classNameId;
private long classPK;
private Date modifiedDate;
private boolean shared;
#ManyToOne
private User creatorUser;
#ManyToOne
private Company creatorCompany;
#OneToMany(mappedBy = "activity")
private List<ActivityCompany> activityCompanies = new ArrayList<ActivityCompany>();
#OneToMany(mappedBy = "activity")
private List<ActivityAttachment> activityAttachments;
public Activity(String param, User user, int activityType) {
this.param = param;
this.createdDate = new Date();
this.activityType = activityType;
this.creatorUser = user;
this.modifiedDate = new Date();
}
and activitycompany;
#Entity
public class ActivityCompany {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#ManyToOne
private Activity activity;
#ManyToOne
private Company company;
public Activity getActivity() {
return activity;
}
public void setActivity(Activity activity) {
this.activity = activity;
}
public Company getCompany() {
return company;
}
public void setCompany(Company company) {
this.company = company;
}
public Long getId() {
return id;
}
}

How to rewrite given query in jpql custom query?

I have a mysql query which look like this:
SELECT * FROM `HOST` WHERE `DATE_OF_SCAN` between
(SELECT subtime((Select max(`DATE_OF_SCAN`) from `HOST` ), '0 0:5:0'))
and
(Select max(`DATE_OF_SCAN`) from `HOST` );
which basically is returning hosts from range of max date in table and (max date - 5 min).
I'm trying to rewrite it in the jpql:
#Query("SELECT h FROM Host h WHERE h.date between "
+ "(SELECT subtime((Select max(ho.date) from Host ho ), 0 0:5:0)) "
+ "and (Select max(hos.date) from Host hos)")
public List<Host> findHosts();
but it is constantly throwing exception:
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: 0 near line 1, column 126 [SELECT h FROM com.iie.model.Host h WHERE h.date between (SELECT subtime((Select max(ho.date) from com.iie.model.Host ho ), 0 0:5:0)) and (Select max(hos.date) from com.iie.model.Host hos)]
at org.hibernate.hql.internal.ast.QuerySyntaxException.convert(QuerySyntaxException.java:54)
at org.hibernate.hql.internal.ast.QuerySyntaxException.convert(QuerySyntaxException.java:47)
at org.hibernate.hql.internal.ast.ErrorCounter.throwQueryException(ErrorCounter.java:79)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:276)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:180)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:136)
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:101)
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:80)
at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:119)
at org.hibernate.internal.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:214)
at org.hibernate.internal.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:192)
at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:1537)
at org.hibernate.ejb.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:285)
finally. I've tried to pass the '0 0:5:0' as a parameter, but it throws an exception that this is not a proper Joda DateTime format.
The Host:
#Entity
#Table(name = "HOST")
public class Host {
#Id
#GeneratedValue
#Column(name = "HOST_ID")
private Long id;
#Column(name = "HOSTNAME")
private String hostname;
#Column(name = "IP")
private String ip;
#Column(name = "DATE_OF_SCAN")
#Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTime")
private DateTime date;
public Host(Long id, String hostname, String ip, DateTime date) {
this.id = id;
this.hostname = hostname;
this.ip = ip;
this.date = date;
}
public Host(String hostname, String ip, DateTime date) {
this.hostname = hostname;
this.ip = ip;
this.date = date;
}
public Host() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getHostname() {
return hostname;
}
public void setHostname(String hostname) {
this.hostname = hostname;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public DateTime getDate() {
return date;
}
public void setDate(DateTime date) {
this.date = date;
}
this part is not valid SQL
SELECT h FROM Host h
I suggest changing to explicit column names
SELECT h.mycolumn FROM Host h