I have stored objects in a database using tables, I retrieve data from objects in following way:
String query = "SELECT * FROM Librarian WHERE (id = ?)";
Account ac = null;
try {
state = conn.prepareStatement(query);
state.setString(1,passport);
rs = state.executeQuery();
if(rs.next()) {
ByteArrayInputStream bais = new ByteArrayInputStream(rs.getBytes("Object"));
try {
ObjectInputStream ois = new ObjectInputStream(bais);
ac = (Account) ois.readObject();
and then I can access values e.g ac.getName etc..
But this gives me only one object. In a table(given below) I have stored 3 foreign keys and I want to join 3 tables to get information from them, but each table has Object i.e I want to retrieve information from those Objects, hence I want to join tables and get information from objects.
CREATE TABLE Orders
(OrderID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Passport VARCHAR(20) NOT NULL,
FOREIGN KEY (Passport) REFERENCES Guest(Passport) ON DELETE CASCADE,
ISBN INT NOT NULL,
FOREIGN KEY (ISBN) REFERENCES Books(ISBN) ON DELETE CASCADE,
LibPassport VARCHAR(20) NOT NULL,
FOREIGN KEY (LibPassport) REFERENCES Account(LibPassport) ON DELETE CASCADE,
Object LONGBLOB NOT NULL
);
If you need more explanations or code please let me know.
Regards,
I must be missing something...
String query = "SELECT *
FROM ORDERS O
INNER JOIN GUEST G
on O.Passport = G.Passport
INNER JOIN Books B
on B.ISBN = O.ISBN
WHERE (O.OrderID = ?)";
Assuming you only want records were all the keys match.
If you want all records from one table, and only those matching in others, then you have to use LEFT, Right or Full outer joins (later of which isn't supported in mySQL, so you have to use a left and right and a union)
You have to use aliases for the columns you specify in the SELECT part. your query should look like this:
SELECT
o.Id,
o.Whatever,
p.ID,
p.Name,
...
p.Object AS Passport_Object,
b.ID,
b.Name,
...
b.Object AS Books_Object,
a.ID,
...
a.Object AS Account_Object
FROM
Orders AS o
JOIN
Passport AS p ON ...
JOIN
Books AS b ON ...
JOIN
Account AS a ON ...
WHERE
-- some condition here
Do not use SELECT * in your queries, see the question What is the reason not to use select *?.
Related
Update 2
Query:
select distinct p.name, u.cookie_id
from product p
left join user_product up on p.id = up.product_id
left join user u on up.user_id = u.id
where p.active = true
and
(
u.cookie_id = '4c2fe5b2-73fe-4b28-baa6-23db0512114c'
or
not (exists (
select p1.id
from user_product up1, product p1
where p1.id = up1.product_id
))
)
Output:
how should be:
Update 1
I wrote the code with the use of stream() for the better understanding of the problem:
List<Product> productList = productRepository.findAllByActiveTrue();
productList = productList.stream().map(item -> {
if(item.getUserProducts() == null) return item;
List<UserProduct> userProductList = new ArrayList<>();
for (UserProduct userProduct : item.getUserProducts()) {
if(userProduct.getUser().getCookieId().equals(cookieId)){
userProductList.add(userProduct);
}
}
item.setUserProducts(userProductList);
return item;
}).collect(Collectors.toList());
I would like to know how correctly select data from the tables. I want to get all products.
But to get all products is easy. I also need to include in the output data (UserProducts and User) if there's a connection between Product and User by CookieId. In other words, I want to show all products with User and UserProducts (if possible) and exclude the relation Product-UserProduct-User if User's cookieId doesn't match the cookieId from the query.
I am trying the following query, but it returns me only products that has the connection between User and the product, not all products.
#Query("from Product pr join fetch pr.userProducts up left join fetch up.user u where pr.active = true and u.cookieId = :cookieId")
List<Product> getAllProductsByCookieId(UUID cookieId);
My database looks like this:
Visualisation of the idea:
SQL-queries to generate tables:
product-table
create table if not exists product
(
id bigint auto_increment
primary key,
active bit not null,
image_path varchar(255) null,
name varchar(255) null,
price double not null,
unit_number double null,
unit_type varchar(255) null
);
userProduct-table
create table if not exists user_product
(
quantity int null,
product_id bigint not null,
user_id bigint not null,
primary key (product_id, user_id),
constraint FKnw43wab2rt35jmofmpbhkibco
foreign key (product_id) references product (id),
constraint FKq5o2e33vlwpfc2k1mredtia6p
foreign key (user_id) references user (id)
);
user-table
create table if not exists user
(
id bigint auto_increment
primary key,
cookie_id varchar(255) null
);
Your requirement is not possible without scaler objects in JPA. i.e JPA cannot give you a Product object where p.getUserProducts() contains only some UserProducts.
See my answer here. Why left join on CriteriaQuery doesn't filter results?
or here problems with OneToMany including a filter clause in spring jpa
You have to use the native query option or any other option where you retrieve the columns and provide a mapper as to how to create the object. You can use the following sql query.
select p.product, u.cookie_id
from product p
left join user_product up on p.id = up.product_id
left join user u on up.user_id = u.id and u.cookie_id = '?1'
where p.active = true
group by p.product, u.cookie_id
I'm trying to get some data from multiple tables using join query. I have a reservation table where I store the "pick-up location id" and "drop location id" and another table "location" where the location names were stored.
I'm trying to get the location name (pick-up and drop location) in 2 different variables from the "location" table with these 2 ids from the reservation table.
I have the tables with the following parameters.
Location table: "locations_deatils" has location_name location_id.
Reservation table: reservation_cars has pickup_location id, drop_location id, pick_up date, drop_date
SELECT l.location_name as pick-up_loc,
l.location_name as drop_loc,
c.pickup_date,
c.return_date,
FROM locations_deatils l inner join
reservation_cars c on l.locations_id = c.pickup_location and l.locations_id
= c.return_location
WHERE c.pickup_date >= :pickupTime and c.return_date <=:returnTime;
You need to do a separate join for the pick-up and for the drop location.
SELECT l1.location_name as 'pick-up location', l2.location_name as 'drop location', pickup_date, return_date
FROM reservation_cars r
JOIN locations_deatils l1 ON l1.locations_id = r.pickup_location
JOIN locations_deatils l2 ON l2.locations_id = r.return_location
WHERE r.pickup_date >= :pickupTime
AND r.drop_date <= :returnTime
Maybe you meant something like this:
SELECT p_loc.location_name AS pickup_location,
cars.pickup_date,
d_loc.location_name AS drop_location,
cars.return_date
FROM reservation_cars cars
JOIN location_details p_loc
ON cars.pickup_location = p_loc.location_id
JOIN location_details d_loc
ON cars.return_location = d_loc.location_id
WHERE .....
You might need to use an outer join in case the pickup and/or return locations are not set (yet).
let's say i have 2 queries and 2 ResultSet. the first one is members table query, while the second query is for other member datas. now i want to join the first resultset with the second one. for example it looks like this
ResultSet rsMember = psMembers.executeQuery();
ResultSet rsCustomValues = psCustomValues.executeQuery();
// object for mapping query results
MembersMapper memberMapper = new MembersMapper();
while (rsMember.next()) {
memberMapper.setId(rsMember.getString("id"));
memberMapper.setName(rsMember.getString("name"));
memberMapper.setUsername(rsMember.getString("username"));
memberMapper.setGroup(rsMember.getString("group_id"));
List strCustomValues = new ArrayList<>();
while(rsCustomValues.next()){
// map the custom values
Map<String, Object> mapTemp = new HashMap<String, Object>();
mapTemp.put(FIELD_ID, rsCustomValues.getString("custom_field_id"));
mapTemp.put(INTERNAL_NAME,
rsCustomValues.getString("custom_field_internalname"));
mapTemp.put(NAME,rsCustomValues.getString("custom_field_name"));
strCustomValues.add(mapTemp);
}
memberMapper.setCustomvalues(strCustomValues);
}
the problem is the second (inner while) query. what connects data between first and second resultset is member id, which is primary key in first table (first query) and foreign key in second query. so the second query will have member id in random order.
so how can i order the second query without having to put 'order by member_id' in the second query? i will have to avoid 'order by member_id' because it will take time to process.
Edit: here's the scripts
First script
select
mbr.*, usr.username, grp.name as groupname, grp.status
from members mbr
join users usr on mbr.id = usr.id
join groups grp on mbr.group_id = grp.id
where mbr.id > #id#
order by id asc
limit #limit#
Second script
select
cfv.member_id as 'member_id', cf.id as 'custom_field_id',
cf.internal_name as 'custom_field_internalname',
cf.name as 'custom_field_name', cfv.string_value as 'cfv_stringvalue',
cfv.possible_value_id as 'cf_possiblevalueid', cfvp.value as 'cfvpvalue'
from custom_field_values cfv
join custom_fields cf on cf.id = cfv.field_id
left join custom_field_possible_values cfvp on cfv.possible_value_id = cfvp.id
where exists(
select * from (select id from members where id > #id#
limit #limit#
) result where result.id = cfv.member_id)
and cf.subclass = #subclass#
order by cfv.member_id asc
It is better to fetch the second result set to an object representation and sort it out.
See a similar question here How can I sort ResultSet in java?
Say I have this table
CREATE TABLE person(
person_id INT AUTO_INCREMENT PRIMARY KEY,
first_name VARCHAR(50),
last_name VARCHAR(50),
x_cordinates INT,
y_cordinates INT
);
In the past I have used
Person person = EntityManager.find(Person.class, primaryKey);
But the primary key in this instance is auto incremented, is it possible to get a row back using the other colums such as first_name and last_name to get the primary key along with the other values ?
You can create a NamedQuerry like that :
#NamedQuery(name="person.findAll", query="SELECT p FROM Person p WHERE like :first_name")
And can assign a value to "first_name" like that :
query.setParamter("fist_name", "%name%");
You can read this documentation.
Use method createQuery or createNativeQuery of entityManager.
With createQuery you have to use JPQL syntax and with createNativeQuery, you've to use the standard SQL syntax.
For example :
Query query = EntityManager.createQuery("select * from person p where p.first_name = :fname");
17.
query.setParameter("fname", firstName);
Person p = query.getSingleResult();
I am trying to use the below query with Hibernate's session.createSQLQuery.
The Entity object corresponding to user has an attribute called address.
The address object is created out of 5 fields from table 'user'.
If I do not use an SQLQuery it gets filled auto-magically.
However without the SQLQuery I can't get all the info I would get from the desired joins shown below.
The user entity object also attributes like accessPlan which I am filling up using
.addEntity("accessPlan", AccessPlan.class)
Query:
SELECT
user.*,
ap.*,
country.*,
auth.*,
GROUP_CONCAT(coup.code SEPARATOR ' ') coupons
FROM
user
INNER JOIN access_plan ap ON (user.access_plan = ap.id)
INNER JOIN country ON (user.country=country.code)
LEFT JOIN user_auth auth ON (user.id = auth.userid)
LEFT JOIN (
SELECT
trans.user_id,coupon.code
FROM
payments_transaction AS trans
INNER JOIN payments_coupon coupon ON (trans.payments_coupon_id=coupon.id)
) coup ON (user.id=coup.user_id)
GROUP BY user.id;
What can be the easiest way to fill up the composed address object while using the SQLQuery?
OR
Is there a way to avoid using SQLQuery for a query like this?
Please check below example from the section 'Returning multiple entities'
String sql = "SELECT ID as {c.id}, NAME as {c.name}, " +
"BIRTHDATE as {c.birthDate}, MOTHER_ID as {c.mother}, {mother.*} " +
"FROM CAT_LOG c, CAT_LOG m WHERE {c.mother} = c.ID";
List loggedCats = sess.createSQLQuery(sql)
.addEntity("cat", Cat.class)
.addEntity("mother", Cat.class).list()
In your case, cat = user, mother = address... somewhat like that.
I do not have anything to try out at the moment but I guess this will help.