下面的代码使用Ucanaccess Jdbc驱动程序从Microsoft Access文件Filename.accdb获取连接。但是在运行此代码时,它会像File已经被使用一样抛出异常。
但我想在其他应用程序使用时同时使用MS Access数据库文件。
//Code for connecting with MS Access Database
public void getConnection(){
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try {
Class.forName("net.ucanaccess.jdbc.UcanaccessDriver");
} catch (ClassNotFoundException cnfex) {
logger.error("Problem in loading or "
+ "registering MS Access JDBC driver " + cnfex);
}
String dbURL = "jdbc:ucanaccess://" + msAccDB;
logger.info("DB File Url = " + msAccDB);
try {
DriverManager.registerDriver(new UcanaccessDriver());
connection = DriverManager.getConnection(dbURL);
} catch (SQLException ex) {
logger.error(ex);
}
return connection;
}
虽然我运行上面的代码得到例外,如:
net.ucanaccess.jdbc.UcanaccessSQLException:UCAExc ::: 4.xx E:\ FileName.accdb(进程无法访问该文件,因为它正由另一个进程使用)net.ucanaccess.jdbc.UcanaccessDriver.connect(UcanaccessDriver。 java:231)at java.sql.DriverManager.getConnection(DriverManager.java:664)at java.sql.DriverManager.getConnection(DriverManager.java:270) ................ ................................................ .. .................................................. ........... ....................................... ........................ at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62 )在com.un.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java: 389)at com.sun.javafx.application.LauncherImpl.launchApplication(Launcher) Impl.java:328)sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)at java .lang.reflect.Method.invoke(Method.java:498)at sun.launcher.LauncherHelper $ FXHelper.main(LauncherHelper.java:767)引起:java.io.FileNotFoundException:E:\ Retail Expert Data \ Pos。 accdb(进程无法访问该文件,因为它正由另一个进程使用)在java.io.RandomAccessFile.open0(本机方法)java.io.RandomAccessFile.open(RandomAccessFile.java:316)java.io.RandomAccessFile 。(RandomAccessFile.java:243)com.healthmarketscience.jackcess。 .jackcess.DatabaseBuilder.open(DatabaseBuilder.java:252)at net.ucanaccess.jdbc.DefaultJackcessOpener.open(Defaul) tJackcessOpener.java:35)net.ucanaccess.jdbc.DBReference。(DBReference.java:169)net.ucanaccess.jdbc.DBReferenceSingleton.loadReference(DBReferenceSingleton.java:51)at net.ucanaccess.jdbc.UcanaccessDriver.connect( UcanaccessDriver.java:90)......还有17个
对于这种类型的场景,最好迁移到SQL服务器,这样可以比Access更好地(更安全,更快)地处理多用户访问,同时通常保留兼容的数据结构。
另一个应用程序在数据库文件上执行了“Open Exclusive”。因此,没有其他进程可以同时打开数据库。
如果您希望两个应用程序同时访问数据库,则需要让另一个应用程序以非独占模式打开数据库。另外,请注意此博客文章中描述的限制:
确保Microsoft Access应用程序已拆分 - 前端文件链接到后端表。然后复制前端文件供您自己专用。
在Access的多用户设置中 - 必须将其拆分,并且每个用户必须拥有自己的前端文件。
有人建议我使用C#Dot Net。我试图访问MSAccess数据库令人惊讶它与OleDBConnection一起工作,而Microsoft Access文件与其他应用程序一起使用,并且文件也已打开。
结帐解决方案
如果我们使用另一种语言,如C#。
当它被另一个应用程序使用时,绝对可以访问Ms访问数据库文件。
public static OleDbConnection GetMSAccessDatabaseConnection(){
// If accdb file password ecrypted
string ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + file_path + ";Jet OLEDB:Database Password=" + your_password + ";";
// Without password
string ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + file_path + ";Persist Security Info=False;";
try{
return new OleDbConnection(ConnectionString);
}
catch(Exception ex){
// Log your Exception
return null;
}
}
UCanAccess不支持这一点。它需要对数据库文件的独占访问权限。
https://ucanaccess.blogspot.com/2017/07/multiuser-concurrent-write-access.html
根据我的经验,只要您不通过UCanAccess更新数据库,数据库文件就不会被破坏。不保证,但......
您可以使用jdbc-odbc-bridge代替。您可以谷歌如何将桥接器从Java 7迁移到Java 8,这样您就可以使用所有酷的Java 8功能,还可以在Wine中配置odbc,以便您的Java应用程序可以在支持Windows jre / jdk的Linux上运行JDBC-ODBC桥。但是,由于数据库文件驻留在“E:”驱动器上,我假设您使用Windows,因此您不需要Wine。
如果情况相反,您还可以设置一个通用的Docker容器,其中包含Wine,windows-java和odbc,以便您可以轻松地启动运行jar文件的容器并从主机文件系统访问数据库文件。它有点慢,但工作得很好,除了调试,这非常慢。
以下是我打算解决类似问题的方法。它非常难看(是的,真的,真的,非常难看),但它只是暂时的,并且允许从Microsoft Access到jdbc支持的数据库的逐步过渡,而不必在Windows上运行东西:
我将从UCanAccess开始
<dependency>
<groupId>net.ttddyy</groupId>
<artifactId>datasource-proxy</artifactId>
<version>1.5.1</version>
</dependency>
然后我将使用ProxyDataSourceBuilder和QueryTransformer拦截所有jdbc语句(来自datasource-proxy,在github上解释用法)。所有选择都将被允许通过未触发,但创建,更新和删除将被截获,我将手动“解析”所有查询参数(参数化查询中的所有?),并将字符串传递给文件,或者rest-api,运行在Wine中的Windows-java服务可以通过odbc和Access数据库引擎来获取它并执行它。然后我会抛出一些异常来防止UCanAccess实际写入Access数据库文件。 Hibernate会对失败的乐观锁定做很多大惊小怪,但是可以捕获任何异常,以便实际的应用程序可以继续。
显然,这不是如何在生产环境中完成的,但是如果它在某种程度上证明是“稳定的”,那么我可以直到远离Access完成迁移,而无需在VMWare中设置Windows开发环境或运行应用程序在Windows上。这显然是一个不尝试这种家庭孩子的特技,但我的应用程序没有并发用户,不需要速度,没有无法从备份恢复的过于重要的数据,等等所以我想我会试一试。