best way to call two database servers - java

i want to call two table of different database at once.table of database A contains user id and table of database B contains user location with the user id, so i want to join these two tables and get the location corresponding to user_id.database A and B are in two different servers. so how can i join these two tables. if it is not possible to join this, is there any efficient way to do this.please help.i'm trying to do this using java, mysql.
ps = con.prepareStatement("SELECT user_id FROM A.users");
rs = ps.executeQuery();
while(rs.next())
{
//call select statement for database B to get the location for each user id
}
please suggest an efficient way to do this
Id User_id
===========
1 44
2 23
User_id location
====================
44 india
23 us

Supposing user_id is a long.
PreparedStatement psUserLocation = conB.prepareStatement("SELECT location FROM B.users WHERE user_id = ?");
while(rs.next()) {
//call select statement for database B to get the location for each user id
long userId = rs.getLong(user_id);
psUserLocation.setLong(1, userId)
ResultSet userLocation = ps.executeQuery();
// Do whatever with the location(s)
}
EDIT: one query for all users instead of one query per user:
private final static String QUERY = "SELECT user_id, location FROM B.users WHERE user_id IN (%a)";
StringBuilder userList = new StringBuilder();
while(rs.next()) {
long userId = rs.getLong(user_id);
userList.append(userId);
if (!rs.isLast()) {
userList.append(",");
}
}
String usersLocationQuery = QUERY.replaceAll("%a", userList.toString());
PreparedStatement psUsersLocation = conB.prepareStatement(usersLocationQuery);
ResultSet usersLocation = psUsersLocation.executeQuery();
// Do whatever with the locations
Keep in mind this can fail/work wrong because most DB have a limit for how many items an SQL IN clause can include. Also this second method might allow an SQL injection on the %a replacement.

You may use FEDERATED Storage Engine. The FEDERATED storage engine lets you access data from a remote MySQL database without using replication or cluster technology. Querying a local FEDERATED table automatically pulls the data from the remote (federated) tables. No data is stored on the local tables. This may not be very efficient but it will do the work (JOINs).

If you can do away with join, one possible way is to get all the user_id's from tableA in one go, and then pass the user_id's to tableB at once. Of course, this approach will require you to change code as well.
Something like:
select user_id from tableA (of databaseA);
and
select user_id, location from tableB (of database B) where user_id in (<result_from_above_query)
The above process will require two queries.

Related

SQL/JPA want to select data for a list of ids filtering by a specific timestamp range for each id

I have a table with some data, there are record id, userIds, timestamp and data columns. Receive from the client a list of userIds, initially, I just had to fetch data by the same timestamp range for all useIds, just using userId IN (list). However, now I'm required to get data by different timestamp ranges for each userId, let's say userID 1 needs data from 1643580000000 to 1646431200000 and userId 2 from 1626418800000 to 1647500400000 (utcTimestamp in mills).
Most probably I'll receive a list of [userId, startTime, endTime], so, I was considering to loop the main query for each userId with its respective timestamp range (I've seen it's a bad idea due to performance, but if I have to, I have to), but I also found out about cursors (not much experience here).
I wanted to know if it's possible to get what I want without loops or cursors, and if not, best way with each one.
Thanks in advance!
Notes: using MariaDB. SQL query will be used as nativeQuery in a Java service repository.
You can run a query laike this.
Of course you have to add for every user his own time range
SELECT * FROM mytable
WHERE (userID = 1 AND `timestamp` BETWEEN 1643580000000 AND 1646431200000)
OR (userId = 2 AND `timestamp`BETWEEN 1626418800000 AND 1647500400000)
If you have a lot of rows and not that many id to process, you can do it with
SELECT * FROM mytable
WHERE (userID = 1 AND `timestamp` BETWEEN 1643580000000 AND 1646431200000)
UNION
SELECT * FROM mytable
WHERE (userId = 2 AND `timestamp`BETWEEN 1626418800000 AND 1647500400000)
Here also you need to add for every id another UNION

How do I Join two tables together in SQLite that can be used in JAVA Sprint Boot?

I am using a Movie Database that will link to the front-end of my website. i am using Java Spring Boot to link the Database. My question is, How can i join a Movies table and Reviews table>]?
try {
String getAllActorsbyMoviesidQuery = "SELECT * FROM tblMovies JOIN tblReviews ON tblReviews.actor_id = tblMovies.actor_id";
statement = dbConnection.createStatement();
ResultSet resultSet = statement.executeQuery(getAllReviewsbyMoviesidQuery);
Joining the 2 tables on actor_id is not probably the suitable way.
I guess there exists inside tblReviews a column like movie_id that refers to the id column of the table tblMovies:
SELECT * FROM tblMovies JOIN tblReviews ON tblReviews.movie_id = tblMovies.id
change the column names to the actual ones.
If you want the reviews for a particular movie, then add a WHERE clause, like:
WHERE tblMovies.id = ?
or
WHERE tblMovies.title = ?

Can I SELECT with LAST_INSERT_ID() after INSERT Batch without any cares?

I'm asking myself if it is possible to SELECT with LAST_INSERT_ID() in WHERE Clause after an batch of INSERTs without getting corrupt data in the tables? I'm thinking of the scenario that multiple users doing the same stuff at the same time. I develop an JSF Application in which this scenario can be possible.
In hard Code my SELECT after INSERTs looks like this:
preparedstatement.addBatch(
"INSERT INTO table1(all the FIELDS)"
+ "VALUES(null, ...);"
);
preparedstatement.addBatch(
"INSERT INTO table2(all the FIELDS)"
+ "VALUES(null, LAST_INSERT_ID(), ...);"
);
preparedstatement = connect.prepareStatement(
"SELECT id FROM table3 WHERE id = LAST_INSERT_ID();"
);
preparedstatement.executeBatch();
resultSet = preparedstatement.executeQuery();
Get I problems with this implementation or is there an better way?
Best Regards
You should be fine, quoting MySQL's documentation:
The ID that was generated is maintained in the server on a
per-connection basis. This means that the value returned by the
function to a given client is the first AUTO_INCREMENT value generated
for most recent statement affecting an AUTO_INCREMENT column by that
client. This value cannot be affected by other clients, even if they
generate AUTO_INCREMENT values of their own. This behavior ensures
that each client can retrieve its own ID without concern for the
activity of other clients, and without the need for locks or
transactions.
MySQL Last_insert_id

SQL command how to append(insert) values into DB

my question is how to insert values into DB in sql. i have a USER who can have multiple emails. how can i insert multiple emails into one object? i dont want to add a completely new user object into a new row. i just want to update and append new email into email field of an existing user in db.
i did this:
JPA.em().createQuery
("insert into User (email) select (email) from User where USERNAME=? VALUES (?)")
.setParameter(1, username).setParameter(2, email).executeUpdate();
but it is not working, thanks for help !!
Get the user from the database, concatenate its existing email with the new value, and save the user.
JPA uses entities and generates SQL queries for you. You tyically use queries only to get entities from the database. And those queries are JPQL queries, not SQL queries.
And it looks like your schema is not normalized correctly. One User entity should have many Email entities (OneToMany associations), rather than stuffing all the emails in a single CLOB field of the user. This is how you could search and get individual emails from the database, and get users without all their emails if you don't need them.
I don't know JPA but query should be
JPA.em().createQuery
("insert into User (email) select (email) from User where USERNAME=? VALUES (?)")
.setParameter(1, username).setParameter(2, email).executeUpdate();
should be
JPA.em().createQuery("UPDATE User
SET email =?
WHERE USERNAME=? ")
.setParameter(1,email )
.setParameter(2,username)
.executeUpdate();

How to map native query to one model class?

Hi I´m using Eclipselink and I did a native query to select some fields of 2 tables. I mapped my table Logins in a model class. I would not like to map my table "B" because I need only 2 fields of this table on my sql result.. can I map this 2 fields in my Logins table to my sql result ?
My sql is this:
select l.login_id, s.lugarcerto,s.vrum, l.username, l.first_name, l.last_name, l.phone, l.fax_number, l.address, l.zip,
l.address2 as 'birth_date', l.city as 'cpf_cnpj'
from Logins l
join (select se.login_id, lugarcerto = min(case when se.service = 'IM' then '1' end), vrum = min(case when se.service = 'VE' then '1' end)
from (select distinct ad.login_id, substring(ap.Rate_code,(CHARINDEX('-', ap.Rate_code)+1),2) as 'service'
from Ad_Data.dbo.ad ad
join Ad_Data.dbo.ad_pub ap on (ad.ad_id = ap.ad_id)
where ap.ad_type =1) se
group by se.login_id) s on (s.login_id = l.login_id)
I did map Logins table and I want to map s.lugarcerto and s.vrum to my SQL query result.
There´s anyway to just add it to my Logins model ?
Not without having mappings for the attributes you want those values put into, and not without causing problems with them being cached in the entity.
Why not just return the values beside the entity, much like you would with a JPQL query such as: "Select l, subquery1, subquery2 from Logins l" ie:
Query q = em.createNativeQuery(yourQueryString, "resultMappingName");
And in the entity, include the annotation:
#SqlResultSetMapping(name="resultMappingName",
entities={#EntityResult(entityClass=com.acme.Logins.class, )},
columns={#ColumnResult(name="LUGARCERTO"), #ColumnResult(name="VRUM")}
)
Best Regards,
Chris

Categories

Resources