关于ResultSet can not re-read row data for column 2 错误及其原因

本文探讨了使用MSSQL2000官方驱动时,遇到包含Blob或Clob字段的表所产生的错误,并提供了解决方案。介绍了如何通过调整查询顺序或更换第三方驱动来避免错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

用MS SQL2000遇到这样的问题了,我所采用的ms sql的驱动是官方的.在网上查了一下,感觉说得零零散散,模模糊糊,有错有对.真是鱼龙混杂,感觉像进了市场买菜.......我尽我的掌握和有限的水平综合起来总结一下:

        这个问题的原因是只要表里有Blob或者Clob两个当中的一种或者这两个字段都存在,并且采用MS SQL官方的驱动.就会产生这个错误!并且查看了很多资料,很多总结都指出这种错误仅MS SQL2000才会出现.

     网上总结的微软驱动的缺点及解决方案:    数据库表:TChannle

(1)如果采用jdbc-odbc驱动,那么就必须按照查询顺序来一次读取(不论有没有image或text类型)
(2)如果采用微软提供的ms sql server jdbc driver,如果查询语句中,不存在image或text类型字段,那么可以按照无序获取
(3) 如果采用微软提供的ms sql server jdbc driver,如果查询语句中,存在image或text类型字段,那么就必须按照顺序读取,否则就会报告Driver]ResultSet can not re-read row data for column之类的错误
(4)如果想不查询语句中有没有image或text类型字段,都可以不按照顺序获取,或重复获取。
    上面四点,什么算是无序获取和顺序获取?我迷糊半天,又查了半天,查到一个例子:
    数据库表:TestTable
    表字段及类型:
         guid char(38)
         title varchar(100)
         content Text
         username varchar(20)
    查询sql语句:
         select guid,username,content,title from TestTable where····
    java代码:
         rs.getString("guid");
         rs.getBinaryStream("content");
         rs.getString("username");
    -----------------------------------------------------------
    上面那段代码,很不荣幸是。使用微软的驱动,必然会报错(就是上面说的那个错误)。如果你跟踪的话,必然是这一行:rs.getString("username")抛出错误。

    那么,如果你把rs.getString("username")和rs.getBinaryStream("content");位置互换以下,会怎么样呢。结果就是可以正常运行。

    为什么会出现这种情况呢,因为微软的驱动,在包含了blob或clob类型(就是Image和Text类型)的字段。那么就必须按照select顺序查询,且不支持重复查询。

    还有重复查询,又是什么意思?再举个例子:


    表字段及类型:

           chanleid主键   int自增

          chanName频道名称  varchar

          creatTime    varchar

          creatUserName  varchar

    所谓重复查询的语句:

           select    chanName, chanName, chanName from  TChannle

    可以查出三个频道名称,即chanName.这就是重复查询!

如何解决这个问题呢?

    (1)  使用Sql Server 2000的第三方驱动就没有这样的问题存在。网上说找到jTDS取代微软的SQLServer2000的JDBC驱动.

    要使用jTDS驱动,配置要做一些变动:


   数据库URL:jdbc:jtds:sqlserver://localhost:1433;DatabaseName=XXX
   驱动类:net.sourceforge.jtds.jdbc.Driver
  jtds驱动的下载地址:http://sourceforge.net/projects/jtds/  

   (2)hibernate映射文件里面不映射CLOB或者BLOB字段,当遇到CLOB或者BLOB字段时,直接映射成String类型的,MS SQL数据库会自动转成text类型的.

package org.example; import javax.swing.*; import javax.swing.table.DefaultTableModel; import java.awt.*; import java.awt.event.*; import java.math.BigDecimal; import java.sql.*; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; // 数据库工具类 class MySQL { private static final String URL = "jdbc:mysql://localhost:3306/cangchu"; private static final String USER = "root"; private static final String PASSWORD = "123456"; static { try { Class.forName("com.mysql.cj.jdbc.Driver"); } catch (ClassNotFoundException e) { showError("数据库驱动加载失败", e); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USER, PASSWORD); } // 用户验证 public static boolean validateUser(String username, String password) { String sql = "SELECT * FROM `管理员` WHERE `用户名`=? AND `密码`=?"; try (Connection conn = getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, username); pstmt.setString(2, password); return pstmt.executeQuery().next(); } catch (SQLException e) { showError("用户验证错误", e); return false; } } // 更新密码 public static boolean updatePassword(String username, String newPassword) { String sql = "UPDATE 管理员 SET 密码 = ? WHERE 用户名 = ?"; try (Connection conn = getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, newPassword); pstmt.setString(2, username); return pstmt.executeUpdate() > 0; } catch (SQLException e) { showError("密码更新错误", e); return false; } } // 读取表数据 public static List<Map<String, Object>> readTable(String tableName) { List<Map<String, Object>> result = new ArrayList<>(); String sql = "SELECT * FROM " + tableName; try (Connection conn = getConnection(); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql)) { ResultSetMetaData metaData = rs.getMetaData(); int columnCount = metaData.getColumnCount(); while (rs.next()) { Map<String, Object> row = new LinkedHashMap<>(); for (int i = 1; i <= columnCount; i++) { row.put(metaData.getColumnName(i), rs.getObject(i)); } result.add(row); } } catch (SQLException e) { showError("数据库查询错误", e); } return result; } // 执行更新操作 public static int executeUpdate(String sql, Object... params) { try (Connection conn = getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { for (int i = 0; i < params.length; i++) { pstmt.setObject(i + 1, params[i]); } return pstmt.executeUpdate(); } catch (SQLException e) { showError("数据库操作错误: " + sql, e); return -1; } } // 检查外键是否存在 public static boolean checkForeignKeyExists(String table, String column, String value) { String sql = "SELECT COUNT(*) FROM " + table + " WHERE " + column + " = ?"; try (Connection conn = getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, value); try (ResultSet rs = pstmt.executeQuery()) { return rs.next() && rs.getInt(1) > 0; } } catch (SQLException e) { showError("外键检查错误", e); return false; } } // 更新仓库容量 public static void updateWarehouseCapacity(String warehouseId, int amount, boolean isInbound) { String sql = "UPDATE 仓库 SET 剩余容量 = 剩余容量 + ? WHERE 仓库编号 = ?"; executeUpdate(sql, isInbound ? -amount : amount, warehouseId); } // 更新商品库存 public static void updateProductStock(String productId, int amount, boolean isInbound) { String sql = "UPDATE 商品 SET 库存 = 库存 + ? WHERE 商品编号 = ?"; executeUpdate(sql, isInbound ? amount : -amount, productId); } // 显示错误信息 static void showError(String message, Exception e) { String errorMsg = message + ": " + e.getMessage(); if (e instanceof SQLException) { SQLException sqlEx = (SQLException) e; errorMsg += "\nSQL状态: " + sqlEx.getSQLState(); errorMsg += "\n错误码: " + sqlEx.getErrorCode(); } JOptionPane.showMessageDialog(null, errorMsg, "数据库错误", JOptionPane.ERROR_MESSAGE); e.printStackTrace(); } } // 登录界面 class LoginScreen { private JFrame frame; private JTextField usernameField; private JPasswordField passwordField; public void show() { frame = new JFrame("用户登录"); frame.setSize(400, 250); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLocationRelativeTo(null); JPanel panel = new JPanel(new GridLayout(3, 2, 10, 10)); panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); panel.add(new JLabel("账号:")); usernameField = new JTextField(); panel.add(usernameField); panel.add(new JLabel("密码:")); passwordField = new JPasswordField(); panel.add(passwordField); JButton loginButton = new JButton("登录"); loginButton.addActionListener(e -> login()); JButton resetButton = new JButton("重置"); resetButton.addActionListener(e -> reset()); JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 10)); buttonPanel.add(loginButton); buttonPanel.add(resetButton); frame.add(panel, BorderLayout.CENTER); frame.add(buttonPanel, BorderLayout.SOUTH); frame.setVisible(true); } private void login() { String username = usernameField.getText().trim(); String password = new String(passwordField.getPassword()); if (username.isEmpty() || password.isEmpty()) { JOptionPane.showMessageDialog(frame, "账号和密码不能为空!"); return; } if (MySQL.validateUser(username, password)) { JOptionPane.showMessageDialog(frame, "登录成功!"); frame.dispose(); new MainMenu(username).setVisible(true); } else { JOptionPane.showMessageDialog(frame, "账号或密码错误!"); passwordField.setText(""); passwordField.requestFocus(); } } private void reset() { usernameField.setText(""); passwordField.setText(""); } public static void main(String[] args) { SwingUtilities.invokeLater(() -> new LoginScreen().show()); } } // 主菜单界面 class MainMenu extends JFrame { private String currentUser; public MainMenu(String username) { super("仓库管理系统 - 当前用户: " + username); this.currentUser = username; setSize(900, 600); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLocationRelativeTo(null); JTabbedPane tabPane = new JTabbedPane(); tabPane.addTab("仓库管理", new WarehouseManager().createPanel()); tabPane.addTab("商品管理", new ProductManager().createPanel()); tabPane.addTab("供应商管理", new SupplierManager().createPanel()); tabPane.addTab("出入库管理", new InventoryManager().createPanel()); tabPane.addTab("管理员管理", new AdminManager(currentUser).createPanel()); add(tabPane); } } // 仓库管理 class WarehouseManager { private JTable table; private DefaultTableModel model; public JPanel createPanel() { JPanel panel = new JPanel(new BorderLayout()); // 工具栏 JToolBar toolbar = new JToolBar(); JButton refreshBtn = new JButton("刷新"); JButton addBtn = new JButton("添加"); JButton editBtn = new JButton("修改"); JButton deleteBtn = new JButton("删除"); JButton searchBtn = new JButton("搜索"); refreshBtn.addActionListener(e -> refreshData()); addBtn.addActionListener(e -> addWarehouse()); editBtn.addActionListener(e -> editWarehouse()); deleteBtn.addActionListener(e -> deleteWarehouse()); toolbar.add(refreshBtn); toolbar.add(addBtn); toolbar.add(editBtn); toolbar.add(deleteBtn); // 搜索面板 JPanel searchPanel = new JPanel(); JTextField searchField = new JTextField(15); searchBtn.addActionListener(e -> searchWarehouse(searchField.getText())); searchPanel.add(new JLabel("仓库名称:")); searchPanel.add(searchField); searchPanel.add(searchBtn); // 表格 model = new DefaultTableModel() { @Override public boolean isCellEditable(int row, int column) { return false; } }; table = new JTable(model); table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); // 设置列名 model.setColumnIdentifiers(new String[]{"仓库编号", "仓库名", "总容量", "剩余容量"}); refreshData(); // 布局 JPanel topPanel = new JPanel(new BorderLayout()); topPanel.add(toolbar, BorderLayout.NORTH); topPanel.add(searchPanel, BorderLayout.CENTER); panel.add(topPanel, BorderLayout.NORTH); panel.add(new JScrollPane(table), BorderLayout.CENTER); return panel; } private void refreshData() { List<Map<String, Object>> data = MySQL.readTable("仓库"); model.setRowCount(0); for (Map<String, Object> row : data) { model.addRow(new Object[]{ row.get("仓库编号"), row.get("仓库名"), row.get("总容量"), row.get("剩余容量") }); } } private void searchWarehouse(String keyword) { List<Map<String, Object>> data = new ArrayList<>(); String sql = "SELECT * FROM 仓库 WHERE 仓库名 LIKE ?"; try (Connection conn = MySQL.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, "%" + keyword + "%"); ResultSet rs = pstmt.executeQuery(); while (rs.next()) { Map<String, Object> row = new LinkedHashMap<>(); row.put("仓库编号", rs.getString("仓库编号")); row.put("仓库名", rs.getString("仓库名")); row.put("总容量", rs.getInt("总容量")); row.put("剩余容量", rs.getInt("剩余容量")); data.add(row); } } catch (SQLException e) { MySQL.showError("搜索错误", e); } model.setRowCount(0); for (Map<String, Object> row : data) { model.addRow(new Object[]{ row.get("仓库编号"), row.get("仓库名"), row.get("总容量"), row.get("剩余容量") }); } } private void addWarehouse() { JDialog dialog = new JDialog((Frame) null, "添加仓库", true); dialog.setSize(400, 300); dialog.setLayout(new GridLayout(5, 2, 10, 10)); dialog.setLocationRelativeTo(null); JTextField idField = new JTextField(); JTextField nameField = new JTextField(); JTextField capacityField = new JTextField(); JTextField remainingField = new JTextField(); JButton submitBtn = new JButton("提交"); submitBtn.addActionListener(e -> { try { String id = idField.getText().trim(); String name = nameField.getText().trim(); int capacity = Integer.parseInt(capacityField.getText().trim()); int remaining = Integer.parseInt(remainingField.getText().trim()); // 验证输入 if (id.isEmpty() || name.isEmpty()) { JOptionPane.showMessageDialog(dialog, "仓库编号和名称不能为空!"); return; } if (capacity <= 0 || remaining < 0) { JOptionPane.showMessageDialog(dialog, "容量必须为正数!"); return; } if (remaining > capacity) { JOptionPane.showMessageDialog(dialog, "剩余容量必须等于总容量!"); return; } if (remaining <capacity) { JOptionPane.showMessageDialog(dialog, "剩余容量必须等于总容量!"); return; } // 执行SQL if (MySQL.executeUpdate( "INSERT INTO 仓库 (仓库编号, 仓库名, 总容量, 剩余容量) VALUES (?, ?, ?, ?)", id, name, capacity, remaining) > 0) { JOptionPane.showMessageDialog(dialog, "仓库添加成功!"); dialog.dispose(); refreshData(); } else { JOptionPane.showMessageDialog(dialog, "仓库添加失败!"); } } catch (NumberFormatException ex) { JOptionPane.showMessageDialog(dialog, "请输入有效的数字!"); } }); JButton cancelBtn = new JButton("取消"); cancelBtn.addActionListener(e -> dialog.dispose()); // 添加组件 dialog.add(new JLabel("仓库编号:")); dialog.add(idField); dialog.add(new JLabel("仓库名称:")); dialog.add(nameField); dialog.add(new JLabel("总容量:")); dialog.add(capacityField); dialog.add(new JLabel("剩余容量:")); dialog.add(remainingField); dialog.add(submitBtn); dialog.add(cancelBtn); dialog.setVisible(true); } private void editWarehouse() { int row = table.getSelectedRow(); if (row == -1) { JOptionPane.showMessageDialog(null, "请选择要修改的仓库"); return; } String id = (String) table.getValueAt(row, 0); String name = (String) table.getValueAt(row, 1); int capacity = (int) table.getValueAt(row, 2); int remaining = (int) table.getValueAt(row, 3); JDialog dialog = new JDialog((Frame) null, "修改仓库", true); dialog.setSize(400, 300); dialog.setLayout(new GridLayout(5, 2, 10, 10)); dialog.setLocationRelativeTo(null); JTextField idField = new JTextField(id); idField.setEditable(false); JTextField nameField = new JTextField(name); JTextField capacityField = new JTextField(String.valueOf(capacity)); JTextField remainingField = new JTextField(String.valueOf(remaining)); JButton submitBtn = new JButton("提交"); submitBtn.addActionListener(e -> { try { String newName = nameField.getText().trim(); int newCapacity = Integer.parseInt(capacityField.getText().trim()); int newRemaining = Integer.parseInt(remainingField.getText().trim()); // 验证输入 if (newName.isEmpty()) { JOptionPane.showMessageDialog(dialog, "仓库名称不能为空!"); return; } if (newCapacity <= 0 || newRemaining < 0) { JOptionPane.showMessageDialog(dialog, "容量必须为正数!"); return; } if (newRemaining > newCapacity) { JOptionPane.showMessageDialog(dialog, "剩余容量不能大于总容量!"); return; } // 执行SQL if (MySQL.executeUpdate( "UPDATE 仓库 SET 仓库名=?, 总容量=?, 剩余容量=? WHERE 仓库编号=?", newName, newCapacity, newRemaining, id) > 0) { JOptionPane.showMessageDialog(dialog, "仓库信息更新成功!"); dialog.dispose(); refreshData(); } else { JOptionPane.showMessageDialog(dialog, "仓库信息更新失败!"); } } catch (NumberFormatException ex) { JOptionPane.showMessageDialog(dialog, "请输入有效的数字!"); } }); JButton cancelBtn = new JButton("取消"); cancelBtn.addActionListener(e -> dialog.dispose()); // 添加组件 dialog.add(new JLabel("仓库编号:")); dialog.add(idField); dialog.add(new JLabel("仓库名称:")); dialog.add(nameField); dialog.add(new JLabel("总容量:")); dialog.add(capacityField); dialog.add(new JLabel("剩余容量:")); dialog.add(remainingField); dialog.add(submitBtn); dialog.add(cancelBtn); dialog.setVisible(true); } private void deleteWarehouse() { int row = table.getSelectedRow(); if (row == -1) { JOptionPane.showMessageDialog(null, "请选择要删除的仓库"); return; } String id = (String) table.getValueAt(row, 0); String name = (String) table.getValueAt(row, 1); int confirm = JOptionPane.showConfirmDialog( null, "确定要删除仓库: " + name + " (ID: " + id + ")?", "确认删除", JOptionPane.YES_NO_OPTION ); if (confirm == JOptionPane.YES_OPTION) { if (hasInventoryRecords(id)) { JOptionPane.showMessageDialog(null, "该仓库有出入库记录,无法删除!"); return; } if (MySQL.executeUpdate("DELETE FROM 仓库 WHERE 仓库编号=?", id) > 0) { JOptionPane.showMessageDialog(null, "仓库删除成功!"); refreshData(); } else { JOptionPane.showMessageDialog(null, "仓库删除失败!"); } } } private boolean hasInventoryRecords(String warehouseId) { String sql = "SELECT COUNT(*) FROM 出入库 WHERE 仓库ID = ?"; try (Connection conn = MySQL.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, warehouseId); try (ResultSet rs = pstmt.executeQuery()) { return rs.next() && rs.getInt(1) > 0; } } catch (SQLException e) { MySQL.showError("记录检查错误", e); return true; } } } // 商品管理 class ProductManager { private JTable table; private DefaultTableModel model; public JPanel createPanel() { JPanel panel = new JPanel(new BorderLayout()); // 工具栏 JToolBar toolbar = new JToolBar(); JButton refreshBtn = new JButton("刷新"); JButton addBtn = new JButton("添加"); JButton editBtn = new JButton("修改"); JButton deleteBtn = new JButton("删除"); refreshBtn.addActionListener(e -> refreshData()); addBtn.addActionListener(e -> addProduct()); editBtn.addActionListener(e -> editProduct()); deleteBtn.addActionListener(e -> deleteProduct()); toolbar.add(refreshBtn); toolbar.add(addBtn); toolbar.add(editBtn); toolbar.add(deleteBtn); // 搜索面板 JPanel searchPanel = new JPanel(); JTextField nameField = new JTextField(10); JTextField categoryField = new JTextField(10); JButton searchBtn = new JButton("搜索"); searchBtn.addActionListener(e -> searchProducts( nameField.getText().trim(), categoryField.getText().trim() )); searchPanel.add(new JLabel("商品名称:")); searchPanel.add(nameField); searchPanel.add(new JLabel("商品类别:")); searchPanel.add(categoryField); searchPanel.add(searchBtn); // 表格 model = new DefaultTableModel() { @Override public boolean isCellEditable(int row, int column) { return false; } }; table = new JTable(model); table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); // 设置列名 model.setColumnIdentifiers(new String[]{ "商品编号", "商品名", "供应商ID", "产地", "类别", "价格", "库存" }); refreshData(); // 布局 JPanel topPanel = new JPanel(new BorderLayout()); topPanel.add(toolbar, BorderLayout.NORTH); topPanel.add(searchPanel, BorderLayout.CENTER); panel.add(topPanel, BorderLayout.NORTH); panel.add(new JScrollPane(table), BorderLayout.CENTER); return panel; } private void refreshData() { List<Map<String, Object>> data = MySQL.readTable("商品"); model.setRowCount(0); for (Map<String, Object> row : data) { model.addRow(new Object[]{ row.get("商品编号"), row.get("商品名"), row.get("供应商ID"), row.get("产地"), row.get("类别"), row.get("价格"), row.get("库存") }); } } private void searchProducts(String name, String category) { List<Map<String, Object>> data = new ArrayList<>(); String sql = "SELECT * FROM 商品 WHERE 商品名 LIKE ? AND 类别 LIKE ?"; try (Connection conn = MySQL.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, "%" + name + "%"); pstmt.setString(2, "%" + category + "%"); ResultSet rs = pstmt.executeQuery(); while (rs.next()) { Map<String, Object> row = new LinkedHashMap<>(); row.put("商品编号", rs.getString("商品编号")); row.put("商品名", rs.getString("商品名")); row.put("供应商ID", rs.getString("供应商ID")); row.put("产地", rs.getString("产地")); row.put("类别", rs.getString("类别")); row.put("价格", rs.getBigDecimal("价格")); row.put("库存", rs.getInt("库存")); data.add(row); } } catch (SQLException e) { MySQL.showError("搜索错误", e); } model.setRowCount(0); for (Map<String, Object> row : data) { model.addRow(new Object[]{ row.get("商品编号"), row.get("商品名"), row.get("供应商ID"), row.get("产地"), row.get("类别"), row.get("价格"), row.get("库存") }); } } private void addProduct() { JDialog dialog = new JDialog((Frame) null, "添加商品", true); dialog.setSize(500, 400); dialog.setLayout(new GridLayout(7, 2, 10, 10)); dialog.setLocationRelativeTo(null); JTextField idField = new JTextField(); JTextField nameField = new JTextField(); JTextField supplierIdField = new JTextField(); JTextField originField = new JTextField(); JTextField categoryField = new JTextField(); JTextField priceField = new JTextField(); JTextField stockField = new JTextField("0"); // 默认库存为0 JButton submitBtn = new JButton("提交"); submitBtn.addActionListener(e -> { try { String id = idField.getText().trim(); String name = nameField.getText().trim(); String supplierId = supplierIdField.getText().trim(); String origin = originField.getText().trim(); String category = categoryField.getText().trim(); double price = Double.parseDouble(priceField.getText().trim()); int stock = Integer.parseInt(stockField.getText().trim()); // 验证输入 if (id.isEmpty() || name.isEmpty()) { JOptionPane.showMessageDialog(dialog, "商品编号和名称不能为空!"); return; } if (!MySQL.checkForeignKeyExists("供应商", "供应商编号", supplierId)) { JOptionPane.showMessageDialog(dialog, "供应商ID不存在!"); return; } if (price <= 0) { JOptionPane.showMessageDialog(dialog, "价格必须大于0!"); return; } if (stock < 0) { JOptionPane.showMessageDialog(dialog, "库存不能为负数!"); return; } // 执行SQL if (MySQL.executeUpdate( "INSERT INTO 商品 (商品编号, 商品名, 供应商ID, 产地, 类别, 价格, 库存) VALUES (?, ?, ?, ?, ?, ?, ?)", id, name, supplierId, origin, category, price, stock) > 0) { JOptionPane.showMessageDialog(dialog, "商品添加成功!"); dialog.dispose(); refreshData(); } else { JOptionPane.showMessageDialog(dialog, "商品添加失败!"); } } catch (NumberFormatException ex) { JOptionPane.showMessageDialog(dialog, "请输入有效的数字!"); } }); JButton cancelBtn = new JButton("取消"); cancelBtn.addActionListener(e -> dialog.dispose()); // 添加组件 dialog.add(new JLabel("商品编号:")); dialog.add(idField); dialog.add(new JLabel("商品名称:")); dialog.add(nameField); dialog.add(new JLabel("供应商ID:")); dialog.add(supplierIdField); dialog.add(new JLabel("产地:")); dialog.add(originField); dialog.add(new JLabel("类别:")); dialog.add(categoryField); dialog.add(new JLabel("价格:")); dialog.add(priceField); dialog.add(new JLabel("库存:")); dialog.add(stockField); dialog.add(submitBtn); dialog.add(cancelBtn); dialog.setVisible(true); } private void editProduct() { int row = table.getSelectedRow(); if (row == -1) { JOptionPane.showMessageDialog(null, "请选择要修改的商品"); return; } String id = (String) table.getValueAt(row, 0); String name = (String) table.getValueAt(row, 1); String supplierId = (String) table.getValueAt(row, 2); String origin = (String) table.getValueAt(row, 3); String category = (String) table.getValueAt(row, 4); BigDecimal price = (BigDecimal) table.getValueAt(row, 5); int stock = (int) table.getValueAt(row, 6); JDialog dialog = new JDialog((Frame) null, "修改商品", true); dialog.setSize(500, 400); dialog.setLayout(new GridLayout(7, 2, 10, 10)); dialog.setLocationRelativeTo(null); JTextField idField = new JTextField(id); idField.setEditable(false); JTextField nameField = new JTextField(name); JTextField supplierIdField = new JTextField(supplierId); JTextField originField = new JTextField(origin); JTextField categoryField = new JTextField(category); JTextField priceField = new JTextField(price.toString()); JTextField stockField = new JTextField(String.valueOf(stock)); JButton submitBtn = new JButton("提交"); submitBtn.addActionListener(e -> { try { String newName = nameField.getText().trim(); String newSupplierId = supplierIdField.getText().trim(); String newOrigin = originField.getText().trim(); String newCategory = categoryField.getText().trim(); double newPrice = Double.parseDouble(priceField.getText().trim()); int newStock = Integer.parseInt(stockField.getText().trim()); // 验证输入 if (newName.isEmpty()) { JOptionPane.showMessageDialog(dialog, "商品名称不能为空!"); return; } if (!MySQL.checkForeignKeyExists("供应商", "供应商编号", newSupplierId)) { JOptionPane.showMessageDialog(dialog, "供应商ID不存在!"); return; } if (newPrice <= 0) { JOptionPane.showMessageDialog(dialog, "价格必须大于0!"); return; } if (newStock < 0) { JOptionPane.showMessageDialog(dialog, "库存不能为负数!"); return; } // 执行SQL if (MySQL.executeUpdate( "UPDATE 商品 SET 商品名=?, 供应商ID=?, 产地=?, 类别=?, 价格=?, 库存=? WHERE 商品编号=?", newName, newSupplierId, newOrigin, newCategory, newPrice, newStock, id) > 0) { JOptionPane.showMessageDialog(dialog, "商品信息更新成功!"); dialog.dispose(); refreshData(); } else { JOptionPane.showMessageDialog(dialog, "商品信息更新失败!"); } } catch (NumberFormatException ex) { JOptionPane.showMessageDialog(dialog, "请输入有效的数字!"); } }); JButton cancelBtn = new JButton("取消"); cancelBtn.addActionListener(e -> dialog.dispose()); // 添加组件 dialog.add(new JLabel("商品编号:")); dialog.add(idField); dialog.add(new JLabel("商品名称:")); dialog.add(nameField); dialog.add(new JLabel("供应商ID:")); dialog.add(supplierIdField); dialog.add(new JLabel("产地:")); dialog.add(originField); dialog.add(new JLabel("类别:")); dialog.add(categoryField); dialog.add(new JLabel("价格:")); dialog.add(priceField); dialog.add(new JLabel("库存:")); dialog.add(stockField); dialog.add(submitBtn); dialog.add(cancelBtn); dialog.setVisible(true); } private void deleteProduct() { int row = table.getSelectedRow(); if (row == -1) { JOptionPane.showMessageDialog(null, "请选择要删除的商品"); return; } String id = (String) table.getValueAt(row, 0); String name = (String) table.getValueAt(row, 1); int confirm = JOptionPane.showConfirmDialog( null, "确定要删除商品: " + name + " (ID: " + id + ")?", "确认删除", JOptionPane.YES_NO_OPTION ); if (confirm == JOptionPane.YES_OPTION) { if (hasInventoryRecords(id)) { JOptionPane.showMessageDialog(null, "该商品有出入库记录,无法删除!"); return; } if (MySQL.executeUpdate("DELETE FROM 商品 WHERE 商品编号=?", id) > 0) { JOptionPane.showMessageDialog(null, "商品删除成功!"); refreshData(); } else { JOptionPane.showMessageDialog(null, "商品删除失败!"); } } } private boolean hasInventoryRecords(String productId) { String sql = "SELECT COUNT(*) FROM 出入库 WHERE 商品ID = ?"; try (Connection conn = MySQL.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, productId); try (ResultSet rs = pstmt.executeQuery()) { return rs.next() && rs.getInt(1) > 0; } } catch (SQLException e) { MySQL.showError("记录检查错误", e); return true; } } } // 供应商管理 class SupplierManager { private JTable table; private DefaultTableModel model; public JPanel createPanel() { JPanel panel = new JPanel(new BorderLayout()); // 工具栏 JToolBar toolbar = new JToolBar(); JButton refreshBtn = new JButton("刷新"); JButton addBtn = new JButton("添加"); JButton editBtn = new JButton("修改"); JButton deleteBtn = new JButton("删除"); refreshBtn.addActionListener(e -> refreshData()); addBtn.addActionListener(e -> addSupplier()); editBtn.addActionListener(e -> editSupplier()); deleteBtn.addActionListener(e -> deleteSupplier()); toolbar.add(refreshBtn); toolbar.add(addBtn); toolbar.add(editBtn); toolbar.add(deleteBtn); // 搜索面板 JPanel searchPanel = new JPanel(); JTextField nameField = new JTextField(10); JTextField regionField = new JTextField(10); JButton searchBtn = new JButton("搜索"); searchBtn.addActionListener(e -> searchSuppliers( nameField.getText().trim(), regionField.getText().trim() )); searchPanel.add(new JLabel("供应商名称:")); searchPanel.add(nameField); searchPanel.add(new JLabel("所在地区:")); searchPanel.add(regionField); searchPanel.add(searchBtn); // 表格 model = new DefaultTableModel() { @Override public boolean isCellEditable(int row, int column) { return false; } }; table = new JTable(model); table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); // 设置列名 model.setColumnIdentifiers(new String[]{ "供应商编号", "供应商名", "供应商地址", "供应商电话" }); refreshData(); // 布局 JPanel topPanel = new JPanel(new BorderLayout()); topPanel.add(toolbar, BorderLayout.NORTH); topPanel.add(searchPanel, BorderLayout.CENTER); panel.add(topPanel, BorderLayout.NORTH); panel.add(new JScrollPane(table), BorderLayout.CENTER); return panel; } private void refreshData() { List<Map<String, Object>> data = MySQL.readTable("供应商"); model.setRowCount(0); for (Map<String, Object> row : data) { model.addRow(new Object[]{ row.get("供应商编号"), row.get("供应商名"), row.get("供应商地址"), row.get("供应商电话") }); } } private void searchSuppliers(String name, String region) { List<Map<String, Object>> data = new ArrayList<>(); String sql = "SELECT * FROM 供应商 WHERE 供应商名 LIKE ? AND 供应商地址 LIKE ?"; try (Connection conn = MySQL.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, "%" + name + "%"); pstmt.setString(2, "%" + region + "%"); ResultSet rs = pstmt.executeQuery(); while (rs.next()) { Map<String, Object> row = new LinkedHashMap<>(); row.put("供应商编号", rs.getString("供应商编号")); row.put("供应商名", rs.getString("供应商名")); row.put("供应商地址", rs.getString("供应商地址")); row.put("供应商电话", rs.getString("供应商电话")); data.add(row); } } catch (SQLException e) { MySQL.showError("搜索错误", e); } model.setRowCount(0); for (Map<String, Object> row : data) { model.addRow(new Object[]{ row.get("供应商编号"), row.get("供应商名"), row.get("供应商地址"), row.get("供应商电话") }); } } private void addSupplier() { JDialog dialog = new JDialog((Frame) null, "添加供应商", true); dialog.setSize(500, 300); dialog.setLayout(new GridLayout(5, 2, 10, 10)); dialog.setLocationRelativeTo(null); JTextField idField = new JTextField(); JTextField nameField = new JTextField(); JTextField addressField = new JTextField(); JTextField phoneField = new JTextField(); JButton submitBtn = new JButton("提交"); submitBtn.addActionListener(e -> { String id = idField.getText().trim(); String name = nameField.getText().trim(); String address = addressField.getText().trim(); String phone = phoneField.getText().trim(); // 验证输入 if (id.isEmpty() || name.isEmpty()) { JOptionPane.showMessageDialog(dialog, "供应商编号和名称不能为空!"); return; } // 执行SQL if (MySQL.executeUpdate( "INSERT INTO 供应商 (供应商编号, 供应商名, 供应商地址, 供应商电话) VALUES (?, ?, ?, ?)", id, name, address, phone) > 0) { JOptionPane.showMessageDialog(dialog, "供应商添加成功!"); dialog.dispose(); refreshData(); } else { JOptionPane.showMessageDialog(dialog, "供应商添加失败!"); } }); JButton cancelBtn = new JButton("取消"); cancelBtn.addActionListener(e -> dialog.dispose()); // 添加组件 dialog.add(new JLabel("供应商编号:")); dialog.add(idField); dialog.add(new JLabel("供应商名称:")); dialog.add(nameField); dialog.add(new JLabel("供应商地址:")); dialog.add(addressField); dialog.add(new JLabel("供应商电话:")); dialog.add(phoneField); dialog.add(submitBtn); dialog.add(cancelBtn); dialog.setVisible(true); } private void editSupplier() { int row = table.getSelectedRow(); if (row == -1) { JOptionPane.showMessageDialog(null, "请选择要修改的供应商"); return; } String id = (String) table.getValueAt(row, 0); String name = (String) table.getValueAt(row, 1); String address = (String) table.getValueAt(row, 2); String phone = (String) table.getValueAt(row, 3); JDialog dialog = new JDialog((Frame) null, "修改供应商", true); dialog.setSize(500, 300); dialog.setLayout(new GridLayout(5, 2, 10, 10)); dialog.setLocationRelativeTo(null); JTextField idField = new JTextField(id); idField.setEditable(false); JTextField nameField = new JTextField(name); JTextField addressField = new JTextField(address); JTextField phoneField = new JTextField(phone); JButton submitBtn = new JButton("提交"); submitBtn.addActionListener(e -> { String newName = nameField.getText().trim(); String newAddress = addressField.getText().trim(); String newPhone = phoneField.getText().trim(); // 验证输入 if (newName.isEmpty()) { JOptionPane.showMessageDialog(dialog, "供应商名称不能为空!"); return; } // 执行SQL if (MySQL.executeUpdate( "UPDATE 供应商 SET 供应商名=?, 供应商地址=?, 供应商电话=? WHERE 供应商编号=?", newName, newAddress, newPhone, id) > 0) { JOptionPane.showMessageDialog(dialog, "供应商信息更新成功!"); dialog.dispose(); refreshData(); } else { JOptionPane.showMessageDialog(dialog, "供应商信息更新失败!"); } }); JButton cancelBtn = new JButton("取消"); cancelBtn.addActionListener(e -> dialog.dispose()); // 添加组件 dialog.add(new JLabel("供应商编号:")); dialog.add(idField); dialog.add(new JLabel("供应商名称:")); dialog.add(nameField); dialog.add(new JLabel("供应商地址:")); dialog.add(addressField); dialog.add(new JLabel("供应商电话:")); dialog.add(phoneField); dialog.add(submitBtn); dialog.add(cancelBtn); dialog.setVisible(true); } private void deleteSupplier() { int row = table.getSelectedRow(); if (row == -1) { JOptionPane.showMessageDialog(null, "请选择要删除的供应商"); return; } String id = (String) table.getValueAt(row, 0); String name = (String) table.getValueAt(row, 1); int confirm = JOptionPane.showConfirmDialog( null, "确定要删除供应商: " + name + " (ID: " + id + ")?", "确认删除", JOptionPane.YES_NO_OPTION ); if (confirm == JOptionPane.YES_OPTION) { if (hasRelatedProducts(id)) { JOptionPane.showMessageDialog(null, "该供应商有商品记录,无法删除!"); return; } if (MySQL.executeUpdate("DELETE FROM 供应商 WHERE 供应商编号=?", id) > 0) { JOptionPane.showMessageDialog(null, "供应商删除成功!"); refreshData(); } else { JOptionPane.showMessageDialog(null, "供应商删除失败!"); } } } private boolean hasRelatedProducts(String supplierId) { String sql = "SELECT COUNT(*) FROM 商品 WHERE 供应商ID = ?"; try (Connection conn = MySQL.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, supplierId); try (ResultSet rs = pstmt.executeQuery()) { return rs.next() && rs.getInt(1) > 0; } } catch (SQLException e) { MySQL.showError("记录检查错误", e); return true; } } } // 出入库管理 class InventoryManager { private JTabbedPane tabbedPane = new JTabbedPane(); private Map<String, DefaultTableModel> models = new LinkedHashMap<>(); private Map<String, JTable> tables = new LinkedHashMap<>(); public JPanel createPanel() { JPanel panel = new JPanel(new BorderLayout()); tabbedPane.addTab("入库管理", createInventoryPanel("入库")); tabbedPane.addTab("出库管理", createInventoryPanel("出库")); panel.add(tabbedPane, BorderLayout.CENTER); return panel; } private JPanel createInventoryPanel(String type) { JPanel panel = new JPanel(new BorderLayout()); // 工具栏 JToolBar toolbar = new JToolBar(); JButton addBtn = new JButton("添加"); JButton editBtn = new JButton("修改"); JButton deleteBtn = new JButton("删除"); JButton refreshBtn = new JButton("刷新"); JButton capacityBtn = new JButton("仓库容量"); JButton stockBtn = new JButton("商品库存"); addBtn.addActionListener(e -> addRecord(type)); editBtn.addActionListener(e -> editRecord(type)); deleteBtn.addActionListener(e -> deleteRecord(type)); refreshBtn.addActionListener(e -> refreshData(type)); capacityBtn.addActionListener(e -> showWarehouseCapacity()); stockBtn.addActionListener(e -> showProductStock()); toolbar.add(addBtn); toolbar.add(editBtn); toolbar.add(deleteBtn); toolbar.add(refreshBtn); toolbar.add(capacityBtn); toolbar.add(stockBtn); // 搜索面板 JPanel searchPanel = new JPanel(); JTextField warehouseField = new JTextField(8); JTextField productField = new JTextField(8); JTextField dateField = new JTextField(8); JButton searchBtn = new JButton("搜索"); searchBtn.addActionListener(e -> searchRecords( type, warehouseField.getText().trim(), productField.getText().trim(), dateField.getText().trim() )); searchPanel.add(new JLabel("仓库ID:")); searchPanel.add(warehouseField); searchPanel.add(new JLabel("商品ID:")); searchPanel.add(productField); searchPanel.add(new JLabel("日期:")); searchPanel.add(dateField); searchPanel.add(searchBtn); // 表格 DefaultTableModel model = new DefaultTableModel() { @Override public boolean isCellEditable(int row, int column) { return false; } }; model.setColumnIdentifiers(new String[]{"编号", "仓库ID", "商品ID", "商品数量", "日期", "类型"}); models.put(type, model); JTable table = new JTable(model); table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); tables.put(type, table); refreshData(type); // 布局 JPanel topPanel = new JPanel(new BorderLayout()); topPanel.add(toolbar, BorderLayout.NORTH); topPanel.add(searchPanel, BorderLayout.CENTER); panel.add(topPanel, BorderLayout.NORTH); panel.add(new JScrollPane(table), BorderLayout.CENTER); return panel; } private void refreshData(String type) { List<Map<String, Object>> data = MySQL.readTable("出入库"); DefaultTableModel model = models.get(type); model.setRowCount(0); for (Map<String, Object> row : data) { if (type.equals(row.get("类型"))) { model.addRow(new Object[]{ row.get("编号"), row.get("仓库ID"), row.get("商品ID"), row.get("商品数量"), row.get("日期"), row.get("类型") }); } } } private void searchRecords(String type, String warehouseId, String productId, String date) { DefaultTableModel model = models.get(type); model.setRowCount(0); StringBuilder sql = new StringBuilder("SELECT * FROM 出入库 WHERE 类型=?"); List<Object> params = new ArrayList<>(); params.add(type); if (!warehouseId.isEmpty()) { sql.append(" AND 仓库ID LIKE ?"); params.add("%" + warehouseId + "%"); } if (!productId.isEmpty()) { sql.append(" AND 商品ID LIKE ?"); params.add("%" + productId + "%"); } if (!date.isEmpty()) { sql.append(" AND 日期 LIKE ?"); params.add("%" + date + "%"); } try (Connection conn = MySQL.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql.toString())) { for (int i = 0; i < params.size(); i++) { pstmt.setObject(i + 1, params.get(i)); } ResultSet rs = pstmt.executeQuery(); while (rs.next()) { model.addRow(new Object[]{ rs.getString("编号"), rs.getString("仓库ID"), rs.getString("商品ID"), rs.getInt("商品数量"), rs.getString("日期"), rs.getString("类型") }); } } catch (SQLException e) { MySQL.showError("搜索错误", e); } } private void addRecord(String type) { JDialog dialog = new JDialog((Frame) null, type + "记录", true); dialog.setSize(500, 300); dialog.setLayout(new GridLayout(5, 2, 10, 10)); dialog.setLocationRelativeTo(null); JTextField warehouseField = new JTextField(); JTextField productField = new JTextField(); JTextField quantityField = new JTextField(); JTextField dateField = new JTextField(); JButton submitBtn = new JButton("提交"); submitBtn.addActionListener(e -> { try { String warehouseId = warehouseField.getText().trim(); String productId = productField.getText().trim(); int quantity = Integer.parseInt(quantityField.getText().trim()); String date = dateField.getText().trim(); // 验证输入 if (warehouseId.isEmpty() || productId.isEmpty() || date.isEmpty()) { JOptionPane.showMessageDialog(dialog, "所有字段都必须填写!"); return; } if (!MySQL.checkForeignKeyExists("仓库", "仓库编号", warehouseId)) { JOptionPane.showMessageDialog(dialog, "仓库ID不存在!"); return; } if (!MySQL.checkForeignKeyExists("商品", "商品编号", productId)) { JOptionPane.showMessageDialog(dialog, "商品ID不存在!"); return; } if (quantity <= 0) { JOptionPane.showMessageDialog(dialog, "商品数量必须大于0!"); return; } boolean isInbound = "入库".equals(type); // 检查容量/库存 if (isInbound && !checkWarehouseCapacity(warehouseId, quantity)) { JOptionPane.showMessageDialog(dialog, "仓库剩余容量不足!"); return; } if (!isInbound && !checkProductStock(productId, quantity)) { JOptionPane.showMessageDialog(dialog, "商品库存不足!"); return; } // 执行SQL if (MySQL.executeUpdate( "INSERT INTO 出入库 (仓库ID, 商品ID, 商品数量, 日期, 类型) VALUES (?, ?, ?, ?, ?)", warehouseId, productId, quantity, date, type) > 0) { // 更新仓库容量和商品库存 MySQL.updateWarehouseCapacity(warehouseId, quantity, isInbound); MySQL.updateProductStock(productId, quantity, isInbound); JOptionPane.showMessageDialog(dialog, type + "记录添加成功!"); dialog.dispose(); refreshData(type); } else { JOptionPane.showMessageDialog(dialog, type + "记录添加失败!"); } } catch (NumberFormatException ex) { JOptionPane.showMessageDialog(dialog, "请输入有效的数字!"); } }); JButton cancelBtn = new JButton("取消"); cancelBtn.addActionListener(e -> dialog.dispose()); // 添加组件 dialog.add(new JLabel("仓库ID:")); dialog.add(warehouseField); dialog.add(new JLabel("商品ID:")); dialog.add(productField); dialog.add(new JLabel("商品数量:")); dialog.add(quantityField); dialog.add(new JLabel("日期(YYYY-MM-DD):")); dialog.add(dateField); dialog.add(submitBtn); dialog.add(cancelBtn); dialog.setVisible(true); } private boolean checkWarehouseCapacity(String warehouseId, int quantity) { String sql = "SELECT 剩余容量 FROM 仓库 WHERE 仓库编号 = ?"; try (Connection conn = MySQL.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, warehouseId); try (ResultSet rs = pstmt.executeQuery()) { return rs.next() && rs.getInt("剩余容量") >= quantity; } } catch (SQLException e) { MySQL.showError("容量检查错误", e); return false; } } private boolean checkProductStock(String productId, int quantity) { String sql = "SELECT 库存 FROM 商品 WHERE 商品编号 = ?"; try (Connection conn = MySQL.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, productId); try (ResultSet rs = pstmt.executeQuery()) { return rs.next() && rs.getInt("库存") >= quantity; } } catch (SQLException e) { MySQL.showError("库存检查错误", e); return false; } } private void showWarehouseCapacity() { String warehouseId = JOptionPane.showInputDialog("请输入仓库编号:"); if (warehouseId != null && !warehouseId.isEmpty()) { String sql = "SELECT 剩余容量 FROM 仓库 WHERE 仓库编号 = ?"; try (Connection conn = MySQL.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, warehouseId); try (ResultSet rs = pstmt.executeQuery()) { if (rs.next()) { JOptionPane.showMessageDialog(null, "仓库 " + warehouseId + " 的剩余容量: " + rs.getInt("剩余容量")); } else { JOptionPane.showMessageDialog(null, "未找到仓库!"); } } } catch (SQLException e) { MySQL.showError("查询错误", e); } } } private void showProductStock() { String productId = JOptionPane.showInputDialog("请输入商品编号:"); if (productId != null && !productId.isEmpty()) { String sql = "SELECT 库存 FROM 商品 WHERE 商品编号 = ?"; try (Connection conn = MySQL.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, productId); try (ResultSet rs = pstmt.executeQuery()) { if (rs.next()) { JOptionPane.showMessageDialog(null, "商品 " + productId + " 的库存: " + rs.getInt("库存")); } else { JOptionPane.showMessageDialog(null, "未找到商品!"); } } } catch (SQLException e) { MySQL.showError("查询错误", e); } } } private void editRecord(String type) { JTable table = tables.get(type); int row = table.getSelectedRow(); if (row == -1) { JOptionPane.showMessageDialog(null, "请选择要修改的记录"); return; } String id = (String) table.getValueAt(row, 0); String warehouseId = (String) table.getValueAt(row, 1); String productId = (String) table.getValueAt(row, 2); int quantity = (int) table.getValueAt(row, 3); String date = (String) table.getValueAt(row, 4); JDialog dialog = new JDialog((Frame) null, "修改记录", true); dialog.setSize(500, 300); dialog.setLayout(new GridLayout(5, 2, 10, 10)); dialog.setLocationRelativeTo(null); JTextField warehouseField = new JTextField(warehouseId); JTextField productField = new JTextField(productId); JTextField quantityField = new JTextField(String.valueOf(quantity)); JTextField dateField = new JTextField(date); JButton submitBtn = new JButton("提交"); submitBtn.addActionListener(e -> { try { String newWarehouseId = warehouseField.getText().trim(); String newProductId = productField.getText().trim(); int newQuantity = Integer.parseInt(quantityField.getText().trim()); String newDate = dateField.getText().trim(); // 验证输入 if (newWarehouseId.isEmpty() || newProductId.isEmpty() || newDate.isEmpty()) { JOptionPane.showMessageDialog(dialog, "所有字段都必须填写!"); return; } if (!MySQL.checkForeignKeyExists("仓库", "仓库编号", newWarehouseId)) { JOptionPane.showMessageDialog(dialog, "仓库ID不存在!"); return; } if (!MySQL.checkForeignKeyExists("商品", "商品编号", newProductId)) { JOptionPane.showMessageDialog(dialog, "商品ID不存在!"); return; } if (newQuantity <= 0) { JOptionPane.showMessageDialog(dialog, "商品数量必须大于0!"); return; } boolean isInbound = "入库".equals(type); // 检查容量/库存 if (isInbound && !checkWarehouseCapacity(newWarehouseId, newQuantity)) { JOptionPane.showMessageDialog(dialog, "仓库剩余容量不足!"); return; } if (!isInbound && !checkProductStock(newProductId, newQuantity)) { JOptionPane.showMessageDialog(dialog, "商品库存不足!"); return; } // 执行SQL if (MySQL.executeUpdate( "UPDATE 出入库 SET 仓库ID=?, 商品ID=?, 商品数量=?, 日期=? WHERE 编号=?", newWarehouseId, newProductId, newQuantity, newDate, id) > 0) { // 撤销原操作的影响 MySQL.updateWarehouseCapacity(warehouseId, quantity, !isInbound); MySQL.updateProductStock(productId, quantity, !isInbound); // 应用新操作的影响 MySQL.updateWarehouseCapacity(newWarehouseId, newQuantity, isInbound); MySQL.updateProductStock(newProductId, newQuantity, isInbound); JOptionPane.showMessageDialog(dialog, "记录更新成功!"); dialog.dispose(); refreshData(type); } else { JOptionPane.showMessageDialog(dialog, "记录更新失败!"); } } catch (NumberFormatException ex) { JOptionPane.showMessageDialog(dialog, "请输入有效的数字!"); } }); JButton cancelBtn = new JButton("取消"); cancelBtn.addActionListener(e -> dialog.dispose()); // 添加组件 dialog.add(new JLabel("仓库ID:")); dialog.add(warehouseField); dialog.add(new JLabel("商品ID:")); dialog.add(productField); dialog.add(new JLabel("商品数量:")); dialog.add(quantityField); dialog.add(new JLabel("日期(YYYY-MM-DD):")); dialog.add(dateField); dialog.add(submitBtn); dialog.add(cancelBtn); dialog.setVisible(true); } private void deleteRecord(String type) { JTable table = tables.get(type); int row = table.getSelectedRow(); if (row == -1) { JOptionPane.showMessageDialog(null, "请选择要删除的记录"); return; } String id = (String) table.getValueAt(row, 0); String warehouseId = (String) table.getValueAt(row, 1); String productId = (String) table.getValueAt(row, 2); int quantity = (int) table.getValueAt(row, 3); int confirm = JOptionPane.showConfirmDialog( null, "确定要删除这条记录吗?", "确认删除", JOptionPane.YES_NO_OPTION ); if (confirm == JOptionPane.YES_OPTION) { if (MySQL.executeUpdate("DELETE FROM 出入库 WHERE 编号=?", id) > 0) { boolean isInbound = "入库".equals(type); // 撤销操作的影响 MySQL.updateWarehouseCapacity(warehouseId, quantity, !isInbound); MySQL.updateProductStock(productId, quantity, !isInbound); JOptionPane.showMessageDialog(null, "记录删除成功!"); refreshData(type); } else { JOptionPane.showMessageDialog(null, "记录删除失败!"); } } } } // 管理员管理 class AdminManager { private String currentUser; public AdminManager(String currentUser) { this.currentUser = currentUser; } public JPanel createPanel() { JPanel panel = new JPanel(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.insets = new Insets(20, 20, 20, 20); gbc.gridx = 0; gbc.gridy = 0; JLabel titleLabel = new JLabel("用户管理"); titleLabel.setFont(new Font("宋体", Font.BOLD, 24)); panel.add(titleLabel, gbc); gbc.gridy++; JButton changePwdBtn = new JButton("修改密码"); changePwdBtn.setPreferredSize(new Dimension(200, 40)); changePwdBtn.addActionListener(e -> changePassword()); panel.add(changePwdBtn, gbc); return panel; } private void changePassword() { JDialog dialog = new JDialog((Frame) null, "修改密码", true); dialog.setSize(400, 250); dialog.setLayout(new GridLayout(4, 2, 10, 10)); dialog.setLocationRelativeTo(null); JPasswordField oldPwdField = new JPasswordField(); JPasswordField newPwdField = new JPasswordField(); JPasswordField confirmPwdField = new JPasswordField(); JButton submitBtn = new JButton("提交"); submitBtn.addActionListener(e -> { String oldPwd = new String(oldPwdField.getPassword()); String newPwd = new String(newPwdField.getPassword()); String confirmPwd = new String(confirmPwdField.getPassword()); if (oldPwd.isEmpty() || newPwd.isEmpty() || confirmPwd.isEmpty()) { JOptionPane.showMessageDialog(dialog, "所有字段都必须填写!"); return; } if (!MySQL.validateUser(currentUser, oldPwd)) { JOptionPane.showMessageDialog(dialog, "旧密码不正确!"); return; } if (!newPwd.equals(confirmPwd)) { JOptionPane.showMessageDialog(dialog, "两次输入的新密码不一致!"); return; } if (MySQL.updatePassword(currentUser, newPwd)) { JOptionPane.showMessageDialog(dialog, "密码修改成功!"); dialog.dispose(); } else { JOptionPane.showMessageDialog(dialog, "密码更新失败,请联系管理员"); } }); JButton cancelBtn = new JButton("取消"); cancelBtn.addActionListener(e -> dialog.dispose()); dialog.add(new JLabel("旧密码:")); dialog.add(oldPwdField); dialog.add(new JLabel("新密码:")); dialog.add(newPwdField); dialog.add(new JLabel("确认新密码:")); dialog.add(confirmPwdField); dialog.add(submitBtn); dialog.add(cancelBtn); dialog.setVisible(true); } }详细解释解释每一行
最新发布
06-25
/ 出入库管理模块 class InventoryManager { private JTabbedPane tabbedPane = new JTabbedPane(); private Map<String, DefaultTableModel> models = new LinkedHashMap<>(); private Map<String, JTable> tables = new LinkedHashMap<>(); public JPanel createPanel() { JPanel panel = new JPanel(new BorderLayout()); tabbedPane.addTab("入库管理", createInventoryPanel("入库")); tabbedPane.addTab("出库管理", createInventoryPanel("出库")); panel.add(tabbedPane, BorderLayout.CENTER); return panel; } private JPanel createInventoryPanel(String type) { JPanel panel = new JPanel(new BorderLayout()); JToolBar toolbar = new JToolBar(); JButton addBtn = new JButton("添加"); JButton editBtn = new JButton("修改"); JButton deleteBtn = new JButton("删除"); JButton refreshBtn = new JButton("刷新"); JButton capacityBtn = new JButton("仓库容量"); JButton stockBtn = new JButton("商品库存"); addBtn.addActionListener(e -> addRecord(type)); editBtn.addActionListener(e -> editRecord(type)); deleteBtn.addActionListener(e -> deleteRecord(type)); refreshBtn.addActionListener(e -> refreshData(type)); capacityBtn.addActionListener(e -> showWarehouseCapacity()); stockBtn.addActionListener(e -> showProductStock()); toolbar.add(addBtn); toolbar.add(editBtn); toolbar.add(deleteBtn); toolbar.add(refreshBtn); toolbar.add(capacityBtn); toolbar.add(stockBtn); JPanel searchPanel = new JPanel(); JTextField warehouseField = new JTextField(8); JTextField productField = new JTextField(8); JTextField dateField = new JTextField(8); JButton searchBtn = new JButton("搜索"); searchBtn.addActionListener(e -> searchRecords( type, warehouseField.getText().trim(), productField.getText().trim(), dateField.getText().trim() )); searchPanel.add(new JLabel("仓库ID:")); searchPanel.add(warehouseField); searchPanel.add(new JLabel("商品ID:")); searchPanel.add(productField); searchPanel.add(new JLabel("日期:")); searchPanel.add(dateField); searchPanel.add(searchBtn); DefaultTableModel model = new DefaultTableModel() { @Override public boolean isCellEditable(int row, int column) { return false; } }; model.setColumnIdentifiers(new String[]{"编号", "仓库ID", "商品ID", "商品数量", "日期", "类型"}); models.put(type, model); JTable table = new JTable(model); table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); tables.put(type, table); refreshData(type); JPanel topPanel = new JPanel(new BorderLayout()); topPanel.add(toolbar, BorderLayout.NORTH); topPanel.add(searchPanel, BorderLayout.CENTER); panel.add(topPanel, BorderLayout.NORTH); panel.add(new JScrollPane(table), BorderLayout.CENTER); return panel; } private void refreshData(String type) { List<Map<String, Object>> data = MySQL.readTable("出入库"); DefaultTableModel model = models.get(type); model.setRowCount(0); for (Map<String, Object> row : data) { if (type.equals(row.get("类型"))) { model.addRow(new Object[]{ row.get("编号"), row.get("仓库ID"), row.get("商品ID"), row.get("商品数量"), row.get("日期"), row.get("类型") }); } } } private void searchRecords(String type, String warehouseId, String productId, String date) { DefaultTableModel model = models.get(type); model.setRowCount(0); String sql = "SELECT * FROM 出入库 WHERE 类型='" + type + "'"; if (!warehouseId.isEmpty()) { sql += " AND 仓库ID LIKE '%" + warehouseId + "%'"; } if (!productId.isEmpty()) { sql += " AND 商品ID LIKE '%" + productId + "%'"; } if (!date.isEmpty()) { sql += " AND 日期 LIKE '%" + date + "%'"; } try (Connection conn = MySQL.getConnection(); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql)) { while (rs.next()) { model.addRow(new Object[]{ rs.getString("编号"), rs.getString("仓库ID"), rs.getString("商品ID"), rs.getInt("商品数量"), rs.getString("日期"), rs.getString("类型") }); } } catch (SQLException e) { MySQL.showError("搜索错误", e); } } private void addRecord(String type) { JDialog dialog = new JDialog((Frame) null, type + "记录", true); dialog.setSize(500, 300); dialog.setLayout(new GridLayout(5, 2, 10, 10)); dialog.setLocationRelativeTo(null); JTextField warehouseField = new JTextField(); JTextField productField = new JTextField(); JTextField quantityField = new JTextField(); JTextField dateField = new JTextField(); JButton submitBtn = new JButton("提交"); submitBtn.addActionListener(e -> { try { String warehouseId = warehouseField.getText().trim(); String productId = productField.getText().trim(); int quantity = Integer.parseInt(quantityField.getText().trim()); String date = dateField.getText().trim(); if (warehouseId.isEmpty() || productId.isEmpty() || date.isEmpty()) { JOptionPane.showMessageDialog(dialog, "所有字段都必须填写!"); return; } if (!MySQL.checkForeignKeyExists("编号", "编号", warehousenum) { if (!MySQL.checkForeignKeyExists("仓库", "仓库编号", warehouseId)) { JOptionPane.showMessageDialog(dialog, "仓库ID不存在!"); return; } if (!MySQL.checkForeignKeyExists("商品", "商品编号", productId)) { JOptionPane.showMessageDialog(dialog, "商品ID不存在!"); return; } if (quantity <= 0) { JOptionPane.showMessageDialog(dialog, "商品数量必须大于0!"); return; } boolean isInbound = "入库".equals(type); if (isInbound && !checkWarehouseCapacity(warehouseId, quantity)) { JOptionPane.showMessageDialog(dialog, "仓库剩余容量不足!"); return; } if (!isInbound && !checkProductStock(productId, quantity)) { JOptionPane.showMessageDialog(dialog, "商品库存不足!"); return; } if (MySQL.executeUpdate( "INSERT INTO 出入库 (编号,仓库ID, 商品ID, 商品数量, 日期, 类型) VALUES (?,?, ?, ?, ?, ?)", warehouseId, productId, quantity, date, type) > 0) { MySQL.updateWarehouseCapacity(warehouseId, quantity, isInbound); MySQL.updateProductStock(productId, quantity, isInbound); JOptionPane.showMessageDialog(dialog, type + "记录添加成功!"); dialog.dispose(); refreshData(type); } else { JOptionPane.showMessageDialog(dialog, type + "记录添加失败!"); } } catch (NumberFormatException ex) { JOptionPane.showMessageDialog(dialog, "请输入有效的数字!"); } }); JButton cancelBtn = new JButton("取消"); cancelBtn.addActionListener(e -> dialog.dispose()); dialog.add(new JLabel("仓库ID:")); dialog.add(warehouseField); dialog.add(new JLabel("商品ID:")); dialog.add(productField); dialog.add(new JLabel("商品数量:")); dialog.add(quantityField); dialog.add(new JLabel("日期(YYYY-MM-DD):")); dialog.add(dateField); dialog.add(submitBtn); dialog.add(cancelBtn); dialog.setVisible(true); } private boolean checkWarehouseCapacity(String warehouseId, int quantity) { String sql = "SELECT 剩余容量 FROM 仓库 WHERE 仓库编号 = '" + warehouseId + "'"; try (Connection conn = MySQL.getConnection(); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql)) { return rs.next() && rs.getInt("剩余容量") >= quantity; } catch (SQLException e) { MySQL.showError("容量检查错误", e); return false; } } private boolean checkProductStock(String productId, int quantity) { String sql = "SELECT 库存 FROM 商品 WHERE 商品编号 = '" + productId + "'"; try (Connection conn = MySQL.getConnection(); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql)) { return rs.next() && rs.getInt("库存") >= quantity; } catch (SQLException e) { MySQL.showError("库存检查错误", e); return false; } } private void showWarehouseCapacity() { String warehouseId = JOptionPane.showInputDialog("请输入仓库编号:"); if (warehouseId != null && !warehouseId.isEmpty()) { String sql = "SELECT 剩余容量 FROM 仓库 WHERE 仓库编号 = '" + warehouseId + "'"; try (Connection conn = MySQL.getConnection(); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql)) { if (rs.next()) { JOptionPane.showMessageDialog(null, "仓库 " + warehouseId + " 的剩余容量: " + rs.getInt("剩余容量")); } else { JOptionPane.showMessageDialog(null, "未找到仓库!"); } } catch (SQLException e) { MySQL.showError("查询错误", e); } } } private void showProductStock() { String productId = JOptionPane.showInputDialog("请输入商品编号:"); if (productId != null && !productId.isEmpty()) { String sql = "SELECT 库存 FROM 商品 WHERE 商品编号 = '" + productId + "'"; try (Connection conn = MySQL.getConnection(); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql)) { if (rs.next()) { JOptionPane.showMessageDialog(null, "商品 " + productId + " 的库存: " + rs.getInt("库存")); } else { JOptionPane.showMessageDialog(null, "未找到商品!"); } } catch (SQLException e) { MySQL.showError("查询错误", e); } } } private void editRecord(String type) { JTable table = tables.get(type); int row = table.getSelectedRow(); if (row == -1) { JOptionPane.showMessageDialog(null, "请选择要修改的记录"); return; } String id = (String) table.getValueAt(row, 0); String warehouseId = (String) table.getValueAt(row, 1); String productId = (String) table.getValueAt(row, 2); int quantity = (int) table.getValueAt(row, 3); String date = (String) table.getValueAt(row, 4); JDialog dialog = new JDialog((Frame) null, "修改记录", true); dialog.setSize(500, 300); dialog.setLayout(new GridLayout(5, 2, 10, 10)); dialog.setLocationRelativeTo(null); JTextField warehouseField = new JTextField(warehouseId); JTextField productField = new JTextField(productId); JTextField quantityField = new JTextField(String.valueOf(quantity)); JTextField dateField = new JTextField(date); JButton submitBtn = new JButton("提交"); submitBtn.addActionListener(e -> { try { String newWarehouseId = warehouseField.getText().trim(); String newProductId = productField.getText().trim(); int newQuantity = Integer.parseInt(quantityField.getText().trim()); String newDate = dateField.getText().trim(); if (newWarehouseId.isEmpty() || newProductId.isEmpty() || newDate.isEmpty()) { JOptionPane.showMessageDialog(dialog, "所有字段都必须填写!"); return; } if (!MySQL.checkForeignKeyExists("仓库", "仓库编号", newWarehouseId)) { JOptionPane.showMessageDialog(dialog, "仓库ID不存在!"); return; } if (!MySQL.checkForeignKeyExists("商品", "商品编号", newProductId)) { JOptionPane.showMessageDialog(dialog, "商品ID不存在!"); return; } if (newQuantity <= 0) { JOptionPane.showMessageDialog(dialog, "商品数量必须大于0!"); return; } boolean isInbound = "入库".equals(type); if (isInbound && !checkWarehouseCapacity(newWarehouseId, newQuantity)) { JOptionPane.showMessageDialog(dialog, "仓库剩余容量不足!"); return; } if (!isInbound && !checkProductStock(newProductId, newQuantity)) { JOptionPane.showMessageDialog(dialog, "商品库存不足!"); return; } if (MySQL.executeUpdate( "UPDATE 出入库 SET 仓库ID=?, 商品ID=?, 商品数量=?, 日期=? WHERE 编号=?", newWarehouseId, newProductId, newQuantity, newDate, id) > 0) { MySQL.updateWarehouseCapacity(warehouseId, quantity, !isInbound); MySQL.updateProductStock(productId, quantity, !isInbound); MySQL.updateWarehouseCapacity(newWarehouseId, newQuantity, isInbound); MySQL.updateProductStock(newProductId, newQuantity, isInbound); JOptionPane.showMessageDialog(dialog, "记录更新成功!"); dialog.dispose(); refreshData(type); } else { JOptionPane.showMessageDialog(dialog, "记录更新失败!"); } } catch (NumberFormatException ex) { JOptionPane.showMessageDialog(dialog, "请输入有效的数字!"); } }); JButton cancelBtn = new JButton("取消"); cancelBtn.addActionListener(e -> dialog.dispose()); dialog.add(new JLabel("仓库ID:")); dialog.add(warehouseField); dialog.add(new JLabel("商品ID:")); dialog.add(productField); dialog.add(new JLabel("商品数量:")); dialog.add(quantityField); dialog.add(new JLabel("日期(YYYY-MM-DD):")); dialog.add(dateField); dialog.add(submitBtn); dialog.add(cancelBtn); dialog.setVisible(true); } private void deleteRecord(String type) { JTable table = tables.get(type); int row = table.getSelectedRow(); if (row == -1) { JOptionPane.showMessageDialog(null, "请选择要删除的记录"); return; } String id = (String) table.getValueAt(row, 0); String warehouseId = (String) table.getValueAt(row, 1); String productId = (String) table.getValueAt(row, 2); int quantity = (int) table.getValueAt(row, 3); int confirm = JOptionPane.showConfirmDialog( null, "确定要删除这条记录吗?", "确认删除", JOptionPane.YES_NO_OPTION ); if (confirm == JOptionPane.YES_OPTION) { if (MySQL.executeUpdate("DELETE FROM 出入库 WHERE 编号=?", id) > 0) { boolean isInbound = "入库".equals(type); MySQL.updateWarehouseCapacity(warehouseId, quantity, !isInbound); MySQL.updateProductStock(productId, quantity, !isInbound); JOptionPane.showMessageDialog(null, "记录删除成功!"); refreshData(type); } else { JOptionPane.showMessageDialog(null, "记录删除失败!"); } } } } 在添加入库时要手动输入编号
06-25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值