I am writing to-do list web app with spring boot. I Have 2 entities: User (fields: userid (ID), username, password Item (fields: serialnumber (ID), task, userid. I want to allow each user to see only his tasks. So I try to pull all the tasks from "task" table. When I try to retrieve information by a custom query, (I think) hibernate fails to read the table. But when I use a built-in method like findAll() from the Repository interface it's works.
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Item {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer serialnumber;
private int userid;
private String task;
public Item() {
}
public Item(int userid, String task) {
this.userid = userid;
this.task = task;
}
public Integer getSerialnumber() {
return serialnumber;
}
public void setSerialnumber(Integer serialnumber) {
this.serialnumber = serialnumber;
}
public int getUserid() {
return userid;
}
public void setUserid(int userid) {
this.userid = userid;
}
public String getTask() {
return task;
}
public void setTask(String task) {
this.task = task;
}
@Override
public String toString() {
return "Item{" +
"serialnumber=" + serialnumber +
", userid=" + userid +
", task='" + task + '\'' +
'}';
}
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.List;
@Controller
public class MainController {
@Autowired
private ItemRepository itemRepository;
.....
@PostMapping("/addItem")
public String addItem(@RequestParam String task,
@CookieValue(name = "id") String id,
Model model) {
Item item = new Item(Integer.valueOf(id), task);
itemRepository.save(item);
print(item.toString());
model.addAttribute("items", itemRepository.findItemsByUserId(Integer.valueOf(id)));
return "list";
}
......
}
import org.springframework.data.repository.CrudRepository;
import java.util.List;
public interface ItemRepository extends CrudRepository<Item, Integer> {
@Query(value = "SELECT task FROM item WHERE userid = ?1", nativeQuery = true)
List<Item> findItemsByUserId(Integer userid);
}
Hibernate: SELECT task FROM item WHERE userid = ?
2022-04-02 23:23:45.733 WARN 36504 --- [nio-8080-exec-6] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 0, SQLState: S0022
2022-04-02 23:23:45.733 ERROR 36504 --- [nio-8080-exec-6] o.h.engine.jdbc.spi.SqlExceptionHelper : Column 'serialnumber' not found.
2022-04-02 23:23:45.743 ERROR 36504 --- [nio-8080-exec-6] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessResourceUsageException: could not execute query; SQL [SELECT task FROM item WHERE userid = ?]; nested exception is org.hibernate.exception.SQLGrammarException: could not execute query] with root cause
java.sql.SQLException: Column 'serialnumber' not found.
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:129) ~[mysql-connector-java-8.0.28.jar:8.0.28]
The problem could probably be that your query specifies the column task
in the select clause, but you're expecting a List<Item>
as return type in the findItemsByUserId
method.
If you want the entire Item
to be returned, then you should change your query to "SELECT * FROM item WHERE userid =?1"
in order to select all columns.
But, if what you want is the field task
only, then you must change the method return type because you want a projection (specific columns selection). That could be done by defining an interface like:
public interface TaskDto {
String getTask();
}
Then you have to choose between:
@Query(value = "SELECT task FROM item WHERE userid = ?1", nativeQuery = true)
List<TaskDto> findItemsByUserId(Integer userid);
and
@Query(value = "SELECT * FROM item WHERE userid = ?1", nativeQuery = true)
List<Item> findItemsByUserId(Integer userid);
@Query(value = "SELECT task FROM item WHERE userid = ?1", nativeQuery = true)
List<Item> findItemsByUserId(Integer userid);
Clearly your query is returning a List of String values and you are trying to cast them to List of your Item entity.
If you want to fetch your result as List of item, use
@Query(value = "SELECT * FROM item WHERE userid = ?1", nativeQuery = true)
List<Item> findItemsByUserId(Integer userid);
or if you want just the String list of tasks, use
@Query(value = "SELECT task FROM item WHERE userid = ?1", nativeQuery = true)
List<String> findItemsByUserId(Integer userid);
Change the caller methods accordingly. As per your error "serialnumber not found", while JPA/Hibernate use reflection API for mapping individual columns from table to their appropriate fields in entity. Since you are specifically fetching "task", all the other columns are missing. Hence "serialnumber not found".
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.