最近连着两个项目碰到同一个报错:pom.xml 里明明写的是 com.microsoft.sqlserver:sqljdbc4:4.0,但 Maven 就是卡在 Cannot resolve com.microsoft.sqlserver:sqljdbc4:4.0,IDEA 中依赖列表红成一片,mvn compile 直接失败。这个报错看起来像网络问题,实际排查下来,大多数情况是坐标本身已经过时、写法有误,或者依赖根本没被正确放进仓库。这篇文章我把从报错现场到最终落地解决的各种路径都梳理一遍,给还在跟 SQL Server JDBC 驱动死磕的同学一个能直接照着做的参考。
1. 为什么一个看似合法的坐标会解析失败
1.1 先看看最常见的几种报错现场
同一个报错背后,实际的项目代码可能完全不一样。我归纳了三种高频现场,你可以先对号入座:
第一种,也是最常见的一种,pom.xml 里写了:
xml复制<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>sqljdbc4</artifactId>
<version>4.0</version>
</dependency>
然后 IDEA 提示 Cannot resolve com.microsoft.sqlserver:sqljdbc4:4.0。
第二种,是把坐标拼错了。比如把 artifactId 写成 sqljdbc44、sqljdbc4.0,或者把 groupId 写成 com.microsoft.sqlserver.jdbc,又或者版本号写成 4.0.0。这类错字问题表面上看也是 Cannot resolve,但根子完全不一样。标题里那个 sqljdbc44.0 一眼就是书写错误,实际 Maven 坐标里不存在这个写法。
第三种,是公司用的私服或镜像没有同步过这个 artifact。本地 Maven 仓库里没有,私服也没有,中央仓库又因为网络配置访问不到,于是报错。
这三种情况的表象完全一样,但处理方式不同。所以遇到报错不要急着改配置,先把错误信息的上下文看全。Maven 在报 Cannot resolve 的同时,通常会给出完整的 groupId:artifactId:version 三段坐标,先确认你写的坐标和报错坐标是否一致,不一致就说明是拼写问题。
1.2 Maven 是如何找依赖的
要理解这个报错,得先搞清楚 Maven 找依赖的过程。Maven 坐标由 groupId:artifactId:version 三段组成,它定义了一个依赖的唯一身份。你可以把它理解成快递收件地址:国家、城市、街道都写对了,包裹才能送到。三段里任何一段不匹配,甚至大小写不对,都无法找到对应的 jar 包。
Maven 解析依赖的顺序是固定的:
- 先在本地仓库找,默认是
~/.m2/repository; - 本地没有,再看全局
settings.xml里配置的 mirror 镜像仓库; - 再看项目 pom.xml 里声明的
<repository>; - 最后才会访问中央仓库。
Cannot resolve 的本质,就是这套顺序走完了,仍然没有在任何一个位置找到对应坐标的 jar 包和 pom 文件。
这里有个很容易忽略的点:如果本地 ~/.m2 里已经缓存了某个坐标的 _remote.repositories 元数据,并且它记录了"这个文件来自某个具体的仓库地址",那么 Maven 在解析时会做仓库归属校验。私服地址变了、镜像变了,哪怕本地明明有 jar,也可能重新去远程拉,一旦远程拉不到就报 Cannot resolve。这属于比较隐蔽的情况,后面会专门讲。
1.3 sqljdbc4 4.0 的历史遗留属性
sqljdbc4 4.0 这个坐标之所以让人头疼,很大程度是因为微软 JDBC 驱动早期的命名和发布方式比较混乱。
早期微软发布的 SQL Server JDBC Driver 版本和 Java 版本强绑定。4.0 对应的是旧版的 sqljdbc4.jar,接着又有 4.1、4.2 等版本。不同 JDK 要使用不同 jar:
sqljdbc44.0 支持 JDK 5、6、7;sqljdbc414.1 支持 JDK 7;sqljdbc424.2 支持 JDK 8。
后来微软统一改为 com.microsoft.sqlserver:mssql-jdbc 作为官方坐标,jar 包按 jre7、jre8、jre11、jre17 等后缀区分。也就是说,sqljdbc4:4.0 是一个已经被官方后续版本取代的旧坐标。
但问题在于,很多老教程和博客写的就是 sqljdbc4:4.0。新手照着复制,自然踩坑。而且旧坐标里的
