How to use where clause in JPQL? - persistence

I made a shopping cart web application for a stores. If a customer log into the system, They are adding some items to there shopping cart. In my case, I store that all cart items in table named, ShoppingCart. I have 2 tables named, Customer and ShoppingCart. ShoppingCart primary key is userName. userName is a attribute of Customer table. I need to get all the ShoppingCart entries where userName.
SELECT o FROM ShoppingCart o, Customer c WHERE c.userName = :id
id is the primary key of ShoppingCart. I failed to get correct result from this query. How can I do it?
Thanks in Advance.

You can try the below query. In your query, you haven't added which column should be joined to fetch exact results for the given id.
SELECT o FROM ShoppingCart o, Customer c WHERE c.userName = o.userName AND o.userName = :id
Also, you can try adding relationships one-to-many as each customer can have one or more than that order items.
SELECT c FROM Customer c JOIN c.orders o WHERE c.userName = :id
Here, orders is the collection of orders for particular customer. Then from Customer, you can get its orders.

Related

How would I associate users with different company tables?

In the below diagram you can see I have profiles for users. A user means the profile is associated with a login. If they don't have a login account they are merely a "contact" at the company tables you see on the right.
I am creating a CRM that needs to be able to store many facilities, customers, vendors, etc.
My question is how would I associate that profile with the company it belongs too? If I went to there profile page, for example, I should see what company they work for, regardless of what table the company is in.
I have 2 ideas but both seem flawed. One is to make a separate profile table for contacts for each. Example. vendor_profiles, customer_profiles, etc. This seems messy.
My other idea was to make a vendor_id, customer_id, etc column in the profile table, set them all to NULL by default, and if they belong to a vendor then my application code would check each for a number, and I think you get where I am going from there. Again, seems very messy, and inefficient.
I also considered grouping the Vendors, Customers, so on into one table and just setting a "type" but they all store very different info and are used in different, and often, relational ways.
Introduce a new organization table which unifies those aspects of vendor, customer,
facility and our_company that they all share in common:
CREATE TABLE organization (
organization_id serial4
type text);
CREATE TABLE profile (
profile_id serial4
user_id int4 REFERENCES user
organization_id int4 REFERENCES organization
...);
Then add an organization_id foreign key to vendor, customer, facility and our_company
so these tables can be joined to organization when the extra info in those tables are needed.
CREATE TABLE vendor (
vendor_id serial4
organization_id int4 REFERENCES organization
vendor_specific_field text
...);
Note that if you use "unique" names for id fields (such as organization_id instead of id) which have a consistent meaning across all tables, then you can JOIN ... USING syntax
SELECT *
FROM profile p
INNER JOIN organization o USING (organization_id)
INNER JOIN vendor v USING (organization_id)
WHERE o.type = 'vendor'
instead of
SELECT *
FROM profile p
INNER JOIN organization o ON p.organization_id = o.id
INNER JOIN vendor v ON v.organization_id = o.id
WHERE o.type = 'vendor'
which may improve readability and reduce potential errors in join conditions. (You'll never have to wonder what field in one table connects to the id field in another table.)

How to make a double relatiobnship using a Spring Boot project +JPA?

Have a project with 4 tables: users, companies, roles and user_roles_relationships.
In the user_roles_relationships have 3 columns: user_id, role_id and company_id.
Each user have a different role for each company.
I use JPA but, how to get all companies from specific user?, for example, in the list companies section need show all companies associated to the current authenticated user.
In SQL is easy, make a inner join using the relationships table and company table and a where clausle, but how to works in the repository?
The ideal query is:
SELECT companies.*
FROM companies
INNER JOIN user_groups_relatinships ON (user_groups_relatinships.company_id = companies.id)
INNER JOIN users ON (users.id = user_groups_relatinships.user_id)
WHERE users.id = ?
I have a tree entities, the user, the company and the role, the user entity have a role relationship using the #ManyToMany annotation, and the company no have relationships annotations.

How to Carry over a Table into a Column PostgreSQL

This May be a dumb question as I am a beginner in postgreSQL but what I'm trying to do is
I have a Table called Products and inside products there is 3 columns Name, Price, Expiry Date. Now I have a second table called orders with 4 columns. Product, purchasePrice, Amount, and CountryRecieved.
All I want is to reference the Product column to the product table so it has all the Information of the product table?
Is this do able?
The key concepts you need to read up on are:
"normalisation": the process of breaking down data into multiple related entities
"foreign keys": pointers from one database table to another
"joins": the query construct used to follow that pointer and get the data back together
In your case:
You have correctly determined that the information from Products should not just be copied manually into each row of the Orders table. This is one of the most basic aspects of normalisation: each piece of data is in one place, so updates cannot make it inconsistent.
You have deduced that the Orders table needs some kind of Product column; this is your foreign key. The most common way to represent this is to give the Products table an ID column that uniquely identifies each row, and then have a ProductID column in the Orders table. You could also use the product's name as the key, but this means you can never rename a product, as other entities in the database might reference it; integer keys will generally be more efficient in storage and speed, as well.
To use that foreign key relationship, you use a JOIN in your SQL queries. For example, to get the name and quantity of products ordered, you could write:
SELECT
P.Name,
O.Amount
FROM
Products as P
INNER JOIN
Orders as O
-- This "ON" clause tells the database how to look up the foreign key
On O.ProductId = P.ProductId
ORDER BY
P.Name
Here I've used an "inner join"; there are also "left outer join" and "right outer join", which can be used when only some rows on one side will meet the condition. I recommend you find a tutorial that explains them better than I can in a single paragraph.
Assuming the name column is key in Products table and product column in Orders table refers to it, you can join the two table on related column(s) and get all the information:
select
o.*, p.*
from orders o
join products p on o.product = p.name;

Is it possible to insert values in column using just a primary key reference?

I have a table 'users' with the columns:
user_id(PK), user_firstname, user_lastname
and another table 'room' with the columns:
event_id(PK), user_id(FK), user_firstname, user_lastname....(and more columns).
I want to know if it is possible to fill the user_firstname and user_lastname automatically just knowing the user_id column.
Like the default value of user_firstname would be like: "select users.user_firstname where users.user_id = user_id"
I don't know if was clear enough...As you can see my knowledge in database is very narrow.
What you want to achieve can be done with JOINs. They will avoid those redundant user_firstname and user_lastname columns. So you'd just fetch from both tables when querying the room table and you get the extra columns of users into the result set:
SELECT * FROM room AS r INNER JOIN users AS u ON r.user_id = u.user_id;
The thing we did here is called normalization. Another important thing to take care of are foreign key constraints and their cascades, in your case room.user_id references user.user_id. A delete on user should most probably cascade to room, if you want to delete users, instead of flagging them deleted.
The columns user_firstname and user_lastname do not belong in your room table. The user_id column references the users table, that is all you need.
To select the data, you can use a JOIN statement, something like
SELECT R.event_id, R.user_id, U.user_firstname, U.user_lastname
FROM room AS R
JOIN users AS U ON R.user_uid = U.user_id
The answer here is sideways to the question. You do not want a user_firstname and user_lastname column in the Event table. The user_id is a proxy for that row of the entire User table. When you need to access user_firstname, you do a JOIN of the two tables on the common column.

Database schema dilemma with foreign keys pointing to multiple tables (exclusive arc)

Hopefully my description is a little better than the title, but basically I'm having an issue with one part of a new application schema and i'm stuck on what is the most manageable and elegant solution in table structure.
Bare bones table structure with only relevant fields showing would be as follows:
airline (id, name, ...)
hotel (id, name, ...)
supplier (id, name, ...)
event (id, name,...)
eventComponent (id,name) {e.g Food Catering, Room Hire, Audio/Visual...}
eventFlight (id, eventid, airlineid, ...)
eventHotel (id, eventid, hotelid, ...)
eventSupplier (id, eventid, supplierid, hotelid, eventcomponentid, ...)
So airline, hotel, supplier are all reference tables, and an Event is create with 1 to many relationships between these reference tables. E.g an Event may have 2 flight entries, 3 Other components entries, and 2 hotel entries. But the issue is that in the EventSupplier table the supplier can be either a Supplier or an existing Hotel. So after the user has built their new event on the front-end i need to store this in a fashion that doesn't make it a nightmare to then return this data later.
I've been doing a lot of reading on Polymorphic relations and exclusive arcs and I think my scenario is definitely more along the lines or an Exclusive Arc relationship.
I was thinking:
CREATE TABLE eventSupplier (
id SERIAL PRIMARY KEY,
eventid INT NOT NULL,
hotelid INT,
supplierid INT,
CONSTRAINT UNIQUE (eventid, hotelid, supplierid), -- UNIQUE permits NULLs
CONSTRAINT CHECK (hotelid IS NOT NULL OR supplierid IS NOT NULL),
FOREIGN KEY (hotelid) REFERENCES hotel(id),
FOREIGN KEY (supplierid) REFERENCES supplier(id)
);
And then for the retrieval of this data just use an outer join to both tables to work out which one is linked.
select e.id as eventid, coalesce(h.name,s.name) as supplier
from eventSupplier es
left outer join
supplier s on s.id = es.supplierid
left outer join
hotel h on h.id = es.hotelid
where h.id is not null OR s.id is not null
My other options were to have a single foreign key in the eventSupplier table with another field for the "type" which seems to be a harder solution to retrieve data from, though it does seem quite flexible if I want to extend this down the track without making schema changes. Or alternately to store the hotelid in the Supplier table direct and just declare some suppliers as being a "hotel" though there were then be redundant data which I don't want.
Any thoughts on this would be much appreciated!
Cheers
Phil
How about handling events one-by-one and using an EventGroup to group them together?
EDIT:
I have simply renamed entities to fit the latest comments. This as close as I can get to this -- admittedly I do not understand the problem properly.
A good way to test your solution is to think about what would happen if an airline became a supplier. Does your solution handle that or start to get complicated.
Why do you explicitly need to find hotel data down the supplier route if you don't need that level of data other types of supplier? I would suggest that a supplier is a supplier, whether its a hotel or not for these purposes.
If you want to flag a supplier as a hotel, then simply put hotelid on the supplier table or else wait and hook in the supplier later via whatever mechanism you use to get detail on other suppliers.