为什么我得到 java.sql 可能无法被客户端访问,因为缺少“需要传递”

F.M*_*F.M 2 java javafx

我的项目使用了 javafx 和 sdk20。我在使用数据库时遇到一些警告。(我的IDE是eclipse)

警告是:

Description Resource    Path    Location    Type
The type Connection from module java.sql may not be accessible to clients due to missing  'requires transitive' dbConnect.java  /myProject/src/mypackage line 25    Java Problem
Run Code Online (Sandbox Code Playgroud)

db.java:

package mypackage;;
import java.io.IOException;
import java.sql.*;     // Use classes in java.sql package
import java.util.Properties;

public class dbConnect {
 // init database constants
 static final String databaseDriver = "oracle.jdbc.driver.OracleDriver";
 static final String databaseURL = "jdbc:oracle:thin:@localhost:1521:xe";
 static final String username = "system";
 static final String pass = "oracle";
 private Connection connection;
 private Properties properties;
 private Statement statement;

/**
 * Connect to the database  
 * 
 * @return Connection
 */
public Connection connect()
{
    if (connection == null)
    {         
        try {
            Class.forName(databaseDriver);
            connection = (Connection) DriverManager.getConnection
                    (databaseURL, getProperties());
        }
        catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }
    }
    return connection;
}   
.
.
.
Run Code Online (Sandbox Code Playgroud)

模块信息.java

module myProject{
   requires transitive javafx.graphics;
   requires javafx.controls;
   requires javafx.fxml;
   requires javafx.base;
   requires javafx.web;
   requires java.sql;

   opens mypackage to javafx.fxml;
   exports mypackage;
}
Run Code Online (Sandbox Code Playgroud)

我对 ResultSet 和PreparedStatement 也有这些警告。我没有输入那段代码。

Jam*_*s_D 5

出现警告的原因是您的公共类中定义了一个返回类型为 的public方法。该方法表明可以从任何地方调用该方法,包括其他模块中需要您的 module 的任何类。但是,这些类将无法这样做,因为它们将无法访问模块中的类。connect()DbConnectConnectionpublicmyProjectConnectionjava.sql

您可能不需要该方法如此广泛地可访问。事实上,您的数据持久保存到关系数据库中,在一定程度上是一个实现细节,确实不应该暴露给应用程序中的其他层。

您可能有某种数据访问类,它可以访问和保留域对象,并使它们可供应用程序中的其他层使用(例如,表示层、UI 等):

package myPackage;

public class DataAccessor {

    private final Connection connection ;

    public DataAccessor() {
        DbConnect dbConnect = new DbConnect();
        this.connection = dbConnect.connect();
    }

    public List<Foo> getAllFoos() throws Exception {
        Statement statement = connection.createStatement();
        ResultSet result = statement.executeQuery("SELECT * FROM foo");
        List<Foo> foos = new ArrayList<>();
        while (result.next()) {
            Foo foo = new Foo();
            foo.setBar(result.getString("bar"))
            // ...
            foos.add(foo);
        }
        result.close();
        statement.close();
        return foos;
    }

    // etc
}
Run Code Online (Sandbox Code Playgroud)

在几乎所有情况下,任何数据访问类都属于与该类相同的包中DbConnect,并且该DbConnect.connect()方法在该包之外的任何地方都不需要。这意味着该connect()方法不需要是public,并且仅将可见性限制到所需的程度是一般的良好实践。

在这种常见情况下,您可以使该方法具有默认的“包私有”可见性,这将删除警告:

public class DbConnect {

    private Connection connection;

    Connection connect() {
        if (connection == null)
        {         
            try {
                Class.forName(databaseDriver);
                connection = (Connection) DriverManager.getConnection
                        (databaseURL, getProperties());
            }
            catch (ClassNotFoundException | SQLException e) {
                e.printStackTrace();
            }
        }
        return connection;
    } 

}
Run Code Online (Sandbox Code Playgroud)

如果(不太可能)您确实想让该connect()方法公开可用,则需要将该java.sql模块提供给模块的客户端。您可以通过传递要求该模块来做到这一点:

module myProject{
   requires transitive javafx.graphics;
   requires javafx.controls;
   requires javafx.fxml;
   requires javafx.base;
   requires javafx.web;
   requires transitive java.sql;

   opens mypackage to javafx.fxml;
   exports mypackage;
}
Run Code Online (Sandbox Code Playgroud)

但同样,您不太可能需要这样做,或者需要构建您的应用程序以使其成为必要。