【问题标题】:How to make SQL connection statements common如何使 SQL 连接语句通用
【发布时间】:2013-02-01 14:18:47
【问题描述】:

我必须在同一类的不同方法中执行多个 SQL 查询。有什么方法可以使这些语句通用,我可以在所有方法中使用相同的 con,statement 变量来执行查询。

Class.forName("com.mysql.jdbc.Driver").newInstance();
Connection con = DriverManager.getConnection ("jdbc:mysql://localhost:3306/kamal","root","root");
Statement statement=con.createStatement();

【问题讨论】:

  • 你想要完成什么?

标签: java mysql sql


【解决方案1】:

在你的类中使用这个方法并一次又一次地调用它

public Connection getMyConnection() throws ClassNotFoundException, SQLException
    {
        String connectionURL = "jdbc:mysql://localhost:3306/test";
        Class.forName("com.mysql.jdbc.Driver");
        Connection con = DriverManager.getConnection(connectionURL, "root", "root");
        return con;
    }

【讨论】:

    【解决方案2】:

    您可以在静态方法中编写连接语句,该方法可以在您的其他类中重复使用:

    public Connection getConnection() throws ClassNotFoundException, SQLException {
    
        String connURL = "jdbc:mysql://localhost:3306/test";
        Class.forName("com.mysql.jdbc.Driver");
        Connection con = DriverManager.getConnection(connURL, "username", "password");
        return con;
    }
    

    但这有一个缺点,您必须手动管理数据库连接的打开和关闭。

    为了缓解上述缺点,可以考虑使用像 Hibernate 这样的对象关系映射框架,它将连接细节抽象到一个设置文件中,该文件将被每个数据库连接重用。

    【讨论】:

    • 没有理由将方法设为静态。
    • 没有理由使方法成为非静态的。
    【解决方案3】:

    如果您需要整个类中的变量,您可能希望将其设为成员变量。

    但是,对于 Connections 这样的资源不鼓励这样做,因为它很容易剥夺系统,并增加额外的负载。

    您可以做的是使用称为Singleton 的设计模式。阅读它here。

    基本上,您可以使用此实现创建一个名为 ConnectionManager 的新类

    class ConnectionManager {
    
    private static ConnectionManager _instance = null;
    private Connection con = null;
    
    protected ConnectionManager() {
        //empty
    }
    
    private void init() {
        Class.forName("com.mysql.jdbc.Driver").newInstance();
        this.con = DriverManager.getConnection
              ("jdbc:mysql://localhost:3306/kamal","root","root");
    }
    public Connection getConnection() {
        return this.con;
    }
    
    public static ConnectionManager getInstance() {
        if(_instance == null) {
            _instance = new ConnectionManager();
            _instance.init();
        }
        return _instance;
    }
    
    }//end class
    

    现在,这对我们有很多帮助,尤其是在您的应用程序是多线程的情况下。我们只需要建立一个连接,除非程序终止,否则它将保持不变。在任何需要创建新Statement 的地方,都可以简单地使用它。

    ConnectionManager.getInstance().getConnection().createStatement();
    

    【讨论】:

    • 我个人认为将连接用作单例是一个非常糟糕的主意。在多线程环境中,无法保证线程安全。连接池可能是正确的方法。
    • 正确制作的单例是相当线程安全的。连接池非常适合大型应用程序,但对于较小的应用程序非常麻烦。
    • 您不应该在多个线程之间共享单个连接。你可以在这里找到关于线程安全的讨论:stackoverflow.com/questions/1531073/…
    • 这很有趣。但是,这里有 JDBC 规范。 docs.oracle.com/javase/1.3/docs/guide/jdbc/spec/… 。它明确指出驱动程序必须是多线程安全的。但是,我同意你的观点,即单例会降低性能,因为它在多个线程之间共享。
    【解决方案4】:

    这是一个非常简单的连接池实现。请注意,这是使用记事本编写的,尚未经过测试:

    public interface ConnectionPool {
        public Connection getConnection() throws SQLException;
        public void closeConnection(Connection connection) throws SQLException;
    }
    
    
    public class MySQLConnectionPool implements ConnectionPool {
        private static final Class<?> mysqlDriver;
        private final Stack<Connection> connections;
        private final String url;
        private final String user;
        private final String password;
        private final int maxSize;
    
        static {
            mysqlDriver = Class.forName("com.mysql.jdbc.Driver");
        }
    
        public MySQLConnectionPool(String url, String user, String password, int initialSize, int size) {
            if (initialSize > size) {
                throw new IllegalArgumentException("Pool initial size must not be greater than size");
            }
            if (size <= 0) {
                throw new IllegalArgumentException("Pool size must be greater than zero");
            }
            this.size = maxSize;
            this.url = url;
            this.user = user;
            this.password = password;
    
            this.connections = new Stack<Connection>();
            try {
                for (int i = 0;i < initialSize;i++) {
                    connections.push(getConnection(url, user, password));
                }
            } catch (Exception exception) {
                // TODO: Log somewhere?
            }
        }
    
        public Connection getConnection(String url, user, password) throws SQLException {
            DriverManager.getConnection(url, user, password);
        }
    
        public Connection getConnection() SQLException {
            try {
                synchronized (connections) {
                    return connections.pop();
                }
            } catch (EmptyStackException exception) {
                return getConnection(url, user, password);
            }
        }
    
        public void closeConnection(Connection connection) throws SQLException {
            synchronized (connections) {
                if (connections.size() < maxSize) {
                    connections.push(connection);
                    return;
                }
            }
            connection.close();
        }
    }
    
    
    public class SingletonMYSQLConnectionPool extends MySQLConnectionPool() {
        private static volatile SingletonMYSQLConnectionPool instance;
    
        private SingletonMYSQLConnectionPool() {
            super("jdbc:mysql://localhost:3306/kamal","root","root", 0, 2);
        }
    
        public static SingletonMYSQLConnectionPool getInstance() {
            if (instance == null) {
                synchronized (SingletonMYSQLConnectionPool.class) {
                    if (instance == null) {
                        instance = new SingletonMYSQLConnectionPool();
                    }
                }
            }
            return instance;
        }
    }
    

    【讨论】:

    • 什么是重用语句,这是您需要在应用程序级别处理的事情(除非您的容器为它们提供缓存 - 但随后您将使用 DataSource)
    【解决方案5】:
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
            {
                PrintWriter pw = response.getWriter();
                Connection conn;  
                try
                {
                String fname = request.getParameter("fname");
                String lname = request.getParameter("lname");
                Class.forName("com.mysql.jdbc.Driver");
                conn = (Connection)DriverManager.getConnection("jdbc:mysql://localhost:3307/soft\",\"root\",\"root");
                PreparedStatement pst = (PreparedStatement) conn.prepareStatement("insert into soft.IT(fname,lname) values(?,?)");
                    pst.setString(1,fname);  
                    pst.setString(2,lname);        
                    int i = pst.executeUpdate();  
                    if(i!=0){  
    
                        pw.println("<br>Record has been inserted");  
                }  
                else
                {  
                        pw.println("failed to insert the data");  
                }  
                }catch (Exception e)
                {  
                        pw.println(e);  
                }  
            }
    

    【讨论】:

    • 你在使用 conn.commit() 并关闭连接吗?
    【解决方案6】:

    在您的数据库中创建它们的存储过程。

    【讨论】:

      猜你喜欢
      • 2016-03-15
      • 1970-01-01
      • 1970-01-01
      • 2012-07-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-28
      • 2016-10-23
      相关资源
      最近更新 更多