我可以使用 Spring Boot 在正在运行的应用程序上添加数据库连接吗?

Posted

技术标签:

【中文标题】我可以使用 Spring Boot 在正在运行的应用程序上添加数据库连接吗?【英文标题】:Can I add database connections on a running application using Spring Boot? 【发布时间】:2019-11-01 15:27:39 【问题描述】:

例如,我有一个表单,我将在其中放置数据库连接的用户、密码、端口等,并在提交时建立​​并保存与数据库的连接。通常这是在应用程序运行之前在 application.properties 中完成的,但我可以在应用程序的运行时添加它吗?我这是可能的,我该怎么做?

【问题讨论】:

那么application.properties文件是如何使用的呢?再深入一点。 好问题。如果你打算通过 Spring jdbc 来使用它,那就太难了,但是你可以寻找一些方法来使用 JDBC 包装一个纯连接;通常定义您的连接字符串并将其传递给 jdbc 管理器。 【参考方案1】:

一种解决方案是创建一个 DatabaseConnection 实体,其中包含您提到的所有必要连接属性(加上一个 active: boolean 属性)。使用 Spring Data 为该实体创建存储库并创建上层组件。为您的客户提供控制器以在该实体上进行 CRUD。

DatabaseConnectionService 可以提供到其他组件的活动 JDBC 连接以进行查询/更新。

【讨论】:

【参考方案2】:

在我的一个项目中遇到过类似的情况,使用spring-jdbc编写代码和维护会很困难。您可以使用普通的jdbc使用连接参数来获取指定的连接对象。

package com;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;

import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

@Component
public class DB2Connection 

private static final Logger logger = LoggerFactory.getLogger(DB2Connection.class); 

private static String DRIVER_NAME;

private static String VALID_QUERY;

@Value("$db.valid-query")
public void setValidQuery(String query)
    VALID_QUERY = query;


@Value("$db.driverName")
public void setDriverName(String driverName)
    DRIVER_NAME = driverName;


/**
 *  Getting the Database connection
 *  @param  url             url of the database
 *  @param  userName        username of the db
 *  @param  password        password of the db
 *  @return Connection      returns DB Connection object 
 * */
public static Connection getConnection(final String url, final String userName, final String password)

    logger.info("Getting DB Connection...");

    Assert.notNull(url, "Database URL can't be null");
    Assert.notNull(userName, "Database username can't be null");
    Assert.notNull(password, "Database password can't be null");

    Connection con = null;
    try
        Class.forName(DRIVER_NAME);
        con = DriverManager.getConnection(url,userName,password);

        // testing for the valid connection
        if(testConnection(con))
            logger.info("Valid DB Connection # Connection Tested...");
        else
            logger.info("In-Valid DB Connection...");
        
    catch(ClassNotFoundException cla)
        logger.error("Class Not found exception..."+ExceptionUtils.getStackTrace(cla));
    catch(SQLException sqe)
        logger.error("SQL Exception..."+ExceptionUtils.getStackTrace(sqe));
    catch(Exception exe)
        logger.error("Exception occured while making DB Connection..."+ExceptionUtils.getStackTrace(exe));
    
    return con;



/**
 *  Closing the java.sql.Connection class object 
 *  
 *  @param  con     Connection object which need to be closed
 *  
 * */
public static void close(Connection con)

    logger.info("Closing the connection object...");
    try 
        if(con != null )
            con.close();
        
     catch (SQLException e) 
        logger.error("Exception occured while closing DBConnection..."+ExceptionUtils.getStackTrace(e));
    


/**
 * This method will test connection if proper or not
 * @param   con     Connection object which need to be checked
 * @return  flag    true if connection is fine, false in case of connection is wrong
 * */
public static synchronized boolean testConnection(Connection con)

    boolean flag = false;
    logger.info("Testing the connection before providing to another process...");
    ResultSet rs = null;
    Statement stmt = null;
    try
        stmt= con.createStatement();

        // running the query for validation of the database
        rs = stmt.executeQuery(VALID_QUERY);
        while(rs.next())
            // if we get Timestamp as return type - valid query is successfully run in the database
            Timestamp t = rs.getTimestamp(1);
            if( t != null)
                flag =true;
            
        
    catch(SQLException e)
        logger.error("SQL Exception error..."+ExceptionUtils.getStackTrace(e));
    finally
        if(rs != null)
            try 
                rs.close();
             catch (SQLException e) 
                logger.error("Error in closing Result Set"+ExceptionUtils.getStackTrace(e));
            
        if( stmt != null)
            try 
                stmt.close();
             catch (SQLException e) 
                logger.error("Error in closing Statement"+ExceptionUtils.getStackTrace(e));
            
        
    
    return flag;

在 application.properties 文件中定义 db.valid-query 和 db.driverName 的值。 调用 getConnection() 获取连接对象。

您还可以创建自己的自定义执行器,它可以向您显示当前在应用程序中存在的所有当前连接对象。维护当前对象 DB Connection 对象所需的额外代码。

【讨论】:

你能给我一些我必须在 application.properties 中输入的 db.valid_query 和 db.driverName 值的例子吗? 如果我使用 DB2 作为数据库,我的 application.properties 将类似于 -# Check query for DB Connection db.valid-query = SELECT CURRENT TIMESTAMP FROM SYSIBM.SYSDUMMY1 db.driverName = com. ibm.db2.jcc.DB2Driver,您的 db.valid-query 和 db.driverName 将根据数据库进行更改 但是,虽然您已经在 application.properties 中编写了查询,但您仍然可以从数据库中获取查询并更改使用的查询? 应用程序文件中的查询仅用于检查数据库连接是否有效,一旦您验证连接对象使用相同的连接并使用语句对象运行查询。Connection con = DB2Connection。 getConnection(dbDetails.getHostName(), dbDetails.getUserName(), password);Statement stmt=con.createStatement();ResultSet rs=stmt.executeQuery("Select * from table_name");

以上是关于我可以使用 Spring Boot 在正在运行的应用程序上添加数据库连接吗?的主要内容,如果未能解决你的问题,请参考以下文章

AWS 可以与 Spring Boot 和 React 一起使用吗?

Spring Boot 运行失败

使用 Spring Boot 运行基于 Java 的 Flyway 回调

docker 镜像正在运行,但无法在 Spring Boot 应用程序中访问 REST 端点

使用 Spring MVC 运行 Spring Boot 时引发空指针异常

如何在 Spring Boot 测试中获取正在运行的服务器端口?