Optimize Java Code in fetching assistant id - java

Requirement : I have a file from which I need to add the assistant employee id corresponding to it's manager into db. So in file I am getting login id of assistant. I need to pass the login id to db in order to fetch the corresponding employee id of the assistant and add into the list which I am getting from file.
// code for getting employee from file - returns a list
private void setAssistantEmployeeId(List<E> empFile){
List<E> empFilter = empFile.stream().filter(emp -> emp.getLoginId()!=null).collect(Collectors.toList());
String sql = "SELECT ID FROM EMPLOYEE WHERE LOGIN_ID = ";
List<E> tempList = new ArrayList<>(empFilter);
for(E emp : empFilter){
tempList.addAll(jdbcTemplate.query(sql+emp.getLoginId(), (resultset,i)->{
emp.setAssistantEmployeeId(resultset.getString("ID"));
return emp;
}));
}
}
The above code is working as expected but it's taking lot of time to execute. I need some help to optimize this code. Can someone please help me in optimizing this code?
Thank you.

private void setAssistantEmployeeId(List<E> empFile) throws SQLException {
List<E> empFilter = empFile.stream().filter(emp -> emp.getLoginId()!=null).collect(Collectors.toList());
//1. query all LOGIN_ID
String sql = "SELECT ID, LOGIN_ID FROM EMPLOYEE WHERE LOGIN_ID IN (" + empFilter.stream().map(emp -> emp.getLoginId())
.collect(Collectors.joining("','")) + ")";
// create map[LOGIN_ID, ID]
ResultSet rs = runQuery(sql); // execute this query in your way
Map<String, String> id_loginId = new HashMap<>();
while (rs.next()) {
id_loginId.put(rs.getString("LOGIN_ID"), rs.getString("ID"));
}
// 3. assign ID value
empFilter.forEach(e -> {
e.setAssistantEmployeeId(id_loginId.getOrDefault(e.getLoginId(), ""));
});
}

Related

Panache Query with distinct returns PanacheQuery<Entity> and not ArrayList<String>

I'm trying to get a distinct result of one Column from my Database with Panache+Hibernate. Normally in Hibernate you would get an ArrayList<String> back from the query.
List<String> list = repo
.find("select DISTINCT(a.country) from TMdBrandAll a order by a.country")
.page(Page.ofSize(1000)).list();
But if I try this Approach with Panache I get the ErrorMessage
Comiler Error Message
If I change the variable "list" to the returnType List<TMdBrandAll> the compile error is gone.
List<TMdBrandAll> list = brandAllRepo
.find("select DISTINCT(a.country) from TMdBrandAll a order by a.country")
.page(Page.ofSize(1000)).list();
When I now inspect the executed code in the debugger I get.
Debugger output
How can I tell Panache that the outcome of the query will be an ArrayList<Strings> and not an ArrayList<PanacheEntity>?
Thanks for your answers
EDIT:
Code of Repo:
#RequestScoped
#Transactional
public class BrandAllRepo implements PanacheRepositoryBase<TMdBrandAll, Long> {
public void updateBrand(String brandName, String soundexCode, String countryCode, Long active, Long isNew, String user, Long brandAllId) {
update("set brandName = ?1, soundexCode = soundex(pkg_util.f_escape_special_char1(?2))," +
" countryCode = ?3, active = ?4, isNew = ?5, modifiedAt = sysdate, modified_by = ?6 where brandAllId = ?7",
brandName, soundexCode, countryCode, active, isNew, user, brandAllId);
}
}
Working Code from Repo:
#Inject
EntityManager em;
public List<String> findCountries() {
List<String> qres = em
.createQuery("select DISTINCT(a.countryCode) from TMdBrandAll a order by a.countryCode", String.class)
.getResultList();
return new ArrayList<>(qres);
}
With injected EntityManager and standard hibernate query it works.
This is a limitation of Panache.
Have a look at the code https://github.com/quarkusio/quarkus/blob/master/extensions/panache/hibernate-orm-panache/runtime/src/main/java/io/quarkus/hibernate/orm/panache/PanacheRepositoryBase.java
It always returns a List of the entity.
Either create a finder method in BrandAllRepo that returns a List of Strings or use an untyped list:
List list = brandAllRepo
.find("select DISTINCT(a.country) from TMdBrandAll a order by a.country")
.page(Page.ofSize(1000)).list();
You know that there will be Strings in the list.
The second option is not so nice. I would use the first option.
I was running in the same problem, but I figured that it works if I use .project(String.class) and GROUP BY instead of DISTINCT:
List<String> list = repo
.find("select a.country from TMdBrandAll a "
+ "group by a.country "
+ "order by a.country")
.project(String.class)
.page(Page.ofSize(1000)).list();
It seems that Panache gets confused by the DISTINCT clause.

How to show values from table without using Entities?

I am trying to do "sql interpreter" in my web-app, only for CRUD. Everything work fine, I am using method prepareStatement() to execute query. But I have problem with operation select :
When I use the select operation only for 1 field, then parsing to a string gives a fairly good result:
for(String x: resultList){
System.out.println(x);
}
Is there any way to execute:
SELECT field_1, field_2, field_3 FROM table;
and print result in console, with some neat form without use Entites?
Well if it isn't possible, is there any way to generate entity "on the fly"? I mean generate Entities using java code.
You could use a native query and explicitly specify which columns you want to select:
String sql = "SELECT field_1, field_2, field_3 FROM table";
Query q = em.createNativeQuery(sql);
List<Object[]> results = q.getResultList();
for (Object[] r : results) {
System.out.println("(field_1, field_2, field_3) = (" + r[0] + ", " + r[1] + ", " + r[2] + ")");
}
With Spring Data JPA Projections
If you already use some entities and Spring Repository then you can add this code to one of them. Thanks Spring Data JPA Projections.
public interface SomeEntityRepository extends Repository<SomeEntity, Long> {
#Query(value = "SELECT field_1, field_2, field_3 FROM table", nativeQuery = true)
List<TableDto> getFromTable();
}
Where TableDto:
public interface TableDto{
Long getField_1();
String getField_2();
String getField_3();
}
With Spring JdbcTemplate
Or use Spring JdbcTemplate:
String query = "SELECT field_1, field_2, field_3 FROM table where id = ?";
List<TableDto> resluts = jdbcTemplate.queryForObject(
query, new Object[] { id }, new TableDtoRowMapper());
public class TableDtoRowMapper implements RowMapper<TableDto> {
#Override
public TableDtomapRow(ResultSet rs, int rowNum) throws SQLException {
TableDto dto = new TableDto();
dto.setField_1(rs.getString("field_1"));
dto.setField_2(rs.getString("field_2"));
dto.setField_3(rs.getString("field_3"));
return dto;
}
}
In this example TableDto is real class with getters and setters.

Select table row using HQL with param

I want to use this HQL query in order to select table row value:
String hql = "select e.token, e.name from Terminals e where e.token = ?";
Terminals terminal = entityManager
.createQuery(hql, Terminals.class)
.setParameter(0, terminalToken)
.getSingleResult();
But I get this result:
java.lang.IllegalArgumentException: Cannot create TypedQuery for query with more than one return using requested result type [org.api.entity.Terminals]
What is the proper way to implement this?
Your query return two Objects token and name and not a Terminals Object.
Instead you can use :
Object[] obj = entityManager
.createQuery(hql)
.setParameter(0, terminalToken)
.getSingleResult();
if(obj != null){
Terminals terminal = new Terminals((String) obj[0], (String) obj[1]);
}
Or you can create a constructor in Terminals class which hold two fields :
public Terminals(String token, String name){
this.token = token;
this.name = name;
}
then change your code to be :
String hql = "select new com.package.Terminals(e.token, e.name) from Terminals e where e.token = ?";
Terminals terminal = entityManager
.createQuery(hql, Terminals.class)
.setParameter(0, terminalToken)
.getSingleResult();
IMO, you should not directly call createQuery to assign to a custom object. And there is a possiblity of returning a list.
Query query = entityManager.createQuery(hql).setParameter(0, "something");<br>
List<Object[]> terminals = query.getResultList();
and retrieve the objects with an index as the ff as an example:
StudentDto dto = new StudentDto();
for(Object[] a: std) {
dto = new StudentDto();
dto.setId((long) a[0]); //id
dto.setName(a[1].toString()); //first name
dto.setPassportNumber(a[2].toString()); //last name
}

Java JTable data from database

I'm new to java and I need help with displaying a joined table/query in jtable.
First, I have done displaying data from 1 table which is:
Select data from 1 table
insert the result to its entity and insert each one of it to a List
return the list to view and insert row to jtable
I am using a DAO pattern, which has a factory, interface, implement, entity and view.
So what if I select data from other table?
Here is my get method in implement for getting book
public List get(String find) {
try {
ps = db.connect().prepareStatement("SELECT * FROM books WHERE title like ? ");
ps.setString(1, "%" + find + "%");
status = db.execute(ps);
if (status) {
books = db.get_result();
listBooks = new ArrayList<>();
while (books.next()) {
entity_books b = new entity_books();
b.setId(books.getInt(1));
b.setId_category(books.getInt(2));
b.setTitle(books.getString(3));
listBooks.add(b);
}
books.close();
return listBooks;
}
} catch (SQLException e) {
System.out.println(e.getMessage());
}
return null;
}
and then in my view:
listBooks = booksDAO.get(find.getText());
model = (DefaultTableModel) book_table.getModel();
model.setRowCount(0);
listBooks.forEach((data) -> {
model.addRow(new Object[]{
data.getId(),
data.getId_category(),
data.getTitle(),
});
});
This works fine, but I want the query to join table so I can see the category name instead of just ID category. I can do the query, but how do I apply that to my code?
Here is the query for joined table
select title,category from book b
join category c on c.id = b.id_category
Normally if I select only 1 table, I would insert it to its entity ( book table -> book entity ), so how do I handle this with multiple tables?
I didn't use prepared statement, but this code works on my end.
String sql = "SELECT * FROM customer c JOIN company cmp ON c.company_idcompany = cmp.idcompany";
ResultSet rs = stmt.executeQuery(sql);
//STEP 5: Extract data from result set
while (rs.next()) {
//Retrieve this from customer table
int id = rs.getInt("idcustomer");
//Retrieve this from customer table
String username = rs.getString("company_username");
//Display values
System.out.println("ID: " + id);
System.out.println("Username: " + username);
}

Populate List of entity class objects from sql ResultSet

So I have this sql query:
"select company, surveys.surveyID, questionID, question, questionScore FROM surveys INNER JOIN (SELECT * FROM companies INNER JOIN "
+ "(SELECT * FROM questions INNER JOIN categories "
+ "ON questions.catID = categories.catID) AS cats "
+ "ON companies.questionID = cats.questionID) AS yes "
+ "ON yes.surveyID = surveys.surveyID WHERE company=?"
'cats' and 'yes' have no meaning and are just victums of my extremely verbose naming scheme.
company is just a string.
The table it returns would look like this:
---------------------------------------------
|companyName|surveyID|questionID|questionScore|
---------------------------------------------
The primary key for this table is (companyName, surveyID AND QuestionID) because each company can have multiple surveys, each survey has a number of questions.
Then I have this class:
public class Company
{
private String companyName;
private String surveyorName;
private String surveyorTitle;
private int surveyID;
private Map<Integer,Integer> questions;
public Company(String name, String surveyor, String surveyerTitle,
int surveyID, Map<Integer, Integer> questions)
{
this.companyName = name;
this.surveyorName = surveyor;
this.surveyorTitle = surveyerTitle;
this.surveyID = surveyID;
this.questions = questions;
}
With a all the getters and setters
For example, say there is a company Mens Insamen. SurveyID is 1.
So
Mens Insamen 1 q1 3
Mens Insamen 1 q2 1
etc...
Now I need to populate a List of Company objects with the data from the sql query. I have tried for a while but couldn't really come up with anything.
If it is (unsurprisingly) unclear (fokol (no) coffee) I can improve it at some point.
Thanks in advance
create class CompanyMapper have a method inside it, pass that method the SQL ResultSet as input, loop thru it and create a list of Company and return it.
class CompanyMapper{
public List<Company> getCompanies(ResultSet rs){
ArrayList<Company> compList = new ArrayList<Company>();
while(...rs has entry...){
//Add new Company to the list
}
return compList;
}
It's really difficult to tell, what you have so far from the question, but if you want to populate a list of your custom objects, then you need to do something like this:
public List<Company> getCompanies() throws SQLException
{
List<Company> result = new ArrayList<Company>();
Connection connection = DriverManager.getConnection(...);
Statement statement = connection.createStatement();
ResultSet set = statement.executeQuery("your query here");
set.beforeFirst();
while(set.next())
{
String textData = set.getString("columnname");
int integerData = set.getInt("columnname");
// you can also use set.getString(columnindex);
Company company = new Company();
company.set(...);
result.add(company);
}
connection.close();
return result;
}
You can achive this simply using arraylist and your while loop
Create your arraylist for compines just outside the loop and add each Company object to this array list using the loop
ArrayList<Company> compList = new ArrayList<Company>();
while{
/*read values to variables and create an object of Company
then add to arraylist as follows **/
Company comp = new Company (name, surveyor, surveyerTitle,surveyID,questions);
compList.add(comp);
}
1- You should create a connection to the database using,
Class.forName(DB_LIBRARY);
connection = DriverManager.getConnection(CONNECTION_PARAMETRS);
Note that you need to replace DB_LIBRARY with the valid driver's library, and CONNECTION_PARAMETERS with your database connection setting (eg. host name, user name, password, ..etc).
2- create a statement, and return a result set
Statement statement = connection.createStatement();
ResultSet rs = statement.executeQuery(your_select_query);
3- loop through the result set and fetch data
Company company;
while(rs.next()){
company = new Company(rs.getString(1),
rs.getString(2),
rs.getString(3),
rs.getInt(4),
new HashMap<Integer, Integer>().put(rs.getInt(5), rs.getInt(6)
}
Note that you can use columns name or their number, also you may use an ArrayList if you want to fetch more than one record, as following
ArrayList<Company> companies = new ArrayList<Company>();
while(rs.next()){
companies.add(new Company(rs.getString(1),
rs.getString(2),
rs.getString(3),
rs.getInt(4),
new HashMap<Integer, Integer>().put(rs.getInt(5), rs.getInt(6));
}

Categories

Resources