基于Hibernate的CRUD GUI出现IndexOutOfBoundsException问题求助
解决Hibernate CRUD GUI中的IndexOutOfBoundsException异常
问题概述
你在基于Hibernate开发基础CRUD GUI时,点击搜索按钮触发了java.lang.IndexOutOfBoundsException: Index 0 out of bounds for length 0异常,异常指向代码中getQuantity().get(i)的调用位置。你尝试将Items list改为List<Items>类型,但由于搜索仅返回单个结果,这个调整并没有解决问题。
原因分析
从异常栈信息可以明确定位问题:
- 空列表直接取值导致越界:异常发生在
ArrayList.get()方法,说明getQuantity()返回的是一个空列表,但你在代码中直接调用get(i)(i=0)获取元素,自然触发索引越界。 getQuantity()查询逻辑的局限性:该方法的HQL是查询所有商品的交易数量统计,当你搜索的商品没有对应的Advicenote或Transactions记录时,这个查询会返回空列表。- 空值判断错误:代码中
if (list.equals(null))的写法存在隐患——如果list本身是null,调用equals(null)会直接抛出NullPointerException,正确的空值判断应该是list == null。
解决方案建议
针对上述问题,给出以下分步修复方案:
1. 先判断列表是否为空,再安全取值
在搜索方法的循环逻辑中,先获取getQuantity()的返回列表,检查列表长度后再取值,避免直接索引访问:
// 先获取数量列表,避免重复调用方法 List<ItemAndQuantity> quantityList = getQuantity(); for (int i = 0; i < 1; i++) { Object[] rowData; if (quantityList.size() > i) { // 有数量记录时正常取值 ItemAndQuantity quantity = quantityList.get(i); rowData = new Object[]{ list.getName(), list.getCategory().getName(), quantity.getQuantity(), list.getNetPrice(), list.getNetPrice()*(list.getVatRate()+1), quantity.getQuantity()*list.getNetPrice(), list.getNetPrice()*(list.getVatRate()+1)*quantity.getQuantity() }; } else { // 无数量记录时显示0 rowData = new Object[]{ list.getName(), list.getCategory().getName(), 0, list.getNetPrice(), list.getNetPrice()*(list.getVatRate()+1), 0, 0 }; } dtm.addRow(rowData); }
2. 修复空值判断逻辑
把错误的list.equals(null)替换为正确的list == null:
if (list == null) { JOptionPane.showMessageDialog(null, "No results"); } else { // 后续表格填充逻辑 }
3. 优化getQuantity()的查询精度
当前getQuantity()查询所有商品的数量,效率低且容易出现空结果。可以修改为针对当前搜索到的商品单独查询数量,同时使用左连接和coalesce函数确保即使无交易记录也返回0:
public List<ItemAndQuantity> getQuantity(int itemId) { // 增加itemId参数 List<ItemAndQuantity> quantity = new ArrayList<>(); try { session = sessionFactory.openSession(); transaction = session.beginTransaction(); // 左连接确保无交易时也能返回数据,coalesce将null转为0 Query query = session.createQuery( "select coalesce(sum(t.flow * a.inOrOut), 0) " + "from Items i " + "left join i.transactions t " + "left join t.advicenote a " + "where i.itemId = :itemId " + "group by i.itemId" ); query.setParameter("itemId", itemId); quantity.addAll(query.list()); transaction.commit(); } catch (HibernateException e) { if (transaction != null) { transaction.rollback(); } e.printStackTrace(); } finally { if (session != null && session.isOpen()) { session.close(); } } return quantity; }
然后在搜索方法中调用时传入当前商品的ID:
List<ItemAndQuantity> quantityList = getQuantity(list.getItemId());
4. 完善Session资源管理
在搜索方法中,Session的关闭应该放在finally块中,避免异常时Session无法正常关闭:
Session session = null; Transaction transaction = null; try { session = sessionFactory.openSession(); transaction = session.beginTransaction(); Criteria criteria = session.createCriteria(Items.class); Items list = (Items) criteria.add(Restrictions.eq("name", name).ignoreCase()).uniqueResult(); transaction.commit(); // 后续表格填充逻辑... } catch (Exception e) { if (transaction != null) { transaction.rollback(); } JOptionPane.showMessageDialog(null, e.getMessage()); e.printStackTrace(); } finally { if (session != null && session.isOpen()) { session.close(); } }
内容的提问来源于stack exchange,提问作者Fluellen
相关产品推荐
相关产品推荐

