Spring Boot+Jooq项目中静态@Value属性为空的Connection类问题求助
Hey there! The issue you're hitting is a common one with Spring: @Value can't inject values directly into static fields. Spring's dependency injection works with instance members, not static ones—so those static variables stay null because Spring never gets a chance to populate them. Let's walk through a few better approaches, starting with the most Spring-idiomatic one.
Option 1: Ditch Static Methods (Recommended)
Instead of using static methods, let Spring manage ConnectionFactory as a singleton bean, and inject it wherever you need it. This aligns with Spring's core principles and avoids static state headaches.
Updated ConnectionFactory Class
@Component public class ConnectionFactory { private final String codigoEscola; private final String driver; private final String nameDb; private final String user; private final String password; private final String server; private final String firstUrlPart; private final String lastPartUrl; private final String port; private final String strConnection; // Constructor injection (preferred over @Value on fields for immutability) public ConnectionFactory( @Value("${bws.codigo.escola}") String codigoEscola, @Value("${bws.driver.connection}") String driver, @Value("${bws.database.name}") String nameDb, @Value("${bws.database.user}") String user, @Value("${bws.database.password}") String password, @Value("${bws.database.server}") String server, @Value("${bws.string.connection}") String firstUrlPart, @Value("${bws.string.connectionLast}") String lastPartUrl, @Value("${bws.database.port}") String port) { this.codigoEscola = codigoEscola; this.driver = driver; this.nameDb = nameDb; this.user = user; this.password = password; this.server = server; this.firstUrlPart = firstUrlPart; this.lastPartUrl = lastPartUrl; this.port = port; this.strConnection = firstUrlPart + server + ":" + port + "/" + nameDb + lastPartUrl; } public Connection getConnection() throws SQLException { try { Class.forName(driver); return DriverManager.getConnection(strConnection, user, password); } catch (ClassNotFoundException e) { throw new SQLException(e.getMessage()); } } }
How to Use It
Inject the ConnectionFactory bean into your service/repository class:
@Service // Or @Component, @Repository, etc. public class AlunoService { private final ConnectionFactory connectionFactory; // Constructor injection public AlunoService(ConnectionFactory connectionFactory) { this.connectionFactory = connectionFactory; } public int getAlunoCount() throws SQLException { try (Connection con = connectionFactory.getConnection()) { DSLContext ctx = DSL.using(con, SQLDialect.MYSQL); return ctx.selectCount() .from(ALUNO) .fetchOne(0, int.class); } } }
Option 2: Use @PostConstruct to Populate Static Fields (If You Must Keep Static Methods)
If you really need to keep the static getConnection() method (though this is not ideal for testability and Spring best practices), you can use @PostConstruct to copy instance-level injected values to static fields:
@Component public class ConnectionFactory { private static String codigoEscola; private static String driver; private static String nameDb; private static String user; private static String password; private static String server; private static String firstUrlPart; private static String lastPartUrl; private static String port; private static String strConnection; @Value("${bws.codigo.escola}") private String instanceCodigoEscola; @Value("${bws.driver.connection}") private String instanceDriver; @Value("${bws.database.name}") private String instanceNameDb; @Value("${bws.database.user}") private String instanceUser; @Value("${bws.database.password}") private String instancePassword; @Value("${bws.database.server}") private String instanceServer; @Value("${bws.string.connection}") private String instanceFirstUrlPart; @Value("${bws.string.connectionLast}") private String instanceLastPartUrl; @Value("${bws.database.port}") private String instancePort; @PostConstruct private void initStaticFields() { codigoEscola = instanceCodigoEscola; driver = instanceDriver; nameDb = instanceNameDb; user = instanceUser; password = instancePassword; server = instanceServer; firstUrlPart = instanceFirstUrlPart; lastPartUrl = instanceLastPartUrl; port = instancePort; strConnection = firstUrlPart + server + ":" + port + "/" + nameDb + lastPartUrl; } public static Connection getConnection() throws SQLException { try { Class.forName(driver); return DriverManager.getConnection(strConnection, user, password); } catch (ClassNotFoundException e) { throw new SQLException(e.getMessage()); } } }
Bonus: Let Spring Boot Auto-Configure jOOQ (Even Better!)
You don't need to manage connections manually at all! Spring Boot's jOOQ starter can auto-configure a DSLContext bean for you, which handles connection pooling and lifecycle automatically. Just add the jOOQ starter to your build file, and inject DSLContext directly:
Example Usage
@Service public class AlunoService { private final DSLContext dslContext; public AlunoService(DSLContext dslContext) { this.dslContext = dslContext; } public int getAlunoCount() { return dslContext.selectCount() .from(ALUNO) .fetchOne(0, int.class); } }
This is the cleanest approach—no need for your custom ConnectionFactory at all!
内容的提问来源于stack exchange,提问作者Manzini

