hibernate define class from multiple columns in multiple tables - sql

i have a class with some datafields:
class Call{
roomId
roomDisplay
roomLocation
typeId
name
staffAidId
}
now i would like to map this using hibernate annotations in java
but the original sql query that i used was something like this:
SELECT
c.roomId,
r.display,
r.location,
c.typeId,
c.staffAidId,
s.firstname,
s.lastname
FROM callalert c
JOIN staffmember s
LEFT JOIN roomGroup g ON g.groupId = s.roomGroupId
LEFT JOIN room r ON r.roomId = g.roomId
WHERE s.staffId = 4444 AND c.roomId = g.roomId
is there a way to map this
in other words:
is there a way to map columns from different tables to 1 custom class?
the class is no direct representation of 1 table
and from all the tables that are involved, not all columns are used
edit
I tried the view solution:
created a view with the above query
then I try to generate the hibernate classes using Netbeans
and I generates 2 classes:
the class Calls and an Embeddable class CallId
after searching the Internet this happens because hibernate needs a primary key so it creates one himself
how can I make sure only 1 class gets generated?
how do I give a view a primary key (a good primary key would be 1 of the primary keys of the underlying tables). how do i set this?

You should be able to do that if you create a database view for that query. It would work, but it has the downside that you can't auto-generate the ddl schema from the database models.
Check out this article

Related

Select query, join table which is not directly referenced via Foreign Key

With Prisma, I'm trying to join an indirectly referenced table onto a query, see SQL example below which represents the basic use case.
Lets say in the example, that I want to access the companyCar table from the companyUser table. I can think of 2 ways to do this, via joining using the company table, or by directly comparing the companyId of the 2 tables
option 1, follows foreign key references
SELECT * FROM CompanyUser companyuser
JOIN Company company on company.Id = companyuser.companyId
JOIN CompanyCar companycar on companycar.companyId = company.Id
option 2, does not directly follow foreign key references
SELECT * FROM companyUser companyuser
JOIN CompanyCar companycar on companycar.companyId = companyuser.companyId
How do I solve this within the prisma framework using includes or some other mechanism?
I recieved a response from one of the devs on github. See the link below stating that currently a rawQuery must be used, but this feature is an outstanding feature request.
https://github.com/prisma/prisma/discussions/14905

Django - join between different models without foreign key

Imagine I have two simple models (it's not really what I have but this will do):
Class Person(models.Model):
person_id = models.TextField()
name = models.TextField()
#...some other fields
Class Pet(models.Model):
person_id = models.TextField()
pet_name = models.TextField()
species = models.TextField()
#...even more fields
Here's the key difference between this example and some other questions I read about: my models don't enforce a foreign key, so I can't use select_related()
I need to create a view that shows a join between two querysets in each one. So, let's imagine I want a view with all owners named John with a dog.
# a first filter
person_query = Person.objects.filter(name__startswith="John")
# a second filter
pet_query = Pet.objects.filter(species="Dog")
# the sum of the two
magic_join_that_i_cant_find_and_possibly_doesnt_exist = join(person_query.person_id, pet_query.person_id)
Now, can I join those two very very simple querysets with any function?
Or should I use raw?
SELECT p.person_id, p.name, a.pet_name, a.species
FROM person p
LEFT JOIN pet a ON
p.person_id = a.person_id AND
a.species = 'Dog' AND
p.name LIKE 'John%'
Is this query ok? Damn, I'm not sure anymore... that's my issue with queries. Everything is all at once. But consecutive queries seem so simple...
If I reference in my model class a "foreign key" (for select_related() use), will it be enforced in the database after the migration? (I need that it DOESN'T happen)
Make a models.ForeignKey but use db_constraint=False.
See https://docs.djangoproject.com/en/3.0/ref/models/fields/#django.db.models.ForeignKey.db_constraint
Also, if this model is managed=False, ie it is a legacy db table and you're not using Django migrations, the constraint won't ever be made in the first place and it's fine.
If you create a FK in the model, Django will create a constraint on migration, so you want to avoid that in your case.
I don't think there is a way to join in the database in Django if you don't declare the field to join as a foreign key. The only thing you can do is to do the join in Python, which might or might not be OK. Think that prefetch_related does precisely this.
The code would be something like:
person_query = Person.objects.filter(name__startswith="John")
person_ids = [person.id for person in person_query]
pet_query = Pet.objects.filter(species="Dog", person_id__in=person_ids).order_by('person_id')
pets_by_person_id = {person_id: pet_group for person_id, pet_group in itertools.groupby(pet_query, lambda pet: pet.person_id)}
# Now everytime you need the pets for a certain person
pets_by_person_id(person.id)
# You can also set it in all objects for easy retrieval
for person in person_query:
person.pets = pets_by_person_id(person.id)
The code might not be 100% accurate, but you get the idea I hope.

How to join Two tables of two non relashinship defined columns using Nhibernate QueryOver

Using NHibernate QueryOver, I want to join two tables using two columns which are not defined in the mapping as a relationship.
E.g. This is not my exact scenario but this can explain that
Tables:
Employee(Id, Name, DepartmentId, SomeCode,Address)
Department (Id, Name, ,Code)
Select
SELECT *
FROM EMPLOYEE E
JOIN DEPARTMENT D
ON D.Code = E.SomeCode
Can someone please tell me how to do this query using NHibernate QueryOver. Note that "SomeCode" in Employee and "Code" in Department are not defined as a relationship. DepartmentId is the foreign key and I can join these using JoinAlias but I want it in a somewhat different way.
There are similar questions, e.g.
NHibernate (+ FluentNhibernate) : Join two detached tables
Hibernate Criteria Projection without mapped association of tables
And the answer is:
either use HQL and CROSS JOIN (with WHERE)
There is NO way how to do that with QueryOver/Criteria)
See the doc:
14.2. The from clause
Multiple classes may appear, resulting in a cartesian product or "cross" join.
from Formula, Parameter
from Formula as form, Parameter as param
So using HQL in your case, we can do it like this:
SELECT ...
FROM EMPLOYEE E, DEPARTMENT D
WHERE D.Code = E.SomeCode
...
BUT I would suggest: create that mapping in the code. Simply introduce many-to-one relation. It will be loaded lazily (only if used) and will nicely serve to our needs - be used in QueryOver as a relation for Join
If there is such relation, if this exist in the business object domain, we should not be scared to use it. We can hide it via security etc...

How to avoid unnecessary inner join on a simple query on entity inheritance mapped with JOINED strategy?

I'm using JPA 2 with Hibernate 4.2.0-Final as provider and I have the following entities:
#Entity
#Inheritance(strategy=InheritanceType.JOINED)
public class Person {
#Id
private String id;
.. Person attributes ..
.. Getters/Setters ..
}
#Entity
#Table(uniqueConstraints={#UniqueConstraint(name="UniqueCode", columnNames="code")})
public class Customer extends Person {
#Column(nullable=false)
private String code;
.. Other Customer attributes ..
.. Getters/Setters ..
}
And I have the following JPQL:
SELECT count(distinct c.code) FROM Customer c
For which Hibernate is generating the following SQL:
select
count(distinct customer0_.code) as col_0_0_
from
Customer customer0_
inner join
Person customer0_1_
on customer0_.id=customer0_1_.id
But I only need to count Customers with distinct code, which happens to be a field that is specific to Customer, so there is no need for the inner join to 'Person'. I'd like Hibernate to generate the SQL like follows (i.e. without joinning table 'Person'):
select
count(distinct customer0_.code) as col_0_0_
from
Customer customer0_
Is there a way to tell Hibernate to avoid the unnecessary inner join? Maybe some Hibernate-specific Query Hint?
The JOINED Strategy in JPA uses a separate table for each class in the object hierarchy.
So if you want to load objects for a subclass you also have to load information from the parent class (As the subclass alone does not represent complete picture without the attributes in the parent class). This results in a JOIN when querying for the sub-object.
From the JPA documentation you can see this as being a main disadvantage for The JOINED strategy.
1) Aside from certain uses of the table-per-class strategy described
below, the joined strategy is often the slowest of the inheritance
models. Retrieving any subclass requires one or more database joins,
and storing subclasses requires multiple INSERT or UPDATE statements.

how to map a bag/list/set in a class from a table which is got an indirect link to a table

I know the title might sound a bit weird but I've attached a screen of the database design. I have two master tables with a many-to-many relationship in between. But we're using the primary key from the many-to-many table to refer another table called ResourceAllcoation table with the foreign key (ProjectResourceID)
Now what would be the best way to get a bag of ResourceAllocation in the Resource entity? Is there a direct way to do this in nhibernate?
Currently my nhibernate mapping has a one-to-many bag to the ProjectResource table which is then referring the ResourceAllocation table which I feel might not be the best approach.
Please forgive my ignorance. Any thoughts is appreciated.
#kalki, when I implemented your mapping, I figured that the sql query getting generated is
SELECT
*
FROM PROJECTRESOURCE P
LEFT OUTER JOIN RESOURCEALLOCATION R
ON P.PROJECTRESOURCEID=R.ID WHERE P.RESOURCEID=1
but that doesn't work since ProjectResource doesn't have a PROJECTRESOURCEID column
If the query generated was
SELECT *
FROM PROJECTRESOURCE P
LEFT OUTER JOIN RESOURCEALLOCATION R
ON P.ID = R.PROJECTRESOURCEID
WHERE P.RESOURCEID=1
it would work.
You can map this using a Many-to-Many in NHibernate and an IdBag