JSP search in more tables in database - java

With this search.jsp, it finds matches all words searched by user, then removes duplicate found users and shows a list of found matches.
I can only search for e-mail, firstname, lastname, username of a user, but I also want to search skills, and show the users who match that skill found.
For example I search for username; Admin, it finds the admin and shows
this person in the result. This works now, but I also want this;;; If
I search for Java, Then I want everybody that has the skill Java to
show up in the result.
I know it is easier with SQL query's, but this is different.
I have provided the models and database information below;
database:
**Table name: User**
userId
emailAddress
firstname
lastname
username
**Table name: user_skill**
User_userId
skills_skillId
**Table name: skill**
skillId
name
where it all happens : : : search.jsp:
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("Hij komt er in");
//get the action
String uri = request.getRequestURI();
String action = uri.substring(uri.lastIndexOf("/") + 1);
if (action.equals("searchUser")) {
Session session = HibernateUtil.getSessionFactory().openSession();
String searchQuery = request.getParameter("searchQuery");
String[] params = searchQuery.split(" ");
// Found users
List<User> usersFound = new ArrayList<User>();
// Exact match
String hqlMatch = this.getSearchHqlQuery(params, "AND");
List<User> exactResult = session.createQuery(hqlMatch).list();
if (exactResult != null && !exactResult.isEmpty()) {
usersFound.addAll(exactResult);
} // Multiple search
else {
String hqlLike = this.getSearchHqlQuery(params, "OR");
List<User> likeResult = session.createQuery(hqlLike).list();
if (likeResult != null && !likeResult.isEmpty()) {
usersFound.addAll(likeResult);
}
}
System.out.println("size:" + usersFound.size());
// set our results on the request and redirect back
request.setAttribute("users", usersFound);
request.setAttribute("usersSize", usersFound.size());
request.setAttribute("usersSizeResults", usersFound.size());
redirect(request, response, "/search.jsp");
session.close();
}
}
private String getSearchHqlQuery(String[] params, String andOrfilter) {
StringBuilder hql = new StringBuilder();
hql.append("from User ");
if (params.length > 0) {
hql.append("where ");
for (int i = 0; i < params.length; i++) {
if (i > 0) {
hql.append(andOrfilter);
}
hql.append(" (username like '%").append(params[i]);
hql.append("%' OR firstname like '%").append(params[i]);
hql.append("%' OR lastname like '%").append(params[i]);
hql.append("%' OR emailAddress like '%").append(params[i]);
hql.append("%') ");
}
}
return hql.toString();
}
model.user.java:
#Entity
public class User implements Serializable{
#Id
#GeneratedValue
private int userId;
private String username, firstname, lastname, emailAddress, position, password;
private String fullName;
private boolean isAdmin;
#ManyToMany
private List<Skill> skills;
public User(){
}
model.skill.java:
#Entity
public class Skill implements Serializable {
#Id
#GeneratedValue
private long skillId;
#Column(columnDefinition = "varchar(25)")
private String name;
#Column(columnDefinition = "varchar(25)")
private String level;
#Column(columnDefinition = "varchar(250)")
private String description;
public Skill() {
}

Add a join to the skills, and an or clause to your query:
select distinct u from User u
left join u.skills skill
where ... (existing or clauses)
or skill.name like :param
Also, your code is opened to SQL injection attacks, and will fail if the param contains a single quote. Use a named parameter as shown above.

Related

How to implement Server-side processing of DataTables with JDBC so that it paginates?

I have a Spring Boot app with DataTables server-side processing and Oracle database. Actually, I started with implementing one of the tutorials. It worked. The tutorial uses JPA. I want to implement the same using JDBC. I made all the corresponding classes, the repository, the new model with same filds but without jpa. But when I tried to fetch the data, it allowed me to get only the first page without a chance to get to the second page. Below I will post the extracts of the original and added code. So, the original tutorial used these classes:
#Entity
#Table(name = "MYUSERS")
public class User {
#Id
#Column(name = "USER_ID")
private Long id;
#Column(name = "USER_NAME")
private String name;
#Column(name = "SALARY")
private String salary;
...getters and setters
}
And
#Entity
public class UserModel {
#Id
private Long id;
private String name;
private String salary;
private Integer totalRecords;
#Transient
private Integer rn;
...getters and setters
}
And I substituted these two classes with one like this:
public class NewUser {
private Long id;
private String name;
private String salary;
private Integer totalRecords;
private Integer rn;
...getters and setters
}
The table itself has only 3 fields: id, name and salary, the other 2 fields are created and filled later.
The repositiry the original Author has for the user looks like this:
public interface UserRepository extends JpaRepository<User, Long> {
#Query(value = "SELECT * FROM MYUSERS", nativeQuery = true)
List<User> findAllByUsernames(List<String> listOfUsernames);
}
My own repository looks like this:
#Repository
public class NewUserRepoImpl extends JdbcDaoSupport implements NewUserRepo {
private static final String SELECT_ALL_SQL = "SELECT USER_ID as id, USER_NAME as name, SALARY as salary FROM MYUSERS";
private final NamedParameterJdbcTemplate namedParameterJdbcTemplate;
private final JdbcTemplate jdbctemplate;
public NewUserRepoImpl(NamedParameterJdbcTemplate namedParameterJdbcTemplate, JdbcTemplate jdbctemplate, DataSource dataSource) {
this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
this.jdbctemplate = jdbctemplate;
setDataSource(dataSource);
}
#Override
public List<NewUser> findAll(PaginationCriteria pagination) {
try {
String paginatedQuery = AppUtil.buildPaginatedQueryForOracle(SELECT_ALL_SQL, pagination);
return jdbctemplate.query(paginatedQuery, newUserRowMapper());
} catch (DataAccessException e) {
throw new EntityNotFoundException("No Entities Found");
}
}
#Bean
public RowMapper<NewUser> newUserRowMapper() {
return (rs, i) -> {
final NewUser newUser = new NewUser();
newUser.setId(rs.getLong("ID"));
newUser.setName(rs.getString("NAME"));
newUser.setSalary(rs.getString("SALARY"));
newUser.setTotalRecords(rs.getInt("TOTAL_RECORDS"));
newUser.setTotalRecords(rs.getInt("RN"));
return newUser;
};
}
}
the buildPaginatedQueryForOracle thing transforms my Query and allows it to get the totalRecords and rn. Below I will post the output of it both for the orifinal and my queries (they are the same, I checked).
So, the main part, the controller. I left the old and new pieces in it for now for debug purposes and just returning one of the results:
#RequestMapping(value="/users/paginated/orcl", method=RequestMethod.GET)
#ResponseBody
public String listUsersPaginatedForOracle(HttpServletRequest request, HttpServletResponse response, Model model) {
DataTableRequest<User> dataTableInRQ = new DataTableRequest<User>(request);
System.out.println(new Gson().toJson(dataTableInRQ));
DataTableRequest<NewUser> dataTableInRQNew = new DataTableRequest<NewUser>(request);
System.out.println(new Gson().toJson(dataTableInRQNew));
PaginationCriteria pagination = dataTableInRQ.getPaginationRequest();
System.out.println(new Gson().toJson(pagination));
PaginationCriteria paginationNew = dataTableInRQNew.getPaginationRequest();
System.out.println(new Gson().toJson(paginationNew));
String baseQuery = "SELECT USER_ID as id, USER_NAME as name, SALARY as salary FROM MYUSERS";
String paginatedQuery = AppUtil.buildPaginatedQueryForOracle(baseQuery, pagination);
String paginatedQueryNew = AppUtil.buildPaginatedQueryForOracle(baseQuery, paginationNew);
System.out.println(paginatedQuery);
System.out.println(paginatedQueryNew);
Query query = entityManager.createNativeQuery(paginatedQuery, UserModel.class);
System.out.println("Query:");
System.out.println(query);
#SuppressWarnings("unchecked")
List<UserModel> userList = query.getResultList();
System.out.println(new Gson().toJson(userList));
#SuppressWarnings("unchecked")
List<NewUser> userListNew = newUserRepo.findAll(paginationNew);
System.out.println(new Gson().toJson(userListNew));
DataTableResults<UserModel> dataTableResult = new DataTableResults<UserModel>();
DataTableResults<NewUser> dataTableResultNew = new DataTableResults<NewUser>();
dataTableResult.setDraw(dataTableInRQ.getDraw());
dataTableResultNew.setDraw(dataTableInRQNew.getDraw());
dataTableResult.setListOfDataObjects(userList);
dataTableResultNew.setListOfDataObjects(userListNew);
if (!AppUtil.isObjectEmpty(userList)) {
dataTableResult.setRecordsTotal(userList.get(0).getTotalRecords()
.toString());
if (dataTableInRQ.getPaginationRequest().isFilterByEmpty()) {
dataTableResult.setRecordsFiltered(userList.get(0).getTotalRecords()
.toString());
} else {
dataTableResult.setRecordsFiltered(Integer.toString(userList.size()));
}
}
if (!AppUtil.isObjectEmpty(userListNew)) {
dataTableResultNew.setRecordsTotal(userListNew.get(0).getTotalRecords()
.toString());
if (dataTableInRQ.getPaginationRequest().isFilterByEmpty()) {
dataTableResultNew.setRecordsFiltered(userListNew.get(0).getTotalRecords()
.toString());
} else {
dataTableResultNew.setRecordsFiltered(Integer.toString(userListNew.size()));
}
}
System.out.println(new Gson().toJson(dataTableResult));
System.out.println(new Gson().toJson(dataTableResultNew));
return new Gson().toJson(dataTableResult);
}
So, I log out everything possible in the console. Here is the output:
{"uniqueId":"1579786571491","draw":"1","start":0,"length":5,"search":"","regex":false,"columns":[{"index":0,"data":"id","name":"ID","searchable":true,"orderable":true,"search":"","regex":false,"sortDir":"ASC"},{"index":1,"data":"name","name":"Name","searchable":true,"orderable":true,"search":"","regex":false},{"index":2,"data":"salary","name":"Salary","searchable":true,"orderable":true,"search":"","regex":false}],"order":{"index":0,"data":"id","name":"ID","searchable":true,"orderable":true,"search":"","regex":false,"sortDir":"ASC"},"isGlobalSearch":false,"maxParamsToCheck":3}
{"uniqueId":"1579786571491","draw":"1","start":0,"length":5,"search":"","regex":false,"columns":[{"index":0,"data":"id","name":"ID","searchable":true,"orderable":true,"search":"","regex":false,"sortDir":"ASC"},{"index":1,"data":"name","name":"Name","searchable":true,"orderable":true,"search":"","regex":false},{"index":2,"data":"salary","name":"Salary","searchable":true,"orderable":true,"search":"","regex":false}],"order":{"index":0,"data":"id","name":"ID","searchable":true,"orderable":true,"search":"","regex":false,"sortDir":"ASC"},"isGlobalSearch":false,"maxParamsToCheck":3}
{"pageNumber":0,"pageSize":5,"sortBy":{"mapOfSorts":{"id":"ASC"}},"filterBy":{"mapOfFilters":{},"globalSearch":false}}
{"pageNumber":0,"pageSize":5,"sortBy":{"mapOfSorts":{"id":"ASC"}},"filterBy":{"mapOfFilters":{},"globalSearch":false}}
SELECT * FROM (SELECT FILTERED_ORDERED_RESULTS.*, COUNT(1) OVER() total_records, ROWNUM AS RN FROM (SELECT BASEINFO.* FROM ( SELECT USER_ID as id, USER_NAME as name, SALARY as salary FROM MYUSERS ) BASEINFO ) FILTERED_ORDERED_RESULTS ORDER BY id ASC ) WHERE RN > (0 * 5) AND RN <= (0 + 1) * 5
SELECT * FROM (SELECT FILTERED_ORDERED_RESULTS.*, COUNT(1) OVER() total_records, ROWNUM AS RN FROM (SELECT BASEINFO.* FROM ( SELECT USER_ID as id, USER_NAME as name, SALARY as salary FROM MYUSERS ) BASEINFO ) FILTERED_ORDERED_RESULTS ORDER BY id ASC ) WHERE RN > (0 * 5) AND RN <= (0 + 1) * 5
Query:
org.hibernate.query.internal.NativeQueryImpl#3ea49a4
[{"id":3,"name":"user3","salary":"300","totalRecords":18},{"id":4,"name":"user4","salary":"400","totalRecords":18},{"id":5,"name":"user5","salary":"500","totalRecords":18},{"id":6,"name":"user6","salary":"600","totalRecords":18},{"id":7,"name":"user7","salary":"700","totalRecords":18}]
[{"id":3,"name":"user3","salary":"300","totalRecords":1},{"id":4,"name":"user4","salary":"400","totalRecords":2},{"id":5,"name":"user5","salary":"500","totalRecords":3},{"id":6,"name":"user6","salary":"600","totalRecords":4},{"id":7,"name":"user7","salary":"700","totalRecords":5}]
{"draw":"1","recordsFiltered":"18","recordsTotal":"18","data":[{"id":3,"name":"user3","salary":"300","totalRecords":18},{"id":4,"name":"user4","salary":"400","totalRecords":18},{"id":5,"name":"user5","salary":"500","totalRecords":18},{"id":6,"name":"user6","salary":"600","totalRecords":18},{"id":7,"name":"user7","salary":"700","totalRecords":18}]}
{"draw":"1","recordsFiltered":"1","recordsTotal":"1","data":[{"id":3,"name":"user3","salary":"300","totalRecords":1},{"id":4,"name":"user4","salary":"400","totalRecords":2},{"id":5,"name":"user5","salary":"500","totalRecords":3},{"id":6,"name":"user6","salary":"600","totalRecords":4},{"id":7,"name":"user7","salary":"700","totalRecords":5}]}
It helped me realize that:
DataTableRequest incoming from the back is the same for both jpa
and jdbc
PaginationCriteria are also the same
paginatedQuery
having been made with the method specified above are the same.
Differences are already seen in the Lists: where the Jpa list
retrieved with native Query has totalRecords as 18 for every row,
the JDBC repo with the same query returns 1,2,3... for every
subsequent row.
It made me think that I should look at the Query made for JPA. But, as you see in the log, System.out.println wasn't able to decipher it for some reason.
Any advice on how to decipher it and more importantly how to get the right total result for each row would be greatly appreciated!!!

Update multiple users by passing list of User ids

I am trying to update some user information by passing List of User-Ids as parameter
i want to update isActive field of User fo which i am passing the user ids.
Below is my controller
#PutMapping
#ResponseStatus(HttpStatus.OK)
#RequestMapping("/UserUpdate")
public ResponseEntity<?> updateUsers(List<Long> userIds) {
**userService.updateUsers(userIds);**
return ResponseEntity.ok(200);
}
updateUsers() is a method in my Service where i have to write the logic
I tried something like below but it's not working
public void updateUsers(List<Long> userIds) {
List<Users> userList= userRepository.findAll();
for (Long i : userIds) {
for ( Users user : userList)
{
if(userRepository.findById(i) != null)
{
user.setIsActive(9L);
user.setUserName("Update Test");
}
my dto
public class UserDto {
private List<Users> userList;
private String appName="Users Project";
// getters and setters removed for brevity
And my Users entity class
#Entity
#Table(name="USERS")
public class Users {
#Id
#Column(name="USER_ID")
#GeneratedValue(strategy = GenerationType.AUTO)
private Long userId;
#Column(name="NAME")
private String userName;
#Column(name="ACTIVE")
private Long isActive;
// getters and setters removed for brevity
Alternatively you can use the following code
#Modifying
#Query("update Users u set u.isActive = ?1, u.userName = ?2 where u.userId in ?3")
void updateUsers(Long isActive, String userName, List<Long> userId);
Add this code in your userRepository and use the method.
public void updateUsers(List<Long> userIds) {
for (Long i : userIds) {
User user = userRepository.findById(i);
if(user != null){
user.setIsActive(9L);
user.setUserName("Update Test");
// call your update method here (this is not stated in your code)
}
}
}

Jdbc returns empty list but SQL query succesfully gets data [Spring]

I am trying to execute this query:
#Override
public UserInfo get(Long id) {
String sql = "SELECT * FROM users WHERE id = ? ";
List<UserInfo> list = jdbcTemplate.query(sql,new UserInfoMapper(),id);
return list.get(0);
}
but jdbc return empty list and I get exception at return line.
But if try to execute directly though the console it returns:
Query, Answer
Query was executed with id 1 and retured correct anwser;
But in method its returned this
I couldn't find any same questions so that may be point at my inattention to something. But I can't see any problem that may cause this. Thanks in advance;
Updated 1
Changing code to
#Override
public UserInfo get(Long id) {
String sql = "SELECT * FROM users WHERE id = ? ";
List<UserInfo> list = jdbcTemplate.query(sql, new Object[] {id},new UserInfoMapper());
return list.get(0);
}
resulted in same: result
Updated 2
#Override
public UserInfo mapRow(ResultSet resultSet, int i) throws SQLException {
UserInfo info = new UserInfo();
info.setId(resultSet.getLong("id"));
info.setFirstname(resultSet.getString("firstname"));
info.setMiddlename(resultSet.getString("middlename"));
info.setLastname(resultSet.getString("lastname"));
info.setUsername(resultSet.getString("username"));
info.setPassword(resultSet.getString("password"));
info.setEmail(resultSet.getString("email"));
info.setMobilephone(resultSet.getString("mobilephone"));
info.setPosition(resultSet.getString("position"));
return info;
}
public class UserInfo {
private Long id;
private String firstname;
private String middlename;
private String lastname;
private String username;
private String password;
private String email;
private String mobilephone;
private String position;
public UserInfo() {
}
}
Getter and setters for each field is there but I think there is no need to show them up.
Check user credentials that you are using to connect database from your application and the user credentials in console. And also check owner schema , table owner schema in your application.

transfer a session between an admin and a user simultaneously spring

I am trying to create a mini chat application that has users table. The users table has a field called isAdmin that identifies that such a particular user is an admin and if isAdmin is set to false such a user is a customer
the user.java table fields
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "userId")
private Long id;
#Column(nullable = false)
private String name;
#Column(unique = true, nullable = false)
private String email;
#Column(nullable = false)
private long timestamp;
#Column(nullable = true)
private boolean isAdmin;
When I am trying to save a user, I try maintaining a request-response setAttribute method parameter using email field to hold the session attribute email is unique in my db
snippet of the code
#RequestMapping(value = "/create-user", method = RequestMethod.POST)
public ModelAndView createUser(HttpServletRequest request,
HttpServletResponse response,
#RequestParam String name,
#RequestParam String email) {
try {
// create new user object
User user = new User();
user.setName(name);
user.setEmail(email);
user.setTimestamp(new Date().getTime());
// save user in db (if new)
if (_userDao.getByEmail(email) == null) {
request.getSession().setAttribute("email", email);
_userDao.save(user);
}
} catch (Exception e) {
e.printStackTrace();
//logger.error("Exception in creating user: ", e.getStackTrace());
}
return new ModelAndView("redirect:/");
}
I am getting all the chats by email using requests.getSession.getAttribute as shown
#ResponseBody
#RequestMapping(value = "/get-all-chats", method = RequestMethod.GET)
public List<Chat> getAllChats(HttpServletRequest request,
HttpServletResponse response) {
String email = (String) request.getSession().getAttribute("email");
try {
if (email != null) {
return _chatDao.getAll(email);
}
} catch (Exception e) {
e.printStackTrace();
logger.error("Exception in fetching chats: ", e.getStackTrace());
}
return null;
}
my dao method has a query to retrieve all the chats based on the email session attribute that was set
public List getAll(String email) {
String hql = "from Chat c where c.user.email = :email";
return _sessionFactory.getCurrentSession().createQuery(hql).setParameter("email", email).list();
my challenge/confusion is that when I fetch the chat the user can only see his chat and the admin can only see his chat. the chat is not transferred between the admin and the user. Kindly assist.

search item in hibernate query (select two tables)

Im having a trouble with my code. i have a view jsp where i can view all items.
When i try to search for a name. It will loop or have a redundancy. I dont know why. looks like this.
BTW i have two tables and a foreign key product[pid] to stock[pid]
public class Product {
#Id
#Column(name="p_id")
private String pid;
#Column(name="p_name")
private String p_name;
#Column(name="c_name")
private String c_name;
#Column(name="b_name")
private String b_name;
//SETTERS & GETTERS
public class Stock {
#Id
#Column(name="s_id")
private int sid;
#Column(name="p_id")
private String pid;
#Column(name="s_quantity")
private String squantity;
#Column(name="s_price")
private String sprice;
#Column(name="s_cost")
private String cost;
//SETTERS AND GETTERS
#Controller
#RequestMapping(method = RequestMethod.POST, value = "/searchItem")
public String searchItem(HttpServletRequest request, ModelMap map,
#RequestParam(value = "page", required = false) Integer page,
#RequestParam(value = "size", required = false) Integer size ) {
String searchProductName = request.getParameter("productName");
String cat = request.getParameter("category");
String bran = request.getParameter("brand");
Product searchProduct = new Product();
searchProduct.setP_name(searchProductName);
searchProduct.setC_name(cat);
searchProduct.setB_name(bran);
int pageSize = (size != null && size != 0) ? size : 25;
int firstResultIndex = (page != null && page > 0) ? (page - 1) * pageSize : 0;
List<Product> productList = catService.getUsers(searchProduct, firstResultIndex, pageSize);
map.addAttribute("productList", productList);
List<Category> cList = catService.getCat();
map.addAttribute("cList", cList);
List<Brand> bList = catService.getBrand();
map.addAttribute("bList", bList);
return "new/list";
}
#DaoImpl
#SuppressWarnings("unchecked")
#Override
public List<Product> getUsers(Product searchProduct, int startPage, int maxResults) {
EntityManager entityManager = transactionManager.getEntityManagerFactory().createEntityManager();
Session session = entityManager.unwrap(Session.class);
SQLQuery query = session.createSQLQuery("FROM product,stock");
boolean paramExists = false;
if (!StringUtility.isStringNullOrEmpty(searchProduct.getC_name())&&!StringUtility.isStringNullOrEmpty(searchProduct.getB_name())) {
//sqlQuerySB.append(" product.c_name LIKE :category AND product.b_name LIKE :brand");
query = session.createSQLQuery("FROM product,stock WHERE product.c_name LIKE :category AND product.b_name LIKE :brand");
paramExists = true;
}
if (!StringUtility.isStringNullOrEmpty(searchProduct.getP_name())) {
query = session.createSQLQuery("SELECT product.p_name,product.c_name,product.b_name,stock.s_quantity,stock.s_price,stock.s_cost FROM product,stock WHERE product.p_name LIKE :productName");
query.setParameter("productName", "%" + searchProduct.getP_name() + "%");
paramExists = true;
}
if (!StringUtility.isStringNullOrEmpty(searchProduct.getC_name())) {
query = session.createSQLQuery("SELECT product.p_name,product.c_name,product.b_name,stock.s_quantity,stock.s_price,stock.s_cost FROM product,stock WHERE product.c_name LIKE :category ");
query.setParameter("category", "" + searchProduct.getC_name() + "");
paramExists = true;
}
query.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);
List<Product> productList = query.list();
if (entityManager.isOpen())
entityManager.close();
return productList;
}
maybe there is a big problem in my DAOimpl on how i query two tables..
need some help/advice. ty.
You are not specifying the join criteria between product and stock:
SELECT
product.p_name,
product.c_name,
product.b_name,
stock.s_quantity,
stock.s_price,
stock.s_cost
FROM product, stock
WHERE product.p_name LIKE :productName
In this case it will return one row for each for each combination of product (with the name) and stock (full table since it does not have any criteria).
Try to specify the join criteria:
SELECT
product.p_name,
product.c_name,
product.b_name,
stock.s_quantity,
stock.s_price,
stock.s_cost
FROM product, stock
WHERE
product.pid = stock.pid
product.p_name LIKE :productName

Categories