这些答案大多是古老的。Mongo 驱动程序更新了很多,并且发生了巨大的变化。这是截至 2019 年 3 月 6 日的答案 - 使用最新版本的 Mongo Java 驱动程序 - 版本 3.10.1,使用最新版本的 Joda time - 2.10.1。我故意使用完全限定的类名,这样就不会混淆正在使用的库。因此,不需要任何导入语句。
**
编辑 2019-03-09:
来自用户@OleV.V 的反馈。(见下面的评论)表明 Joda Time 可能不如 Java 8 java.time 库。经过调查,我发现当前的 MongoDB Java 驱动程序正确支持 java.time.Instant.now() 方法,并且无需编解码器即可保存 ISODate。此处提供的信息说明了如何将自定义编解码器添加到驱动程序。仅出于这个原因,我相信这个答案是有价值的。
**
我的答案来自于https://gist.github.com/squarepegsys/9a97f7c70337e7c5e006a436acd8a729上的 SquarePegSys BigDecimalCodec.java 的工作,不同之处在于他们的解决方案是针对支持大十进制值,我的解决方案是针对 Joda DateTime 兼容性。
我喜欢先提供程序的输出,然后再显示源代码。通过这种方式,您可以在投入时间消化和理解代码之前评估输出是否提供了您正在寻找的解决方案。同样,重点是使用 Joda 时间在 mongoDB 中将日期值保存为 ISODate 数据类型,即,保存的 DateTime 不会保存为字符串。
我正在使用 Maven 构建。我正在运行 Ubuntu 18.04LTS。
$ mvn -version
Apache Maven 3.5.2
Maven home: /usr/share/maven
Java version: 10.0.2, vendor: Oracle Corporation
Java home: /usr/lib/jvm/java-11-openjdk-amd64
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "4.15.0-43-generic", arch: "amd64", family: "unix"
构建程序:
cd <directory holding pom.xml file>
mvn package
运行程序:
$ java -jar Test.jar
Mar 06, 2019 5:12:02 PM com.mongodb.diagnostics.logging.JULLogger log
INFO: Cluster created with settings {hosts=[127.0.0.1:27017], mode=SINGLE, requiredClusterType=UNKNOWN, serverSelectionTimeout='30000 ms', maxWaitQueueSize=500}
Mar 06, 2019 5:12:03 PM com.mongodb.diagnostics.logging.JULLogger log
INFO: Opened connection [connectionId{localValue:1, serverValue:9}] to 127.0.0.1:27017
Mar 06, 2019 5:12:03 PM com.mongodb.diagnostics.logging.JULLogger log
INFO: Monitor thread successfully connected to server with description ServerDescription{address=127.0.0.1:27017, type=STANDALONE, state=CONNECTED, ok=true, version=ServerVersion{versionList=[4, 0, 6]}, minWireVersion=0, maxWireVersion=7, maxDocumentSize=16777216, logicalSessionTimeoutMinutes=30, roundTripTimeNanos=3220919}
Mar 06, 2019 5:12:03 PM com.mongodb.diagnostics.logging.JULLogger log
INFO: Opened connection [connectionId{localValue:2, serverValue:10}] to 127.0.0.1:27017
使用 mongo shell 查询结果:
MongoDB > db.testcollection.find().pretty()
{
"_id" : ObjectId("5c806e6272b3f469d9969157"),
"name" : "barry",
"status" : "cool",
"number" : 1,
"date" : ISODate("2019-03-07T01:05:38.381Z")
}
源代码
一共实现了4个类(pom.xml文件只是一个构建工具文件)...
- 主要的
- 变压器
- 提供者
- 编解码器
pom.xml
<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>test.barry</groupId>
<artifactId>test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>test</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<outputDirectory>${basedir}</outputDirectory>
<finalName>Test</finalName>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>test.barry.Main</mainClass>
</transformer>
</transformers>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.10.1</version>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.10.1</version>
</dependency>
</dependencies>
</project>
主.java
package test.barry;
public class Main {
public static void main(String[] args) {
java.util.ArrayList<com.mongodb.ServerAddress> hosts = new java.util.ArrayList<com.mongodb.ServerAddress>();
hosts.add(new com.mongodb.ServerAddress("127.0.0.1", 27017));
com.mongodb.MongoCredential mongoCredential = com.mongodb.MongoCredential.createScramSha1Credential("testuser", "admin", "mysecret".toCharArray());
org.bson.BSON.addEncodingHook(org.joda.time.DateTime.class, new test.barry.DateTimeTransformer());
org.bson.codecs.configuration.CodecRegistry codecRegistry = org.bson.codecs.configuration.CodecRegistries.fromRegistries(
org.bson.codecs.configuration.CodecRegistries.fromProviders(
new test.barry.DateTimeCodecProvider()
), com.mongodb.MongoClient.getDefaultCodecRegistry()
);
com.mongodb.MongoClientSettings mongoClientSettings = com.mongodb.MongoClientSettings.builder()
.applyToClusterSettings(clusterSettingsBuilder -> clusterSettingsBuilder.hosts(hosts))
.credential(mongoCredential)
.writeConcern(com.mongodb.WriteConcern.W1)
.readConcern(com.mongodb.ReadConcern.MAJORITY)
.readPreference(com.mongodb.ReadPreference.nearest())
.retryWrites(true)
.codecRegistry(codecRegistry)
.build();
com.mongodb.client.MongoClient client = com.mongodb.client.MongoClients.create(mongoClientSettings);
com.mongodb.client.MongoDatabase db = client.getDatabase("testdb");
com.mongodb.client.MongoCollection<org.bson.Document> collection = db.getCollection("testcollection");
// BUILD UP A DOCUMENT
org.bson.Document document = new org.bson.Document("name", "barry")
.append("status", "cool")
.append("number", 1)
.append("date", new org.joda.time.DateTime());
collection.insertOne(document);
}
}
日期时间编解码器.java
package test.barry;
public class DateTimeCodec implements org.bson.codecs.Codec<org.joda.time.DateTime> {
@Override
public void encode(final org.bson.BsonWriter writer, final org.joda.time.DateTime value, final org.bson.codecs.EncoderContext encoderContext) {
writer.writeDateTime(value.getMillis());
}
@Override
public org.joda.time.DateTime decode(final org.bson.BsonReader reader, final org.bson.codecs.DecoderContext decoderContext) {
return new org.joda.time.DateTime(reader.readDateTime());
}
@Override
public Class<org.joda.time.DateTime> getEncoderClass() {
return org.joda.time.DateTime.class;
}
}
DateTimeCodecProvider.java
package test.barry;
public class DateTimeCodecProvider implements org.bson.codecs.configuration.CodecProvider {
@Override
public <T> org.bson.codecs.Codec<T> get(final Class<T> classToVerify, final org.bson.codecs.configuration.CodecRegistry registry) {
if (classToVerify == org.joda.time.DateTime.class) {
return (org.bson.codecs.Codec<T>) new DateTimeCodec();
}
return null;
}
}
日期时间转换器.java
package test.barry;
public class DateTimeTransformer implements org.bson.Transformer {
@Override
public Object transform(Object objectToTransform) {
org.joda.time.DateTime value = (org.joda.time.DateTime) objectToTransform;
return value;
}
}
结论
Java 世界似乎被 Joda 时代所吸引。它是一个不错的库,可以缓解常见的日期/时间需求。我的猜测是 Mongo 会原生支持这个库,但现在我们必须帮助它。
快速说明: 我尝试使用最现代的 mongoDB 类,但在 Main.java 类中,我引用了一个较旧的库方法 - com.mongodb.MongoClient.getDefaultCodecRegistry(),因为我在 com.mongodb.client 中找不到它。蒙古客户。如果您确定如何使用 com.mongodb.client.MongoClient 代替,请添加评论...