jdbc left join 3 tables - java

There are three tables <Table 1>, <Table 2> and <Table 3>
My SQL is something like this:
"Select table1.col1, table1.col2, table1.col3, table2.col4, table2.col5, table2.col6,
table3.col7, table3.col8 from Table 1 as table1
LEFT JOIN Table 2 as table2 on (table1.col1 = table2.col4)
LEFT JOIN Table 3 as table3 on (table1.col1 = table3.col8)"
The normal way to get the resultset is:
public List getExportDataList() throws ClassNotFoundException, SQLException {
Connection connect = null;
String url = "jdbc:.....";
String username = "username ";
String password = "password ";
try {
connect = DriverManager.getConnection(url, username, password);
} catch (SQLException ex) {
System.out.println("in exec");
System.out.println(ex.getMessage());
}
List dataList = new ArrayList<>();
PreparedStatement pstmt = connect.prepareStatement(
THE SQL CODE SHOWN ABOVE
}
ResultSet rs = pstmt.executeQuery();
while(rs.next()){
Table1 table1 = new Table1();
table1.setCOL1(rs.getString("col1"));
table1.setCOL2(rs.getString("col2"));
dataList.add(table1);
}
rs.close();
pstmt.close();
connect.close();
return dataList;
}
so that the "dataList" can be used to display the data in Primefaces dataTable.
However, this way only can save the columns in Table1 to the "dataList". I tried to dataList.add(table2) as well as dataList.add(table3) at the same time, but there is an error : "/reportGenerate.xhtml #50,75 value="#{reportData.dateCreated}": The class 'net.picary.model.Liaison' does not have the property 'dateCreated'."
Can someone tell me how to save all the selected columns from the three tables into "dataList"? Or any alternative way to achieve it?

error: "/reportGenerate.xhtml #50,75
value="#{reportData.dateCreated}": The class
'net.picary.model.Liaison' does not have the property 'dateCreated'."
Your problem is not with Query or JDBC, you should to make sure that attribute dateCreated exist in your net.picary.model.Liaison class with getter and setter like this :
private Date dateCreated;
public String name;
public String experience;
public Date getDateCreated() {
return dateCreated;
}
public void setDateCreated(Date dateCreated) {
this.dateCreated = dateCreated;
}
So when your page reportGenerate.xhtml try to load this attribute it not find it, because :
Not exist in your class
It exist but it is private and without getter and setter.
So make sure that your attribute exist and have gtter and setter, this can solve your error.
EDIT
You have two choices :
When you get your result you should to use 3 List of type table1, table2, table3 and fill them in the same loop like this :
List dataList1 = ...;
List dataList2 = ...;
List dataList3 = ...;
while(rs.next()){
table1 = new Table1();
table1.setCOL1(rs.getString("col1"));
...
dataList1.add(table1);
table2 = new Table2();
table2.setCOL1(rs.getString("col1"));
...
dataList2.add(table2);
table3 = new Table3();
table3.setCOL1(rs.getString("col1"));
...
dataList3.add(table3);
}
and in your xhtml page you had to use this three List instead to one
Create a new Object which combine this three Table like this :
class MyObject {
private Table1 table1;
private Table2 table2;
//constructor
//getters and setters
}
Then create a List<MyObject> list = ....; and set information in each table.
Hope you get my point, good luck

First, Check whether column names (col1,col2,col3,..) are with same name in your code in java with all the three db tables (table1,table2,table3).
(ie)
...
Table1 table1 = new Table1();
table1.setCOL1(rs.getString("col1"));
table1.setCOL2(rs.getString("col2"));
dataList.add(table1);
....
In the above code check you have "col1" is in same name with db column in Table1,Table2,Table3.If the column name(s) is different in database and in your code ,add aliases to your MySQL query and match it with same name in your java code.
If the column name matches, then set the column value for your table 2 and 3.
Then, add it to your Datalist.
....
....
table2.setCOL1(rs.getString("col1"));
dataList.add(table2);
....
and so on. Also, check you have added try/catch for your code to avoid exceptions like Nullpointer,SQLException etc.. which may arise during SQL transactions.

Related

Dynamic SQL Projection with multiple joins in QueryDSL

I was trying for dynamic sql projection with join 2 tables. here visibleColumns is the comma separated string(dynamic columns which i want to show in SQL select statement).
QActive qActive = QActive.active;.
QCustomer qCustomer = QCustomer.customer;
QBaseCounterParty qBaseCounterParty = QBaseCounterParty.baseCounterParty;
StringExpression path = Expressions.stringPath(qActive, visibleColumns);
return JPQLQuery<String> resultSet = query.select(path).from(qActive).innerJoin(qActive.customer, qCustomer).on(qInvoice.customer.id.eq(qCustomer.id))
.innerJoin(qBaseCounterParty).on(qCustomer.id.eq(qBaseCounterParty.id)).where(queryDslSpec).orderBy(sort)
.offset(request.getPagination().getStartRow()).limit(request.getPagination().getRowsPerPage());
so whenever i am trying to run it is creating query as below with 400 Bad Request:
select active.docNumber, customerName from Active active inner join Customer customer with active.id = customer.id inner join BaseCounterParty baseCounterParty with customer.id = baseCounterParty.id order by active.transactionDate desc
I am not sure how to select columns from other tables as columns are totally coming as dynamic.
Here some example of using QueryDSL constructor projection, to fill with data any dto.
Warning dto constructor must have same parameters type and etc.
QActive qActive = QActive.active;.
QCustomer qCustomer = QCustomer.customer;
QBaseCounterParty qBaseCounterParty = QBaseCounterParty.baseCounterParty;
return JPQLQuery<SomeDTO> resultSet = query.select(Projections.constructor(SomeDTO.class,
qActive.someValue1,
qBaseCounterParty.someValue2,
qActive.someValue3))
.from(qActive)
.innerJoin(qActive.customer, qCustomer).on(qInvoice.customer.id.eq(qCustomer.id))
.innerJoin(qBaseCounterParty).on(qCustomer.id.eq(qBaseCounterParty.id))
.where(queryDslSpec)
.orderBy(sort)
.offset(request.getPagination().getStartRow()).limit(request.getPagination().getRowsPerPage());
public class SomeDTO {
// QueryDSL Constructor
public SomeDTO(String value1, int value2, String value3) {
this.value1 = value1;
this.value2 = value2;
this.value3 = value3;
}
}

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));
}

Hibernate: queries by example and many-to-one relationships

Let's say those are my entities:
Table1.java
#Entity
public class Table1 {
// Many to one
private Table2 table2;
// Raw attributes
// ...
}
Table2.java
#Entity
public class Table2 {
// Many to one
private Table3 table3;
// Raw attributes
// ...
}
Table3.java
#Entity
public class Table3 {
// Raw attributes
private String lang; // "fr", "en", "de"...
}
I wanna list all the Table1 rows that have a table2.table3.lang that equals en. I tried to use a query by example:
Table3 table3Example = new Table3();
table3Example.setLang("en");
Table2 table2Example = new Table2();
table2Example.setTable3(table3Example);
Table1 table1Example = new Table1();
table1Example.setTable2(table2Example);
table1Repository.findByExample(table1Example);
The problem is that .findByExample(table1Example) returns all the rows of the database, no matter of the lang, which means that the filter isn't considered at all :(
Any help would be appreciated :)
PS: no exception is thrown, .findByExample(table1Example) just returns all of the Table1 rows.
Try something like this:
Query q = entityManager.createQuery("Select o from Table1 o where o.table2.table3.lang = :lang");
q.setParameter("lang", "en");
List<Table1> r = (List<Table1>)q.getResultList();
To see why you get all the rows in Table1, make sure that you have
<property name="hibernate.show_sql" value="true"/>
in your persistence.xml and then watch the log to see the actual select that hibernate executes.

PreparedStatement not returning ordered ResultSet

I am having some problems and I'm sure it's something stupid.
So I have a query like
SELECT name, id, xyz FROM table ORDER BY ?
then later down the road setting the ? doing a
ps.setString(1, "xyz");
I am outputting the query and the value of xyz in the console. When I loop through the ResultSet returned from the PreparedStatement the values are not in the correct order. They are in the returned order as if I had left the ORDER BY clause off. When I copy/paste the query and the value into TOAD it runs and comes back correctly.
Any ideas to why the ResultSet is not coming back in the correct order?
The database will see the query as
SELECT name, id, xyz FROM table ORDER BY 'xyz'
That is to say, order by a constant expression (the string 'xyz' in this case). Any order will satisfy that.
? is for parameters, you can't use it to insert column names. The generated statements will look something like
SELECT name, id, xyz FROM table ORDER BY 'xyz'
so that your entries are sorted by the string 'xyz', not by the content of column xyz.
Why not run:
ps.setInteger(1, 3);
Regards.
EDIT: AFAIK Oracle 10g supports it.
PreparedStatement placeholders are not intend for tablenames nor columnnames. They are only intented for actual column values.
You can however use String#format() for this, that's also the way I often do. For example:
private static final String SQL_SELECT_ORDER = "SELECT name, id, xyz FROM table ORDER BY %s";
...
public List<Data> list(boolean ascending) {
String order = ascending ? "ASC" : "DESC";
String sql = String.format(SQL_SELECT_ORDER, order);
...
Another example:
private static final String SQL_SELECT_IN = "SELECT name, id, xyz FROM table WHERE id IN (%s)";
...
public List<Data> list(Set<Long> ids) {
String placeHolders = generatePlaceHolders(ids.size()); // Should return "?,?,?..."
String sql = String.format(SQL_SELECT_IN, placeHolders);
...
DAOUtil.setValues(preparedStatement, ids.toArray());
...
The database will see the query like this
SELECT name, id, xyz FROM table ORDER BY 'xyz'
I think you should add more variable like order_field and order_direction
I assume you have a method like below and I give you an example to solve it
pulbic List<Object> getAllTableWithOrder(String order_field, String order_direction) {
String sql = "select * from table order by ? ?";
//add connection here
PreparedStatement ps = (PreparedStatement) conn.prepareStatement(sql);
ps.setString(1,order_field);
ps.setString(2,order_direction);
logger.info(String.valueOf(ps)); //returns something like: com.mysql.jdbc.JDBC4PreparedStatement#a0ff86: select * from table order by 'id' 'desc'
String sqlb = String.valueOf(ps);
String sqlc = sqlb.replace("'"+order_field+"'", order_field);
String sqld = sqlc.replace("'"+order_direction+"'", order_direction);
String[] normQuery = sqld.split(":");
ResultSet result = conn.createStatement().executeQuery(normQuery[1]);
while(result.next()) {
//iteration
}
}

Categories

Resources