HQL uses 'only' the property of first child in the where clause - java

I am using #Inheritance ( strategy = InheritanceType.TABLE_PER_CLASS)
The parent class is an abstract class and has two children. Device and System
public abstract class Parent {
#Id
#Column(name = "idParent")
protected int parentId;
abstract public String getManufacturer();
abstract public void setManufacturer(String manufacturer);
abstract public Date getUpdated();
abstract public void setUpdated(Date updated);
}
public class Device extends Parent {
#Column(name = "Device_Manufacturer")
private String manufacturer;
public String getManufacturer() {
return this.manufacturer;
}
public void setManufacturer(String Manufacturer) {
this.manufacturer = manufacturer;
}
#Column(name = "Device_Last_Edit")
private Date updated;
public Date getUpdated() {
return this.updated;
}
public void setUpdated(Date updated) {
this.updated = updated;
}
}
public class System extends Parent {
#Column(name = "System_Manufacturer")
private String manufacturer;
public Date getUpdated() {
return this.updated;
}
public void setUpdated(Date updated) {
this.updated = updated;
}
#Column(name = "System_Last_Edit")
private Date updated;
public Date getUpdated() {
return this.updated;
}
public void setUpdated(Date updated) {
this.updated = updated;
}
}
When I query with where clause
Parent.manufacturer = 'ABC'
, the query generated by HQL queries both children by doing a union of System and Device.
But it applies the where clause to
Device_Manufacturer
only and not on
System.Manufacturer
I tried using
Type(Parent) = System
in the where clause but still HQL generates same SQL

Related

Hibernate. How to select child entities with a several parent fields with writing all it in parent entity

I have a next question: while working with Hibernate 3.3.0 run into a situation when I have two tables with one-to-many relationships and I need to get the list of parents. In each entity must be filled the several fields from the parent table and a list of all children mapped in the parent. For the easiest understanding, I give an example. I have two tables with one-to-many relationships: parent is "recipients" and child is "requisites". And I have two classes whose objects are the rows of these tables. Class for the table of recipients:
#Entity
#Table(name = "recipients")
#JsonFilter(value = "recipientsFilter")
public class POJORecipient implements POJO {
private static final long serialVersionUID = 4436819032452218525L;
#Id
#Column
private long id;
#Version
#Column
private long version;
#Column(name = "client_id")
private long clientId;
#Column
private String inn;
#Column
private String name;
#Column(name = "rcpt_country_code")
private String rcptCountryCode;
#Column(name = "rcpt_passp_ser")
private String rcptPasspSer;
#Column(name = "rcpt_passp_num")
private String rcptPasspNum;
#OneToMany(mappedBy = "recipient", fetch = FetchType.LAZY)
#JsonManagedReference
private Set<POJORequisite> requisites = new HashSet<>();
public POJORecipient(){}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public long getVersion() {
return version;
}
public void setVersion(long version) {
this.version = version;
}
public long getClientId() {
return clientId;
}
public void setClientId(long clientId) {
this.clientId = clientId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getInn() {
return inn;
}
public void setInn(String inn) {
this.inn = inn;
}
public String getRcptCountryCode() {
return rcptCountryCode;
}
public void setRcptCountryCode(String rcptCountryCode) {
this.rcptCountryCode = rcptCountryCode;
}
public String getRcptPasspSer() {
return rcptPasspSer;
}
public void setRcptPasspSer(String rcptPasspSer) {
this.rcptPasspSer = rcptPasspSer;
}
public String getRcptPasspNum() {
return rcptPasspNum;
}
public void setRcptPasspNum(String rcptPasspNum) {
this.rcptPasspNum = rcptPasspNum;
}
public Set<POJORequisite> getRequisites() {
return requisites;
}
public void setRequisites(Set<POJORequisite> requisites) {
this.requisites = requisites;
}
}
and for requisites table:
#Entity
#Table(name = "requisites")
public class POJORequisite implements POJO {
private static final long serialVersionUID = -35864567359179960L;
#Id
#Column
private long id;
#Version
#Column
private long version;
#Column
private String bic;
#Column
private String bill;
#Column
private String comments;
#Column
private String note;
#ManyToOne
#JoinColumn(name = "recipient_id")
#JsonBackReference
private POJORecipient recipient;
public POJORequisite(){}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public long getVersion() {
return version;
}
public void setVersion(long version) {
this.version = version;
}
public String getBic() {
return bic;
}
public void setBic(String bic) {
this.bic = bic;
}
public String getBill() {
return bill;
}
public void setBill(String bill) {
this.bill = bill;
}
public String getComments() {
return comments;
}
public void setComments(String comments) {
this.comments = comments;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
public POJORecipient getRecipient() {
return recipient;
}
public void setRecipient(POJORecipient recipient) {
this.recipient = recipient;
}
}
So, I want to select from the recipients only names and all mapped requisites. Consequently, after the selection, I will have a list of POJORecipient objects and in each object filled only the field "name" and set of POJORequisite objects.
As answer of my question I want to discover one of next: how can I do that with help HQL or Criteria API (the second variant is preferable), or understand it is impossible in Hibernate at all, or that this possibility appeared in later versions (also preferably with example). I'm trying to resolve this question for several months now and will be immensely grateful for any help. All clarifications and advices also will be so helpful. Thanks in advance!!!

PostgreSQL not doing autoincrement

I am using postgresql with springboot. So whenever I am using post method to add a new detail in my table instead of autoincrementing id it's going from 1 to 3. It's taking alternate values rather than consecutive values. I have given following properties and then created table:
spring.jpa.hibernate.ddl-auto=create
Didn't create the table manually. What is the reason for this error? This is my entity class.
#Entity
#Table(name = "NORTHBOUND_SUBSCRIPTION")
public class NBSubscription {
#Id
#GeneratedValue
#Column(name = "nb_id")
private Long nbId;
#Column(name = "DEVICE_FILTER")
private String deviceFilter;
#Column(name = "INTERFACE_FILTER")
private String interfaceFilter;
#ManyToOne
#JoinColumn(name="subscriber_id", referencedColumnName="SUBSCRIBER_ID")
private Subscriber subscriber;
#OneToOne
#JoinColumn(name="sensor_group_id", referencedColumnName="ID")
private SensorGroup sensorGroup;
#Column(name = "EVENT_TYPE")
private String eventType;
#Column(name = "SAMPLING_INTERVAL")
private Integer samplingInterval;
#Column(name = "CREATEAT")
#DateTimeFormat(pattern = "dd-MM-yyyy HH:mm")
private Timestamp createAt;
#Column(name = "MODIFIEDAT")
#DateTimeFormat(pattern = "dd-MM-yyyy HH:mm")
private Timestamp modifiedAt;
#Column(name = "CREATEDBY")
private String createdBy;
#Column(name = "MODIFIEDBY")
private String modifiedBy;
#Column(name = "mark_deletion")
private String markDeletion;
public NBSubscription() {
super();
}
public NBSubscription(Subscriber subscriber, SensorGroup sensorGroup) {
super();
this.subscriber = subscriber;
this.sensorGroup = sensorGroup;
}
public Long getNbId() {
return nbId;
}
public void setNbId(Long nbId) {
this.nbId = nbId;
}
public String getDeviceFilter() {
return deviceFilter;
}
public void setDeviceFilter(String deviceFilter) {
this.deviceFilter = deviceFilter;
}
public String getInterfaceFilter() {
return interfaceFilter;
}
public void setInterfaceFilter(String interfaceFilter) {
this.interfaceFilter = interfaceFilter;
}
#JsonIgnore
public Subscriber getSubscriber() {
return subscriber;
}
public void setSubscriber(Subscriber subscriber) {
this.subscriber = subscriber;
}
public SensorGroup getSensorGroup() {
return sensorGroup;
}
public void setSensorGroup(SensorGroup sensorGroup) {
this.sensorGroup = sensorGroup;
}
public Integer getSamplingInterval() {
return samplingInterval;
}
public void setSamplingInterval(Integer samplingInterval) {
this.samplingInterval = samplingInterval;
}
public String getEventType() {
return eventType;
}
public void setEventType(String eventType) {
this.eventType = eventType;
}
public Timestamp getCreateAt() {
return createAt;
}
public void setCreateAt(Timestamp createAt) {
this.createAt = createAt;
}
public Timestamp getModifiedAt() {
return modifiedAt;
}
public void setModifiedAt(Timestamp modifiedAt) {
this.modifiedAt = modifiedAt;
}
public String getMarkDeletion() {
return markDeletion;
}
public void setMarkDeletion(String markDeletion) {
this.markDeletion = markDeletion;
}
public String getCreatedBy() {
return createdBy;
}
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
public String getModifiedBy() {
return modifiedBy;
}
public void setModifiedBy(String modifiedBy) {
this.modifiedBy = modifiedBy;
}
Try this
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
if it doesn't work, try using the table sequence
#Id
#GeneratedValue(strategy=SEQUENCE, generator="CUST_SEQ")
Your autoincrement is implemented with a sequence, and by default entities share the same sequence, so the autoincrement values get spread across the entities.
You could assign each entity its own sequence. But be aware sequences don't participate in transactions. That means if you have a rollback there will be a break in the numbering. Occasional gaps are not avoidable.
If you are making this sequence visible to users and they expect the numbering to be contiguous, my advice is to not use a sequence for that, and keep the user-visible counter in a field separate from the id. If it is visible to users, then at some point it will need to change, and you can't change ids.

Crudrepository findBy function only works when nothing is found

The first time I implemented the findByContentContaining function in the repository everyting worked fine. But now when I call the function and if it finds something, it gives me an error. If it doesn't find anything it returns an empty list.
This is my repository (everyting works except the findByContentContaining function):
public interface KweetRepo extends CrudRepository<Kweet, Integer> {
Kweet getById(Integer id);
List<Kweet> findTop10ByPosterId(int id);
List<Kweet> findByContentContaining(String content);
List<Kweet> findByPosterId(int id);
}
This is the model for my Kweet class
#Entity
public class Kweet implements Comparable<Kweet>{
#Id
#GeneratedValue
private int id;
#Column(name="content")
private String content;
#JsonFormat(shape = JsonFormat.Shape.STRING)
private Date dateTime;
#ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinColumn(name = "user_id")
private User poster;
#OneToMany(cascade = CascadeType.ALL)
#JoinTable(name="KweetLikedBy")
private List<User> likedBy;
public Kweet() {
}
public Kweet(String content, Date dateTime, User poster, List<User> likedBy) {
this.content = content;
this.dateTime = dateTime;
this.poster = poster;
this.likedBy = likedBy;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Date getDateTime() {
return dateTime;
}
public void setDateTime(Date dateTime) {
this.dateTime = dateTime;
}
public int getPoster() {
return poster.getId();
}
public void setPoster(User poster) {
this.poster = poster;
}
public List<User> getLikedBy() {
return likedBy;
}
public void addLikedBy(User user) {
this.likedBy.add(user);
}
public void removeLikedBy(User user) {
this.likedBy.remove(user);
}
#Override
public int compareTo(Kweet o) {
return getDateTime().compareTo(o.getDateTime());
}
}

Spring Boot Autowiring Problems: Not An Managed Type

I have a repository class:
public interface WorkOrderRepository extends JpaRepository<WorkOrderDTO, Integer> {
#Query(value = "SELECT * FROM (SELECT * FROM workorder) Sub1 INNER JOIN (SELECT wo_number, GROUP_CONCAT(service_type SEPARATOR ', ') AS 'service_types' FROM service_type GROUP BY wo_number) Sub2 ON Sub1.wo_number=Sub2.wo_number WHERE fleet_company_id=?1 AND (order_status='On-Bidding' OR order_status='Draft')")
Collection<WorkOrderDTO> findWorkOrdersByFleet(Long fleetCompanyID);
#Query(value = "SELECT * FROM workorder WHERE fleet_company_id=?1")
Collection<WorkOrderDTO> findWorkOrdersByFleet1(Long fleetCompanyID);
}
And an entity class:
#Entity
#Table(name="workorder")
public class WorkOrder implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="wo_number")
private Long woNumber;
#ManyToOne(optional=false, cascade=CascadeType.ALL)
#JoinColumn(name = "vehicle_id")
private Vehicle vehicle;
#ManyToOne(optional=false, cascade=CascadeType.ALL)
#JoinColumn(name = "fleet_company_id")
private FleetCompany fleetCompany;
#Column(name="order_title")
private String orderTitle;
#Column(name="order_date")
private String orderDate;
#Column(name="order_time")
private String orderTime;
#Column(name="order_status")
private String orderStatus;
#Column(name="ref_number")
private String refNumber;
#Column(name="proposals")
private int proposals;
#Transient
private String serviceTypes;
public WorkOrder() {
super();
}
public Long getWoNumber() {
return woNumber;
}
public void setWoNumber(Long woNumber) {
this.woNumber = woNumber;
}
public String getOrderTitle() {
return orderTitle;
}
public void setOrderTitle(String orderTitle) {
this.orderTitle = orderTitle;
}
public String getOrderDate() {
return orderDate;
}
public void setOrderDate(String orderDate) {
this.orderDate = orderDate;
}
public String getOrderTime() {
return orderTime;
}
public void setOrderTime(String orderTime) {
this.orderTime = orderTime;
}
public String getOrderStatus() {
return orderStatus;
}
public void setOrderStatus(String orderStatus) {
this.orderStatus = orderStatus;
}
public String getRefNumber() {
return refNumber;
}
public void setRefNumber(String refNumber) {
this.refNumber = refNumber;
}
public int getProposals() {
return proposals;
}
public void setProposals(int proposals) {
this.proposals = proposals;
}
public Vehicle getVehicle() {
return vehicle;
}
public void setVehicle(Vehicle vehicle) {
this.vehicle = vehicle;
}
public FleetCompany getFleetCompany() {
return fleetCompany;
}
public void setFleetCompany(FleetCompany fleetCompany) {
this.fleetCompany = fleetCompany;
}
public String getServiceTypes() {
return serviceTypes;
}
public void setServiceTypes(String serviceTypes) {
this.serviceTypes = serviceTypes;
}
}
and I have a pojo that extends the entity class:
public class WorkOrderDTO extends WorkOrder {
private String service_types;
public WorkOrderDTO() {
super();
}
public WorkOrderDTO(String service_types) {
this.service_types = service_types;
}
public String getService_types() {
return service_types;
}
public void setService_types(String service_types) {
this.service_types = service_types;
}
}
I want to pass the POJO WorkOrderDTO to the JpaRepository instead of the entity for it to map column service_types which is not part of the entity class. But I have autowiring problems when I set WorkOrderDTO instead ofWorkOrder. Maybe, it is some annotations problem. I didn't put any annotations to the POJO.
You could use the "new" Operator. You must create a constructor in WorkOrderDTO with the values you need, e.g.
public WorkOrderDTO(String serviceTypes) {
this.service_types = serviceTypes;
}
then you can use it like that in a jpql - query:
#Query(value = "SELECT new your.package.WorkorderDTO(w.<select servicetypes somehow>) FROM workorder w WHERE fleet_company_id=?1")
However, I find your first query confusing, I think it is supposed to be a native query... There you can't use the "new" operator.
Maybe it is possible for you to map the ServiceType like Vehicle or FleetCompany as a List? Then you could concatenate just the values in the List for your DTO.
EDIT: You could use #OneToMany to map a List, as it is probably in your Vehicle class for WorkOrder, just to clarify my previous paragraph.

How to return list of entities when I query to the view

I have two entities that related with One to Many connection. One is Path another is Point, one path can have few points. And I have view on MySQL side that joined those tables using join table. I need to get the result of query to that view. Here is first
#Entity
#Table(name = "paths")
public class Path {
#JsonIgnore
#Id
#Column(name="id")
#GeneratedValue(strategy=GenerationType.AUTO)
private Long pathID;
#Column(name="path_name")
private String pathName;
#Column(name="path_type")
private Long pathType;
#OneToOne(fetch = FetchType.EAGER)
#JoinColumn(name="uid")
#JsonIgnore
private User owner;
#Column(name="path_status")
private Long pathStatus;
#Column(name="description")
private String pathDescription;
#Column(name="created")
private Long created;
#OneToMany(mappedBy = "primaryKey.point", cascade = CascadeType.ALL)
private Set<PathPoints> pathPoints = new HashSet<PathPoints>();
public Long getPathID(){
return this.pathID;
}
public void setPathID(Long pathID){
this.pathID = pathID;
}
public String getPathName(){
return this.pathName;
}
public void setPathName(String pathName){
this.pathName = pathName;
}
public Long getPathType(){
return this.pathType;
}
public void setPathType(Long pathType){
this.pathType = pathType;
}
public Long getPathStatus(){
return this.pathStatus;
}
public void setPathStatus(Long pathStatus){
this.pathStatus = pathStatus;
}
public String getPathDescription(){
return this.pathDescription;
}
public void setPathDescription(String pathDescription){
this.pathDescription = pathDescription;
}
public Long getCreated(){
return this.created;
}
public void setCreated(Long created){
this.created = created;
}
public Set<PathPoints> getPathPoints() {
return pathPoints;
}
public void setPathPoints(Set<PathPoints> pathPoints) {
this.pathPoints = pathPoints;
}
public User getOwner() {
return owner;
}
public void setOwner(User owner) {
this.owner = owner;
}
}
Here is second
#Entity
#Table(name = "path_points")
#AssociationOverrides({
#AssociationOverride(name = "primaryKey.point", joinColumns = #JoinColumn(name = "point_id")),
#AssociationOverride(name = "primaryKey.path", joinColumns = #JoinColumn(name = "path_id"))
})
public class PathPoints{
private PathPointID primaryKey = new PathPointID();
private Long endTime;
private Long startTime;
#Column(name="end_time")
public Long getEndTime() {
return endTime;
}
public void setEndTime(Long endTime) {
this.endTime = endTime;
}
#Column(name="start_time")
public Long getStartTime() {
return startTime;
}
public void setStartTime(Long startTime) {
this.startTime = startTime;
}
#JsonIgnore
#EmbeddedId
public PathPointID getPrimaryKey() {
return primaryKey;
}
public void setPrimaryKey(PathPointID primaryKey) {
this.primaryKey = primaryKey;
}
#Transient
public Point getPoint() {
return primaryKey.getPoint();
}
public void setPoint(Point point) {
this.primaryKey.setPoint(point);;
}
#JsonIgnore
#Transient
public Path getPath() {
return primaryKey.getPath();
}
public void setPath(Path path) {
this.primaryKey.setPath(path);;
}
}
And that is ID class
#Embeddable
public class PathPointID implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private Point point;
private Path path;
#ManyToOne(cascade = CascadeType.ALL)
public Point getPoint() {
return point;
}
public void setPoint(Point point) {
this.point = point;
}
#ManyToOne(cascade = CascadeType.ALL)
public Path getPath() {
return path;
}
public void setPath(Path path) {
this.path = path;
}
}
You need to create third entity class and make jpa/hibernate operations with it.
#Entity
#Table(name = "your_view_name")
public class YourView {
#Column(name="someColumnFromYourView")
private String someColumnFromYourView;
#Transient
private List<Point> points;
...
}
and then do
YourView view = ...//get this view data by some parameters
view.setPoints(yourDaoMethodToGetPoints(view));
you can see this example. I'm using PostgreSQL and JPA 2.1 here.I wrote a view on the database and mapped it to JPA entity.There one thing you need to remember - you cannot do write operations on this view.

Categories

Resources