Add extra condition to jointable in springboot - spring-boot

I have 2 tables which are related using a mapping table i.e FK of these tables are stored in a mapping table (Joining table).
Users {
uid,
uname
}
Dept {
deptid,
dept_name
}
User_Dept{
ud_id,
uid
deptid
status
}
So in my User Entity i have ManytoOne relation with Dept Entity and have added #Jointable annotation to joining table ( User_Dept) like below
User.java
````#ManyToOne
````#JoinTable(
````name="UserDept",
````joinColumns = ````{#JoinColumn(name="uid",referencedColumnName="uid")},
```` inverseJoinColumns = {#JoinColumn(name="deptid", ````referencedColumnName="deptid")}
````)
````private Dept dept;
}
All good!!
But i have a business scenario to fetch only those users belonging to a particular Dept and who are 'active'.
Basically i need to add extra condition to my #jointable(user_dept) to fetch those users whose "status=active" from user_dept table.
I have tried adding #WhereJoinTable(clause = "status=active") like below
class User {
````#JoinTable(
```` name="UserDept",
````joinColumns = ````{#JoinColumn(name="uid",referencedColumnName="uid")},
```` inverseJoinColumns = {#JoinColumn(name="deptid", ````referencedColumnName="deptid")}
````)
````#WhereJoinTable(clause = "status=active")
````}
And also #where(clause = "status=active") at class level.Nothing works.
Issue:
1. where annotation adds a condition to the base query on User table instead of user_dept table.
2. wherejointable annotation- doesnt seem to have any impact.
3. Tried adding #where on userdept class (based on point 1) , but no luck.
Can someone help?
Also if you can propose any alternate solution even thatworks

Related

JpaRepository find by manyToMany attribute

Let's imagine classic example of manyToMany relation. I have entities Student and Course and manyToMany relation table between those two entities.
#Entity
data class Student(
#Id
val id: UUID,
val name: String,
#ManyToMany
val courses: Set<Course>
)
#Entity
data class Course(
#Id
val id: UUID,
val title: String,
#ManyToMany
val students: Set<Student>
)
repository can looks like this:
#Repository
interface StudentRepository : JpaRepository<Student, UUID> {
fun findAllByCoursesTitle(title: String): List<Student>
}
Function findAllByCoursesTitle should return all student signed up for math, for example.
My problem is:
How will function looks like when i need to return all students signed up for two specific courses. But i need it for dynamic number of courses, 1 or more.
for example input to function would looks like listOf("math", "geography") or in case of course_ids listOf("UUID", "UUID"). It does not matter if it will be ID or title. What is doalbe.
When i would want to write sql query for that it would looks like this:
SELECT student.id, sc1.course_id, sc2.course_id FROM student
JOIN student_course cs1
ON student.id = cs1.student_id
JOIN student_course cs2
ON student.id = cs2.student_id
WHERE cs1.course_id = ?
AND cs2.course_id = ?
But as i said, i need to have it done for various number of courses.
Please somebody advise.
If you want to resolve logic at SQL statement you can try something like this:
SELECT st.id, sc.course_id, sc.course_id FROM student as st
JOIN (
SELECT st.id as stId, sum(case when c.id IN (:courseIdList) then 1 else 0 end) as cc FROM student as std
JOIN student_course as cs ON std.id = cs.student_id
JOIN cource as c ON c.id = cs.cource_id
GROUP BY (st.id) having cc >= :minimumCourseNumbers
) A on A.stId = st.id
There're courseIdList: List course Ids. minimumCourseNumbers: Minimum course numbers that student must register.
However, I think the logic should move to application to filter.

custom listing records using conditional

i need some help with my query, basically im trying to get all my order_items on the table, but i need to get all items by user_id, but there is a detail, i want to include also records that includes on a column more than 3 times the the same email on different users_id.
Ex:
table:
- id;
- user_id;
- email;
1- Get all records from mine (user_id); 2 - Get all records where on 3 differentes user_id have the same email value;
Here is my query:
$orders = OrderItem::select('email','user_id')->where('user_id',Auth::user()->id)->distinct('email')->get();
This should work:
$orders = OrderItem::select(DB::raw('count(*) as email_count,email,user_id'))
->groupBy('email')
->where('email_count','>',2)
->orWhere('user_id',Auth::user()->id)
->get();

HQL Select New doesn't return row when a foreign key is null

I have the following named query
#NamedQuery(name = "UserFlight.getUserFlightDetails",
query = "SELECT new com.foobar.UserFlightDetails(uf.flight.divertedAirport, uf.flight.number) " +
"FROM UserFlight uf WHERE uf.user.id=?1 AND uf.flight.id=?2")
The UserFlightDetails constructor is as follows
public UserFlightDetails(Airport airport, String flightNumber) {
this.setDivertedAirport(airport);
this.setFlightNumber(flightNumber);
}
divertedAirport is a foreign key in the flight table, path=(uf.flight.divertedAirport)
My problem is when divertedAirport is null (it's a nullable foreign key), my HQL query returns null as the result (The code doesn't even trigger the constructor above), so I don't get the flightNumber which is never null.
If the divertedAirport isn't null, I get both the airport and the flight number fine (and the above constructor gets executed just fine).
What could be causing this and how could I resolve it? I tried some null functions like nullif and coalesce but nothing helped.
I'm using spring boot 1.2.7, hibernate-core 4.3.11.Final
Probably, the problem is the uf.flight.divertedAirport. This expression do a JOIN between flight and divertedAirport but, as you say, divertedAirport is a fk and can be null.
So, you need to use the LEFT JOIN.
I would rewrite your query like this:
#NamedQuery(name = "UserFlight.getUserFlightDetails",
query =
"SELECT new com.foobar.UserFlightDetails(divertedAirport, flight.number)
FROM UserFlight uf
JOIN uf.flight flight
LEFT JOIN flight.divertedAirport divertedAirport
JOIN uf.user user
WHERE user.id = ?1 AND flight.id = ?2 ")
I remove the references like uf.user.id for a explicit JOIN (JOIN uf.user user plus user.id), because is more legible and this kind of problem that generated your question is more easy to find using this way to write JPQL queries.

Laravel 4.2 - Update a pivot by its own id

I'm having some trouble with my pivot table. I've recognized too late, that it is possible, that some pivot rows doesn't have unique values in my project, means I've to add an auto_increment ID field to my pivot table.
This is my structure:
Order.php
public function items()
{
return $this->belongsToMany('Item', 'orders_items', 'order_id', 'item_id')->withPivot(['single_price', 'hours', 'prov', 'nanny_id', 'vat', 'vat_perc', 'invoice_id','id']);
}
orders_items
id, order_id, item_id, nanny_id, hours
I've conntected Orders and Items through a pivot table ('orders_items)'. It is possible, that one order has 2 or more same items in the pivot table. So I've to add an unique ID to identify and update them.
Now I try to update a pivot row. Problem is, if I have 2 or more items, he updates them all, not only one. This is my update command:
$order = Order::find($orderId);
$items = $order->items()->whereNull('nanny_id');
$free_item = $items->first();
$free_item->pivot->nanny_id = 123;
$free_item->pivot->save();
With this command, he updates all pivot rows from the order. I know the problem: Laravel uses here the wrong identifiers (it uses order_id and item_id as defined in my belongsToMany relationship - and they aren't unique). For example, Laravel tries to execute this code on save():
UPDATE orders_items SET [...] WHERE order_id = 123 AND item_id = 2;
I want, that Laravel changes the query to this one:
UPDATE orders_items SET [...] WHERE order_id = 123 AND item_id = 2 AND id = 45;
// Edit
Okay, this solution works:
$free_item->pivot->where('id',$free_item->pivot->id)->update('nanny_id',123);
But is there an easier way, f.e. adding a custom pivot model that adds the id automatically to save() and update() methods?

entity framework lazy loading null properties in child

Using entity framwork with lazy loading - Have the following question on loading related entities when the entities
are null.
Say I have two tables employee and employeedetails. Assume in the above case not all employee entries have an entry in the employeedetails table.
If I want to look up a list of Employees
(from e in objectcontext.employees
select new EmployeeEntity
{
EmpID= e.EmployeeID,
FirstName = e.FirstName,
Address = e.employeedetails.Address
}).ToList();
EmployeeEntity is the data class into which we stuff the results.
The above code breaks if even one employee in the returned list
does not have a entry in table employeedetails. This is obvious since e.employeedetails will be null for those customers who do not have a details entry
What is the best way to rewrite the above query?
Would something like this be acceptable ?
(from e in objectcontext.employees
select new EmployeeEntity
{
EmpID= e.EmployeeID,
FirstName = e.FirstName,
Address = e.employeedetails == null ? "" : e.employeedetails.Address,
}).ToList();
I am not clear on the efficiency of this above query - Would this statment do the null check at DB level?
Should I instead do an explicit include like
objectcontext.include("employeedetails")...
And then loop through the results to check for null?
Yes, this statement would indeed perform a null check in the SQL query that is generated. Most likely, it will simply be a NVL or COALESCE.
That's the way you should be doing it.

Resources