Eclipse开发JavaFX应用Inno Setup安装后SQLite数据库创建异常
问题原因
你当前使用的SQLite JDBC连接串为jdbc:sqlite:patientdata,属于相对路径配置:SQLite会将数据库文件创建在JVM进程启动时的工作目录下。
- 在Eclipse开发环境、直接双击运行JAR包时,进程工作目录默认为项目根目录/JAR包所在目录,当前用户对该目录有完整读写权限,因此数据库创建、读写操作均正常。
- 通过Inno Setup打包安装后,应用默认安装到
C:\Program Files\<应用名称>目录,Windows系统对该目录有严格的权限控制,普通运行的进程没有写入权限,会直接拦截数据库文件创建操作;即便系统触发UAC虚拟化把文件重定向到VirtualStore目录,也不会出现在原安装路径下,自然找不到存储位置。
修复方案
1. 固定数据库存储到用户有权限的目录
不要使用相对路径连接数据库,将数据库存储到系统为用户应用分配的专属数据目录,该目录默认对当前用户开放完整读写权限,不会有权限问题。修改getConnection()方法中的连接逻辑,先拼接数据库文件的绝对路径再建立连接:
public static Connection getConnection() throws Exception { Connection conn = null; // 适配不同操作系统的应用数据目录 String appDataBase; String osName = System.getProperty("os.name").toLowerCase(); if (osName.contains("win")) { appDataBase = System.getenv("APPDATA"); } else if (osName.contains("mac")) { appDataBase = System.getProperty("user.home") + "/Library/Application Support"; } else { appDataBase = System.getProperty("user.home") + "/.config"; } // 为当前应用创建独立存储文件夹 File appDir = new File(appDataBase + File.separator + "PatientSystem"); if (!appDir.exists()) { appDir.mkdirs(); } File dbFile = new File(appDir, "patientdata.db"); String jdbcUrl = "jdbc:sqlite:" + dbFile.getAbsolutePath(); Class.forName("org.sqlite.JDBC"); conn = DriverManager.getConnection(jdbcUrl); // 建表逻辑 try (Statement stmt = conn.createStatement()) { String pat = "CREATE TABLE if not exists newpatient " + "(patientId INTEGER NOT NULL," + " patientName CHAR(50) NOT NULL, " + " patientAge INTEGER NOT NULL, " + "patientGender CHAR(10) NOT NULL,"+ "patientAddress CHAR(100) NOT NULL,"+ "patientMobile BIGINT(10) NOT NULL)"; stmt.executeUpdate(pat); String hist = "CREATE TABLE if not exists history " + "(id INTEGER NOT NULL," + " date DATE NOT NULL, " + " start TIME NOT NULL, " + "stop TIME NOT NULL)"; stmt.executeUpdate(hist); } return conn; }
2. 编程读取数据库实际存储路径
建立连接后,执行SQLite内置的PRAGMA database_list命令即可直接获取主数据库文件的绝对路径:
try (Statement st = conn.createStatement(); ResultSet rs = st.executeQuery("PRAGMA database_list")) { while (rs.next()) { if (rs.getInt("seq") == 0) { // seq=0对应主数据库 String realDbPath = rs.getString("file"); System.out.println("数据库实际存储位置:" + realDbPath); } } }
3. 其他需要修复的隐患
你当前insertrecord()方法直接拼接用户输入生成SQL语句,存在严重的SQL注入风险,且输入内容包含单引号时会直接触发SQL语法错误,建议替换为PreparedStatement做参数化查询。另外数据库连接、Statement等资源用完要及时关闭,避免出现连接泄漏。
不要通过Inno Setup给Program Files下的安装目录配置全局写入权限,这违反Windows系统安全规范,会给用户设备带来安全风险,用户数据必须存储到用户专属数据目录。
内容的提问来源于stack exchange,提问作者mexco
相关产品推荐
相关产品推荐

