I new in java and try to use spring framework. I have a question.
By example, I have table :
employee (id_employee, name)
employee_product (id_employee_product, id_employee, product_name)
if I select an employee data from my Employee table, I can map it in a POJO model User and define the tables structure in that model, like this:
public class Employee {
private final int id_employee;
private final String nama;
public Employee(int id_employee, String nama){
this.id_employee = id_employee;
this.nama = nama;
}
public int getId() {
return id_employee;
}
public String getNama() {
return nama;
}
}
And this is the map from jdbcTemplate:
final String sql = "SELECT id_employee, nama FROM employee";
return jdbcTemplate.query(sql, (resultSet, i) -> {
return new Employee(
resultSet.getInt("id_employee"),
resultSet.getString("nama")
);
});
That is clear example for select data from 1 table.
My question is, how to map data from query if my data is custom query? Such us using join and select custom field from that tables, Am I need to create POJO every query?
Sometimes I need to select only employee.id_employee, and employee.name field from my employee table.
And in another controller I need to select employee.id_employee from my employee table.
In another case, I need only select employee.name, and employee_product.product_name
Is there an alternative to map the data without creating POJO for every case?
Create a one POJO combining two tables like this
public class Employee {
private int id_employee;
private String name;
private int id_employee_product.
private String product_name
//getter and setters
//Don't create a constructor its Entiry
}
Now by using a BeanPropertyRowMapper Doc Link write your repository like
public List<Employee> fetchEmployeeProduct(){
JdbcTemplate jdbcTemplate = new JdbcTemplate("Your_DataSource");
StringBuilder query = new StringBuilder();
query.append("Your Query");
List<Employee> employeeProductList =
jdbcTemplate.query(query.toString(), new BeanPropertyRowMapper<Employee>(Employee.class));
}
Make sure SELECT clause in the query and Employee POJO's filed name is same.
Once if you execute your query it will automatically map to POJO. You no need to write a custom mapper BeanPropertyRowMapperwill take care of mapping.
Related
How to do you insert an object array into a database by using JDBCTemplate? I have an object array of variable length coming in from my POST method in my controller.
I have looked at these,
http://www.java2s.com/Tutorial/Java/0417__Spring/PassParameterAsObjectArray.htm
How to insert Integer array into postgresql table using jdbcTemplate in Java Springboot?
As well as others and they do not seem to fit to what I need.
Controller
// Service
#Autowired
private DBService tool;
#PostMapping(value = "/foo")
private void storeData(#RequestBody CustomObject[] customObjects) {
// Calls service then DAO
tool.storeData(customObjects);
}
POJO Object
public class CustomObject {
private Integer id;
private String name;
// Getters & Setters for class attributes
...
}
DAO Is this right? Because I want to store each array element separately, with each element having its own row.
#Autowired
private JdbcTemplate temp;
public void storeData(CustomObject[] customObjects) {
String sql = "INSERT INTO FooBar(name) VALUES(\'" + customObjects.toString() + "\');";
temp.update(sql);
}
Expected
I want to store the array of my custom object from POST into my database with each element having its own row.
Ideally you would want to iterate over the array and save each "CustomObject" .
private JdbcTemplate temp;
public void storeData(CustomObject customObject) {
String sql = "INSERT INTO FooBar VALUES(" + customObject.id + ",\'"+ customObject.name +"\');";
temp.update(sql);
}
#PostMapping(value = "/foo")
private void storeData(#RequestBody CustomObject[] customObjects) {
// Save each record individually
customObjects.forEach { customObject ->
tool.storeData(customObjects);
}
}
I'm using NamedParameterJDBCTemplate in Spring and trying to select only few columns instead of all columns. But I am facing an error - org.SpringFramework.BadSqlGrammarException.
My DAO Class has the following code.
#Autowired
private NamedParameterJdbcTemplate npjt;
... // Some other code
String query = "SELECT t.name AS NAME, t.city AS CITY FROM t WHERE t.country = :countryName";
MapSqlParameterSource param = new MapSqlParameterSource();
param.addValue("countryName", "GERMANY");
List<Person> pl = npjt.query(sql,param, new PersonMapper()); // Throws org.SpringFramework.BadSqlGrammarException
The Person Model Class is as follows.
public class Person {
String name;
String city;
String country;
String address;
// All getters & setters
}
The Mapper Class is as follows.
public class PersonMapper implements RowMapper {
public Person mapRow(ResultSet rs, int rowNum) throws SQLException {
Person p = new Person();
p.setName(rs.getString("NAME"));
p.setCity(rs.getString("CITY"));
return p;
}
}
Facing the error only if select a few columns. When doing a select *, things are working fine.
Your query looks bad.
Try with
String query = "SELECT t.name AS NAME, t.city AS CITY FROM Person t WHERE t.country = :countryName";
Assuming that your table/class name is 'Person'.
Otherwise replace 'Person' with the good table name
How can I execute Multiple SQL statements in a single sql query using hibernate native sql.
String sql = "SELECT * FROM user; SELECT * FROM product;";
UserVO valueObject = new UserVO();
databaseObject.select(sql, valueObject);
Database Object
public List select(String sql, Object valueObject) throws Exception {
Session session = Entitlement.getSessionFactory().openSession();
session.beginTransaction();
List list = session.createSQLQuery(sql).setProperties(valueObject).list();
session.close();
return list;
}
Use union to form a query which has same returning data
(Select EMPLOYEEID as id, EMPLOYEE_NAME as name, "EMPOYEE" as type) UNION (SELECT PRODUCTID as id, Product_NAME as name, "PRODUCT" as type)
form an Entity to hold it
class EntityDetail {
String id;
String name;
String type;
}
I have added an additional column value type to simply identify from which table row is coming from. And yes you will need to form a proper Entity with all valid annotations the above Entity is just for example.
just a lateral approach.
public List<List<Object[]>> execute(String sqls, Object valueObject) throws Exception {
String[] queries = sqls.split(";");
List<List<Object[]>> result = new ArrayList<>();
for(int i=0; i<queries.length; i++) {
result.add(this.select(queries[i], valueObject));
}
return result;
}
I'm designing a hospitality app. and having some problem with fetching multiple rows from database. I'm using Hibernate, Spring Web MVC, mySQL and JSP. I have layers as Controller, Service, Dao, Model. I've designed a search page to see the user profiles according to their city. For example when I write 'NewYork' to the city field on the search screen it will show a list of user profiles who live in NewYork and mark isHosting value as true.
Here is my User class:
public class User{
#Column(unique = true, nullable = false)
private String username;
...
private String city;
private String isHosting;
public boolean isHosting() {
return hosting;
}
public void setHosting(boolean hosting) {
this.hosting = hosting;
}
...
}
Search class:
public class Search {
private String city;
private String sdate;
private String fdate;
private String numOfvisitor;
...
}
This my Dao class:
#Repository
public class SearchDao extends GenericDao<User> {
public User findByUserCity(final String city){
final Criteria c = createCriteria(User.class).add(Restrictions.eq("city", city));
return (User) c.uniqueResult();
}
}
Service class:
#Service
#Transactional
public class SearchService extends GenericService<User>{
#Autowired
public SearchService(SearchDao dao) {
super(dao);
}
...
public User findByUserCity(final String city) {
return ((SearchSurferDao) this.dao).findByUserCity(city);
}
}
And Controller class:
#RequestMapping(value = "/search", method = RequestMethod.GET)
public ModelAndView search(#ModelAttribute Search search) {
User user = SearchService.findByUserCity(search.getCity());
ModelAndView result = new ModelAndView("hello");
...
result.addObject("username", user.getUsername());
return result;
}
I know that I need to write a database query which returns a list and the list is needed to be send to JSP file and with foreach tag I can see profiles on the screen. But how can write a database query to get such a list from db, actually put it in which class? What I need to do in Controller? Where can I check isHosting value?
Criteria c = createCriteria(User.class).add(Restrictions.eq("city", city));
return (User) c.uniqueResult();
The above code does create a query which finds the users with the given city. But it assumes that only one user exists in the given city, which is probably not the case. The method should be
public List<User> findByUserCity(final String city) {
Criteria c = createCriteria(User.class).add(Restrictions.eq("city", city));
return c.list();
}
Also, The Criteria API leads to hard to read code, and is suitable when you have to dynamically compose a query based on several search criteria. For such a static query, you should use HQL:
public List<User> findByUserCity(String city) {
return session.createQuery("select u from User u where u.city = :city")
.setString("city", city)
.list();
}
To see only isHosting=true user you have two ways:
Fetch only isHosting=true users
For this, your query will change to :
session.createQuery("select u from User u where u.city = :city and u.isHosting is true")
.setString("city", city)
.list();
Fetch all users with matching city, then filter them in your java code.
ArrayList<User> fetchedList=session.createQuery("select u from User u where u.city = :city")
.setString("city", city)
.list();
for(User u: fetchedList){
if(u.isHosting()){
display(u);
}
}
Here, I would recommend using first option, as db queries are generally faster than iterating through fetched data on the client side.
However, if you want to have info on all of your users and want to filter isHosting=true users, the 2nd option is better than asking DB again and again.
This is my user.java domain class is
public class User {
private Integer iduser;
private String user_name;
private String user_activation_key;
private String user_password;
private String user_email;
private Character registered;
public Integer getIduser() {
return iduser;
}
public void setIduser(Integer iduser) {
this.iduser = iduser;
}
public String getUser_name() {
return user_name;
}.....more code
And in a another Test class I have Coded as follow.
SQLQuery query = session.createSQLQuery("select * from user");
List<User> availableUsers = new ArrayList<User>();
availableUsers=(List<User>)query.list();
query is a SQLQuery (Hibernate implementation) to get user list from DB.
But I can't cast the (query.list) to List<User>.
I'm getting class cast exception. availableUser is a object list.
What steps should I follow.
Use HQL
SQLQuery query = session.createQuery("from User"); //note here User is POJO class name
List<User> availableUsers = new ArrayList<User>();
availableUsers=(List<User>)query.list();
18.1.1. Scalar queries
These will return a List of Object arrays (Object[]) with scalar values for each column in the user table. Hibernate will use ResultSetMetadata to deduce the actual order and types of the returned scalar values.
Use addScalar() method when using createSQLQuery see more
query.list() returns List<Object>.
Each object is actually an Object array (Object[]) which has the whole row.
For example, if you are getting all the Employee results, then the list is as follows:-
{ {emp_id,emp_name,other_emp_col} , {emp_id,emp_name,other_emp_col}, {emp_id,emp_name,other_emp_col} ....}
So for retrieving them you will have to iterate the list of Object and cast iterator.next() into an Object array and then construct your own User object.
For example:-
List<Object> userList = query.list();
Iterator<Object> itr = userList.iterator();
while(itr.hasNext()){
Object[] userRow = (Object[]) itr.next();
User userObj = new User();
userObj.setName(userRow[0]);
}
To save all these efforts as Aniket said, use HQL