[英]Java using JDBC - Too many connections?
我正在为酒吧写一个库存补货系统作为我的最后一年项目。 我可以从MYSQL数据库中检索信息,我可以一次滚动一个结果。
我正在尝试根据所选类别更改结果。 我已经设法使用组合框来实现这一点,但在类别之间移动时出现以下错误:
线程“main”中的异常com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException:数据源拒绝建立连接,来自服务器的消息:“连接太多”
两个单独文件的代码如下:
RetrieveStockQuery
的SQL查询
public JComboBox getComboBox() throws SQLException { con = SQLConnect.getConnection(); combo = new JComboBox(); combo.removeAllItems(); try { stat = con.createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE ); rs = stat.executeQuery("SELECT categoryName FROM Category"); while (rs.next()) { combo.addItem(rs.getString("categoryName")); categoryName = rs.getString("categoryName"); } } catch (SQLException sqle) { System.out.println(sqle); stat.close(); con.close(); } return combo; } //---------------------------------------------------------------- public void retrieveStock() throws SQLException { con = SQLConnect.getConnection(); stockGUI = new ViewStockGUI(); // I THINK THIS IS WHAT IS CAUSING THE ERROR String viewStock = "SELECT * FROM Stock where categoryName = '" + "'" + stockGUI.selected + "'"; System.out.println(viewStock); try { stat = con.createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE ); rs = stat.executeQuery(viewStock); while(rs.next()){ stockID = rs.getInt("stockID"); stockName = rs.getString("stockName"); stockDescription = rs.getString("stockDescription"); stockPrice = rs.getFloat("stockPrice"); stockQuantity = rs.getInt("stockQuantity"); categoryName = rs.getString("categoryName"); ID = Integer.toString(stockID); price = Float.toString(stockPrice); quantity = Double.toString(stockQuantity); stat.close(); con.close(); System.out.println( "Stock ID: " + stockID + " Stock Name: " + stockName + " Stock Description: " + stockDescription + " Stock Price: " + stockPrice + " Stock Quantity:" + stockQuantity + " Category: " + categoryName); } } catch (SQLException err) { System.out.println(err.getMessage()); } }
我的ViewStockGUI
课程
public class ViewStockGUI extends JPanel { private static final long serialVersionUID = 1L; final JFrame viewFrame; ViewStockQuery stockQuery; ViewStockQuery stockName; JComboBox comboGUI; String selected; JComboBox combo; public ViewStockGUI() throws SQLException { final ViewStockQuery stock = new ViewStockQuery(); comboGUI = stock.getComboBox(); stock.retrieveStock(); viewFrame = new JFrame("View Stock"); JPanel p = new JPanel(); p.setBorder (new TitledBorder(new LineBorder(Color.black, 1, true))); p.setPreferredSize(new Dimension(500,400)); JPanel p2 = new JPanel(); p2.setBorder (new TitledBorder(new LineBorder(Color.black, 1, true))); p2.setPreferredSize(new Dimension(500, 50)); JPanel p3 = new JPanel(); JPanel p4 = new JPanel(); JPanel p5 = new JPanel(); JPanel p6 = new JPanel(); Box box = Box.createVerticalBox(); Box box2 = Box.createHorizontalBox(); Box box3 = Box.createHorizontalBox(); Box box4 = Box.createHorizontalBox(); final JTextField textfieldStockName; final JTextField textfieldStockID; final JTextField textfieldStockDescription; final JTextField textfieldStockPrice; final JTextField textfieldStockQuantity; final JTextField textfieldStockCategory; final JLabel stockName = new JLabel("Name:"); JLabel stockID = new JLabel("ID:"); JLabel stockDescription = new JLabel("Description:"); JLabel stockPrice = new JLabel("Price:"); JLabel stockQuantity = new JLabel("Quantity:"); JLabel categoryName = new JLabel("Category:"); box.add(Box.createVerticalGlue()); box.add(stockName); box.add(textfieldStockName = new JTextField("")); textfieldStockName.setText(stock.getStockName()); textfieldStockName.setEditable(false); box.add(stockID); box.add(textfieldStockID = new JTextField("")); textfieldStockID.setText(stock.getStockID()); textfieldStockID.setEditable(false); box.add(stockDescription); box.add(textfieldStockDescription = new JTextField("")); textfieldStockDescription.setText(stock.getStockDescription()); textfieldStockDescription.setEditable(false); box.add(stockPrice); box.add(textfieldStockPrice = new JTextField("")); textfieldStockPrice.setText(stock.getStockPrice()); textfieldStockPrice.setEditable(false); box.add(stockQuantity); box.add(textfieldStockQuantity = new JTextField("")); textfieldStockQuantity.setText(stock.getStockQuantity()); textfieldStockQuantity.setEditable(false); box.add(categoryName); box.add(textfieldStockCategory = new JTextField("")); textfieldStockCategory.setText(stock.getStockCategory()); textfieldStockCategory.setEditable(false); box.add(Box.createVerticalGlue()); JButton next = new JButton("Next"); next.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { stock.doNext(); textfieldStockName.setText(stock.getStockName()); textfieldStockID.setText(stock.getStockID()); textfieldStockDescription.setText(stock.getStockDescription()); textfieldStockPrice.setText(stock.getStockPrice()); textfieldStockQuantity.setText(stock.getStockQuantity()); textfieldStockCategory.setText(stock.getStockCategory()); } }); JButton previous = new JButton("Previous"); previous.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { stock.doPrevious(); textfieldStockName.setText(stock.getStockName()); textfieldStockID.setText(stock.getStockID()); textfieldStockDescription.setText(stock.getStockDescription()); textfieldStockPrice.setText(stock.getStockPrice()); textfieldStockQuantity.setText(stock.getStockQuantity()); textfieldStockCategory.setText(stock.getStockCategory()); } }); final Counter counter = new Counter(); final JLabel text = new JLabel(counter.getValue1()); JButton plus = new JButton("+"); plus.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { counter.increment(); text.setText(counter.getValue1()); } }); JButton minus = new JButton("-"); minus.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { counter.decrease(); text.setText(counter.getValue1()); } }); JButton update = new JButton("Update"); update.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { stock.updateStock(counter.getValue1()); } catch (SQLException e1) { e1.printStackTrace(); } finally { // doesn't update yet; will work on this later textfieldStockQuantity.setText(stock.getStockQuantity()); } } }); comboGUI.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { combo = (JComboBox) e.getSource(); selected = (String)combo.getSelectedItem(); textfieldStockName.setText(stock.getStockName()); textfieldStockID.setText(stock.getStockID()); textfieldStockDescription.setText(stock.getStockDescription()); textfieldStockPrice.setText(stock.getStockPrice()); textfieldStockQuantity.setText(stock.getStockQuantity()); textfieldStockCategory.setText(stock.getStockCategory()); stockQuery.con.close(); } catch (SQLException e1) { e1.printStackTrace(); } } }); box.add(comboGUI); box2.add(previous); box2.add(next); box3.add(minus); box3.add(text); box3.add(plus); box4.add(update); p.add(box2); p.add(box); p.add(box3); p.add(box4); this.add(p, BorderLayout.SOUTH); } }
如果有人可以提供帮助,将不胜感激。
当您有太多打开的连接时,会出现此异常。
这是可配置的,但在您的情况下,问题出在您的代码中。
你发布的代码很奇怪(至少)。
您要么不关闭连接,除非您得到SQLException
或在处理结果集期间关闭它!
在任何情况下,您都应该重构代码,以便在完成后立即关闭连接和结果集等。
例:
try {
stat = con.createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE );
rs = stat.executeQuery("SELECT categoryName FROM Category");
while (rs.next()) {
combo.addItem(rs.getString("categoryName"));
categoryName = rs.getString("categoryName");
}
} catch (SQLException sqle) {
System.out.println(sqle);
}
finally{
if(stat != null) stat.close();
if(con != null) con.close();
}
通过将关闭置于finally
您可以确保连接以正确的流程或异常关闭(为清楚起见,我省略了try-catch
)。
因此,通过这种方式修改代码以关闭连接。
为了获得更好的性能,您应该研究连接池
我想我在你的代码中看到了问题。 你的代码非常奇怪,但这就是我认为发生的事情:
在ViewStockQuery
类中,您有retrieveStock()
方法。 然后,此方法创建GUI类的实例ViewStockGUI
。 除了这是不好的做法之外,它会导致一个问题,因为在ViewStockGUI
的构造函数中,您在此行的retrieveStock()
方法中调用了它:
stockGUI = new ViewStockGUI();
然后再用这一行调用retrieveStock()
:
final ViewStockQuery stock = new ViewStockQuery();
comboGUI = stock.getComboBox();
stock.retrieveStock();
这会导致递归问题,因为ViewStockGUI()
构造函数调用retrieveStock()
方法创建连接并再次调用ViewStockGUI()
构造函数,该构造函数将再次调用未关闭连接并尝试打开的retrieveStock()
方法不同的联系。 希望你能得到这张照片。
解决它的方法是清理代码。 不要在retrieveStock()
调用构造函数。 查找为您的查询传递所选类别的其他方法。
编辑:
像你这样写ViewStockQuery
:
private String mSelected;
public ViewStockQuery(String selectedCategory) {
mSelected = selectedCategory;
}
...
public void retrieveStock() throws SQLException {
con = SQLConnect.getConnection();
String viewStock = "SELECT * FROM Stock where categoryName = '" + "'" + mSelected + "'";
System.out.println(viewStock);
try {
...
然后编写ViewStockGUI
,以便在选择类别时,即创建ViewStockQuery
并传入所选字符串。
编辑:
就像我之前说的那样,你的代码最终需要改变很多东西。 但是,出于本期的目的,您可以在ViewStockGUI
中执行以下操作:
String selected = (String)combo.getSelectedItem();
final ViewStockQuery stock = new ViewStockQuery(selected);
第一行从组合框中收集选定的类别,第二行创建ViewStockQuery
的实例,并将选定的ViewStockQuery
传递给构造函数。 然后,这将初始化mSelected,就像我在上面为ViewStockQuery
提出的构造函数中看到的ViewStockQuery
。
如果你想使用JDBC(而不是JPA),那么我建议使用Spring的JdbcTemplate或Java SE 7的自动资源管理(ARM)。(我还没有尝试使用JDBC的JDBC,但它应该可以工作。 )
基本上,您需要在try-catch子句的finally块中关闭Closeables。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.