"Exception evaluating SpringEL expression" error while trying to iterate List(<Object>) in Thymeleaf Spring Boot

huangapple go评论115阅读模式
英文:

"Exception evaluating SpringEL expression" error while trying to iterate List(<Object>) in Thymeleaf Spring Boot

问题

以下是翻译好的内容:

我对Spring Boot还很陌生,尝试使用JPA/JPQL在两个不相关的实体(Transaction和Item)之间进行连接。但是,在使用Thymeleaf以表格格式显示时,出现了以下错误:

  1. 2020-04-08 21:42:42.463 ERROR 73816 --- [nio-8080-exec-4] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.thymeleaf.exceptions.TemplateProcessingException: Exception evaluating SpringEL expression: "transactiondetail.tid" (template: "index" - line 27, col 21)] with root cause
  2. org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'tid' cannot be found on object of type 'java.lang.Object[]' - maybe not public or not valid?

以下是我的Thymeleaf实现:

  1. <tr th:each="transactiondetail : ${listTransactionDetail}">
  2. <td th:text="${transactiondetail.tid}">TID</td>
  3. <td th:text="${transactiondetail.from_uid}">From UID</td>
  4. <td th:text="${transactiondetail.to_uid}">To UID</td>
  5. <td th:text="${transactiondetail.item_name}">Item Name</td>
  6. <td th:text="${transactiondetail.item_count}">Count</td>
  7. <td th:text="${transactiondetail.status}">Status</td>
  8. </tr>

以下是控制器:

  1. @Autowired
  2. QueryService queryservice;
  3. @RequestMapping("/")
  4. public String viewHomePage(Model model) {
  5. List<TransactionDetail> listTransactionDetail = queryservice.JPQLQuery();
  6. model.addAttribute("listTransactionDetail", listTransactionDetail);
  7. return "index";
  8. }

当我简单地返回queryservice.JPQLQuery()时,我能够获得结果,这意味着连接和列表是有效的。以下是控制器调用的服务:

  1. @Service
  2. public class QueryService implements IQueryService {
  3. @Autowired
  4. EntityManagerFactory emf;
  5. @Override
  6. public List<TransactionDetail> JPQLQuery()
  7. {
  8. EntityManager em = emf.createEntityManager();
  9. Query query = em.createQuery("Select s.tid,s.from_uid,s.to_uid,d.item_name,s.item_count,s.status from Transaction s inner join Item d on s.item_id=d.item_id");
  10. @SuppressWarnings("unchecked")
  11. List<TransactionDetail> tranlist = (List<TransactionDetail>)query.getResultList();
  12. em.close();
  13. return tranlist;
  14. }
  15. }

以下是TransactionDetail类,该类接收连接的实体。正如您所看到的,我具有带有适当名称的构造函数和getter/setter。但仍然无法正确显示详细信息。

  1. public class TransactionDetail {
  2. private Long tid;
  3. private int from_uid;
  4. private int to_uid;
  5. private String item_name;
  6. private int item_count;
  7. private int status;
  8. public TransactionDetail() {
  9. }
  10. public TransactionDetail(Long tid, int from_uid, int to_uid, String item_name, int item_count, int status) {
  11. super();
  12. this.tid = tid;
  13. this.from_uid = from_uid;
  14. this.to_uid = to_uid;
  15. this.item_name = item_name;
  16. this.item_count = item_count;
  17. this.status = status;
  18. }
  19. public Long getTid() {
  20. return tid;
  21. }
  22. public void setTid(Long tid) {
  23. this.tid = tid;
  24. }
  25. public int getFrom_uid() {
  26. return from_uid;
  27. }
  28. public void setFrom_uid(int from_uid) {
  29. this.from_uid = from_uid;
  30. }
  31. public int getTo_uid() {
  32. return to_uid;
  33. }
  34. public void setTo_uid(int to_uid) {
  35. this.to_uid = to_uid;
  36. }
  37. public int getItem_count() {
  38. return item_count;
  39. }
  40. public void setItem_count(int item_count) {
  41. this.item_count = item_count;
  42. }
  43. public int getStatus() {
  44. return status;
  45. }
  46. public void setStatus(int status) {
  47. this.status = status;
  48. }
  49. public String getItem_name() {
  50. return item_name;
  51. }
  52. public void setItem_name(String item_name) {
  53. this.item_name = item_name;
  54. }
  55. }

我猜想问题可能与我如何将query.getResultList()的结果保存到List<TransactionDetail>中有关。那么,您有什么想法可以解决这个问题吗?提前感谢您的帮助!

英文:

I am new to spring boot and attempting to make a join between two unrelated entities (Transaction and Item) using JPA/JPQL. But I am getting the following error while using thymeleaf to display it in a table format:

  1. 2020-04-08 21:42:42.463 ERROR 73816 --- [nio-8080-exec-4] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.thymeleaf.exceptions.TemplateProcessingException: Exception evaluating SpringEL expression: &quot;transactiondetail.tid&quot; (template: &quot;index&quot; - line 27, col 21)] with root cause
  2. org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field &#39;tid&#39; cannot be found on object of type &#39;java.lang.Object[]&#39; - maybe not public or not valid?

Following is my thymeleaf implementation:

  1. &lt;tr th:each=&quot;transactiondetail : ${listTransactionDetail}&quot;&gt;
  2. &lt;td th:text=&quot;${transactiondetail.tid}&quot;&gt;TID&lt;/td&gt;
  3. &lt;td th:text=&quot;${transactiondetail.from_uid}&quot;&gt;From UID&lt;/td&gt;
  4. &lt;td th:text=&quot;${transactiondetail.to_uid}&quot;&gt;To UID&lt;/td&gt;
  5. &lt;td th:text=&quot;${transactiondetail.item_name}&quot;&gt;Item Name&lt;/td&gt;
  6. &lt;td th:text=&quot;${transactiondetail.item_count}&quot;&gt;Count&lt;/td&gt;
  7. &lt;td th:text=&quot;${transactiondetail.status}&quot;&gt;Status&lt;/td&gt;

Following is the controller:

  1. @Autowired
  2. QueryService queryservice;
  3. @RequestMapping(&quot;/&quot;)
  4. public String viewHomePage(Model model) {
  5. List&lt;TransactionDetail&gt; listTransactionDetail = queryservice.JPQLQuery();
  6. model.addAttribute(&quot;listTransactionDetail&quot;, listTransactionDetail);
  7. return &quot;index&quot;;
  8. }

I am able to get the result when I simply return queryservice.JPQLQuery(), which means the joining and listing is working.
Following is the service the controller is calling:

  1. @Service
  2. public class QueryService implements IQueryService {
  3. @Autowired
  4. EntityManagerFactory emf;
  5. @Override
  6. public List&lt;TransactionDetail&gt; JPQLQuery()
  7. {
  8. EntityManager em = emf.createEntityManager();
  9. Query query = em.createQuery(&quot;Select s.tid,s.from_uid,s.to_uid,d.item_name,s.item_count,s.status from Transaction s inner join Item d on s.item_id=d.item_id&quot;);
  10. @SuppressWarnings(&quot;unchecked&quot;)
  11. List&lt;TransactionDetail&gt; tranlist = (List&lt;TransactionDetail&gt;)query.getResultList();
  12. em.close();
  13. return tranlist;
  14. }
  15. }

Shown below is the TransactionDetail class which is taking in the joined entities. As you can see, I have both constructors and getters/setters with proper names. Still not able to display the details correctly.

  1. public class TransactionDetail {
  2. private Long tid;
  3. private int from_uid;
  4. private int to_uid;
  5. private String item_name;
  6. private int item_count;
  7. private int status;
  8. public TransactionDetail() {
  9. }
  10. public TransactionDetail(Long tid, int from_uid, int to_uid, String item_name, int item_count, int status) {
  11. super();
  12. this.tid = tid;
  13. this.from_uid = from_uid;
  14. this.to_uid = to_uid;
  15. this.item_name = item_name;
  16. this.item_count = item_count;
  17. this.status = status;
  18. }
  19. public Long getTid() {
  20. return tid;
  21. }
  22. public void setTid(Long tid) {
  23. this.tid = tid;
  24. }
  25. public int getFrom_uid() {
  26. return from_uid;
  27. }
  28. public void setFrom_uid(int from_uid) {
  29. this.from_uid = from_uid;
  30. }
  31. public int getTo_uid() {
  32. return to_uid;
  33. }
  34. public void setTo_uid(int to_uid) {
  35. this.to_uid = to_uid;
  36. }
  37. public int getItem_count() {
  38. return item_count;
  39. }
  40. public void setItem_count(int item_count) {
  41. this.item_count = item_count;
  42. }
  43. public int getStatus() {
  44. return status;
  45. }
  46. public void setStatus(int status) {
  47. this.status = status;
  48. }
  49. public String getItem_name() {
  50. return item_name;
  51. }
  52. public void setItem_name(String item_name) {
  53. this.item_name = item_name;
  54. }
  55. }

I am guessing the problem has to do with the way I am saving the results from query.getResultList() into List&lt;TransactionDetail&gt;. So any idea how I can solve this issue? Thanks in advance!

答案1

得分: 0

你的Query正在返回ListObject。然而,EntityManager有一个类似的重载,如下所示:

public <T> TypedQuery<T> createQuery(String qlString, Class<T> resultClass);

通过使用第二个参数,你的结果将不需要转换为List<TransactionDetail>,因此你应该向createQuery方法添加第二个参数,在你的情况下它将是TransactionDetails.class

英文:

Your Query is returning List of Object. However, the EntityManager has an overload like so:

public &lt;T&gt; TypedQuery&lt;T&gt; createQuery(String qlString, Class&lt;T&gt; resultClass);

By using the second argument, your result will not need to be casted to List&lt;TransactionDetail&gt;, thus you should add a second argument to the createQuery methiod, which in your case it would be TransactionDetails.class.

答案2

得分: 0

我相信这是因为你的控制器没有返回模型,只返回了视图。尝试修改你的控制器如下:

  1. public ModelAndView viewHomePage(Model model) {

并将模型和视图返回如下:

  1. return new ModelAndView("index", model.asMap());
英文:

I believe it's because you aren't returning the model from your controller, only the view. Try modifying your controller to read,

  1. public ModelAndView viewHomePage(Model model) {

and return the model and view as

  1. return new ModelAndView( &quot;index&quot;, model.asMap());

答案3

得分: 0

问题原来是因为我尝试将查询结果(其中涉及2个不同实体的数据)转换成一个新的类对象。因此,通过更改查询以包括使用构造函数调用创建目标对象的新实例来进行修复:

  1. TypedQuery<TransactionDetail> query = em.createQuery("Select NEW package_name.TransactionDetail(s.tid,s.from_uid,s.to_uid,d.item_name,s.item_count,s.status) from Transaction s inner join Item d on s.item_id=d.item_id", TransactionDetail.class);
  2. List<TransactionDetail> tranlist = query.getResultList();
英文:

Turns out the issue was due my attempt to convert the result from the query (which was bits of 2 different entities) into a new class object. Hence, fixed it by changing the query to include creation of a new instance of the target object with the constructor call:

  1. TypedQuery&lt;TransactionDetail&gt; query = em.createQuery(&quot;Select NEW package_name.TransactionDetail(s.tid,s.from_uid,s.to_uid,d.item_name,s.item_count,s.status) from Transaction s inner join Item d on s.item_id=d.item_id&quot;, TransactionDetail.class);
  2. List&lt;TransactionDetail&gt; tranlist = query.getResultList();

huangapple
  • 本文由 发表于 2020年4月8日 22:29:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/61103169.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定