You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让变量每次调用时自动从数据库获取最新值?

Great question! The core issue here is that Java's String (and primitive types) are immutable—once you assign a value to a variable like theName, it holds a fixed reference to that string value forever, unless you explicitly reassign it. To get the behavior you want (where every reference to "name" pulls the latest value from the database automatically), you need to wrap this database-fetching logic in a dedicated class.

The Problem with Your Current Approach

Right now, you're storing the name in a static String variable. When you call changeName(), you have to manually re-fetch the value and reassign it to theName—this is error-prone and not scalable if you need to access the name in multiple places.

Solution: Wrap the Database Fetch in a Custom Class

Instead of using a raw String, create a class that encapsulates the logic to fetch the latest name from the database every time you request it. This way, every call to get the name triggers a fresh database lookup.

Step 1: Create the Dynamic Wrapper Class

import java.sql.*;
import java.util.HashMap;

public class DynamicEmployeeName {
    private final String employeeId;

    public DynamicEmployeeName(String employeeId) {
        this.employeeId = employeeId;
    }

    public String get() throws ClassNotFoundException, SQLException {
        HashMap<String, String> infoHR = connectionInfoHR();
        // Use prepared statement to avoid SQL injection!
        String query = "SELECT first_name FROM employees WHERE employee_id = ?";
        
        Class.forName("com.mysql.cj.jdbc.Driver");
        try (Connection con = DriverManager.getConnection(infoHR.get("url"), infoHR.get("uname"), infoHR.get("pass"));
             PreparedStatement st = con.prepareStatement(query)) {
            
            st.setString(1, employeeId);
            try (ResultSet rs = st.executeQuery()) {
                if (rs.next()) {
                    return rs.getString("first_name");
                }
                return "Employee not found";
            }
        } catch (Exception e) {
            e.printStackTrace();
            return "Failed to fetch name from database";
        }
    }

    // Helper method for connection credentials
    private HashMap<String, String> connectionInfoHR() {
        HashMap<String, String> info = new HashMap<>();
        info.put("url", "jdbc:mysql://localhost:3306/sql_hr");
        info.put("uname", "root");
        info.put("pass", "Culley1max1");
        return info;
    }
}

Step 2: Update Your Main Class to Use the Wrapper

import java.sql.SQLException;

public class GroundControlToMajorTom {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        // Create a dynamic name instance tied to employee ID 72913
        DynamicEmployeeName theName = new DynamicEmployeeName("72913");
        
        // Initial fetch (prints the original value, e.g., Jim)
        System.out.println(theName.get());
        
        // Update the name in the database
        changeEmployeeName("Kass", "72913");
        
        // Automatically gets the latest value (prints Kass)
        System.out.println(theName.get());
    }

    // Updated with prepared statement to fix SQL injection risk
    public static void changeEmployeeName(String name, String ID) throws ClassNotFoundException, SQLException {
        String url = "jdbc:mysql://localhost:3306/sql_hr";
        String uname = "root";
        String pass = "Culley1max1";
        String query = "UPDATE employees SET first_name = ? WHERE employee_ID = ?";
        
        Class.forName("com.mysql.cj.jdbc.Driver");
        try (Connection con = DriverManager.getConnection(url, uname, pass);
             PreparedStatement st = con.prepareStatement(query)) {
            st.setString(1, name);
            st.setString(2, ID);
            st.executeUpdate();
        }
    }
}

Critical Fix: SQL Injection Vulnerability

I noticed your original code uses Statement with string concatenation for queries—this is a massive security risk. Always use PreparedStatement with parameter placeholders (?) as shown above, which safely escapes user input and prevents attackers from manipulating your database.

Bonus: Optimize with Caching (Carefully)

If fetching from the database every time is too slow, you can add a short-lived cache to reduce database calls. Just make sure to invalidate the cache whenever you update the name:

public class DynamicEmployeeName {
    private final String employeeId;
    private String cachedName;
    private long cacheTimestamp;
    private static final long CACHE_DURATION_MS = 5000; // 5 seconds

    public String get() throws ClassNotFoundException, SQLException {
        long now = System.currentTimeMillis();
        // Check if cache is expired or empty
        if (cachedName == null || now - cacheTimestamp > CACHE_DURATION_MS) {
            cachedName = fetchNameFromDB(); // Reuse your fetch logic here
            cacheTimestamp = now;
        }
        return cachedName;
    }

    // Call this after updating the database to invalidate the cache
    public void invalidateCache() {
        cachedName = null;
    }

    // ... rest of the class ...
}

Then, in your changeEmployeeName method, add theName.invalidateCache() right after updating the database to ensure the next get() fetches fresh data.

Key Takeaways

  • Immutable types like String can't auto-update their values—use a wrapper class with a getter method to handle dynamic fetching.
  • Never use string concatenation for SQL queries—always use PreparedStatement to avoid injection attacks.
  • Caching can improve performance, but remember to invalidate it when data changes to keep values consistent.

内容的提问来源于stack exchange,提问作者YaBoyIsFat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 21:22:46