当前位置: 首页 > 知识库问答 >
问题:

datastax mapper类中timeuid的数据类型应该是什么?

魏冷勋
2023-03-14

cassandra表中一列的数据类型为timeuuid。

在根据文档创建映射器类时,我不确定timeuuid列应该使用哪种数据类型。我知道它应该是一个等价的Java数据类型,因此我尝试了Java。util。日期请参阅列定义和映射器类列定义,如下所示

 start timeuuid

 @PartitionKey(1)
 @Column(name="start")
 private UUID start;

我在CRUD操作过程中得到以下信息

找不到请求操作的编解码器:[timeuuid-

共有1个答案

陈实
2023-03-14

我已经定制了datastax的UUIDs类,以从一个时间获取TimeUUID。下面是带有exmaple的完整代码

/*
 *      Copyright (C) 2012-2015 DataStax Inc.
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */
package com.datastax.driver.core.utils;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.concurrent.atomic.AtomicLong;

/**
 * Utility methods to work with UUID and most specifically with time-based ones (version 1).
 */
public final class UUIDs {

    private UUIDs() {
    }

    ;

    // http://www.ietf.org/rfc/rfc4122.txt
    private static final long START_EPOCH = makeEpoch();
    private static final long CLOCK_SEQ_AND_NODE = makeClockSeqAndNode();

    /*
     * The min and max possible lsb for a UUID.
     * Note that his is not 0 and all 1's because Cassandra TimeUUIDType
     * compares the lsb parts as a signed byte array comparison. So the min
     * value is 8 times -128 and the max is 8 times +127.
     *
     * Note that we ignore the uuid variant (namely, MIN_CLOCK_SEQ_AND_NODE
     * have variant 2 as it should, but MAX_CLOCK_SEQ_AND_NODE have variant 0)
     * because I don't trust all uuid implementation to have correctly set
     * those (pycassa don't always for instance).
     */
    private static final long MIN_CLOCK_SEQ_AND_NODE = 0x8080808080808080L;
    private static final long MAX_CLOCK_SEQ_AND_NODE = 0x7f7f7f7f7f7f7f7fL;

    private static final AtomicLong lastTimestamp = new AtomicLong(0L);

    private static long makeEpoch() {
        // UUID v1 timestamp must be in 100-nanoseconds interval since 00:00:00.000 15 Oct 1582.
        Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT-0"));
        c.set(Calendar.YEAR, 1582);
        c.set(Calendar.MONTH, Calendar.OCTOBER);
        c.set(Calendar.DAY_OF_MONTH, 15);
        c.set(Calendar.HOUR_OF_DAY, 0);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        c.set(Calendar.MILLISECOND, 0);
        return c.getTimeInMillis();
    }

    private static long makeNode() {

        /*
         * We don't have access to the MAC address (in pure JAVA at least) but
         * need to generate a node part that identify this host as uniquely as
         * possible.
         * The spec says that one option is to take as many source that
         * identify this node as possible and hash them together. That's what
         * we do here by gathering all the ip of this host as well as a few
         * other sources.
         */
        try {

            MessageDigest digest = MessageDigest.getInstance("MD5");
            for (String address : getAllLocalAddresses()) {
                update(digest, address);
            }

            Properties props = System.getProperties();
            update(digest, props.getProperty("java.vendor"));
            update(digest, props.getProperty("java.vendor.url"));
            update(digest, props.getProperty("java.version"));
            update(digest, props.getProperty("os.arch"));
            update(digest, props.getProperty("os.name"));
            update(digest, props.getProperty("os.version"));

            byte[] hash = digest.digest();

            long node = 0;
            for (int i = 0; i < 6; i++) {
                node |= (0x00000000000000ffL & (long) hash[i]) << (i * 8);
            }
            // Since we don't use the mac address, the spec says that multicast
            // bit (least significant bit of the first byte of the node ID) must be 1.
            return node | 0x0000010000000000L;
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }

    private static void update(MessageDigest digest, String value) {
        if (value != null) {
            digest.update(value.getBytes(Charset.forName("utf-8")));
        }
    }

    private static long makeClockSeqAndNode() {
        long clock = new Random(System.currentTimeMillis()).nextLong();
        long node = makeNode();

        long lsb = 0;
        lsb |= (clock & 0x0000000000003FFFL) << 48;
        lsb |= 0x8000000000000000L;
        lsb |= node;
        return lsb;
    }

    /**
     * Creates a new random (version 4) UUID.
     * <p/>
     * This method is just a convenience for {@code UUID.randomUUID()}.
     *
     * @return a newly generated, pseudo random, version 4 UUID.
     */
    public static UUID random() {
        return UUID.randomUUID();
    }

    /**
     * Creates a new time-based (version 1) UUID.
     * <p/>
     * UUID generated by this method are suitable for use with the {@code timeuuid} Cassandra type. In particular the generated UUID includes the timestamp of its generation.
     *
     * @return a new time-based UUID.
     */
    public static UUID timeBased() {
        return new UUID(makeMSB(getCurrentTimestamp()), CLOCK_SEQ_AND_NODE);
    }

    public static UUID getTimeUUID(long tstamp) {
        long timestamp = (tstamp - START_EPOCH) * 10000;
        long msb = 0L;
        msb |= (0x00000000ffffffffL & timestamp) << 32;
        msb |= (0x0000ffff00000000L & timestamp) >>> 16;
        msb |= (0x0fff000000000000L & timestamp) >>> 48;
        msb |= 0x0000000000001000L; // sets the version to 1.
        return new UUID(msb, CLOCK_SEQ_AND_NODE);
    }

    /**
     * Creates a "fake" time-based UUID that sorts as the smallest possible version 1 UUID generated at the provided timestamp.
     * <p/>
     * Such created UUID are useful in queries to select a time range of a {@code timeuuid} column.
     * <p/>
     * The UUID created by this method <b>are not unique</b> and as such are
     * <b>not</b> suitable for anything else than querying a specific time range. In particular, you should not insert such UUID.
     * <p/>
     * Also, the timestamp to provide as parameter must be a unix timestamp (as returned by {@link System#currentTimeMillis} or {@link java.util.Date#getTime}), not a UUID 100-nanoseconds intervals since 15 October 1582. In other words, given a UUID {@code uuid}, you should never do {@code startOf(uuid.timestamp())} but rather {@code startOf(unixTimestamp(uuid.timestamp()))}.
     * <p/>
     * Lastly, please note that Cassandra's timeuuid sorting is not compatible with {@link UUID#compareTo} and hence the UUID created by this method are not necessarily lower bound for that latter method.
     *
     * @param timestamp the unix timestamp for which the created UUID must be a lower bound.
     * @return the smallest (for Cassandra timeuuid sorting) UUID of {@code timestamp}.
     */
    public static UUID startOf(long timestamp) {
        return new UUID(makeMSB(fromUnixTimestamp(timestamp)), MIN_CLOCK_SEQ_AND_NODE);
    }

    /**
     * Creates a "fake" time-based UUID that sorts as the biggest possible version 1 UUID generated at the provided timestamp.
     * <p/>
     * Such created UUID are useful in queries to select a time range of a {@code timeuuid} column.
     * <p/>
     * The UUID created by this method <b>are not unique</b> and as such are
     * <b>not</b> suitable for anything else than querying a specific time range. In particular, you should not insert such UUID.
     * <p/>
     * Also, the timestamp to provide as parameter must be a unix timestamp (as returned by {@link System#currentTimeMillis} or {@link java.util.Date#getTime}), not a UUID 100-nanoseconds intervals since 15 October 1582. In other words, given a UUID {@code uuid}, you should never do {@code startOf(uuid.timestamp())} but rather {@code startOf(unixTimestamp(uuid.timestamp()))}.
     * <p/>
     * Lastly, please note that Cassandra's timeuuid sorting is not compatible with {@link UUID#compareTo} and hence the UUID created by this method are not necessarily upper bound for that latter method.
     *
     * @param timestamp the unix timestamp for which the created UUID must be an upper bound.
     * @return the biggest (for Cassandra timeuuid sorting) UUID of {@code timestamp}.
     */
    public static UUID endOf(long timestamp) {
        long uuidTstamp = fromUnixTimestamp(timestamp + 1) - 1;
        return new UUID(makeMSB(uuidTstamp), MAX_CLOCK_SEQ_AND_NODE);
    }

    /**
     * Return the unix timestamp contained by the provided time-based UUID.
     * <p/>
     * This method is not equivalent to {@code uuid.timestamp()}. More precisely, a version 1 UUID stores a timestamp that represents the number of 100-nanoseconds intervals since midnight, 15 October 1582 and that is what {@code uuid.timestamp()} returns. This method however converts that timestamp to the equivalent unix timestamp in milliseconds, i.e. a timestamp representing a number of milliseconds since midnight, January 1, 1970 UTC. In particular the timestamps returned by this method are comparable to the timestamp returned by {@link System#currentTimeMillis}, {@link java.util.Date#getTime}, etc.
     *
     * @param uuid the UUID to return the timestamp of.
     * @return the unix timestamp of {@code uuid}.
     * @throws IllegalArgumentException if {@code uuid} is not a version 1 UUID.
     */
    public static long unixTimestamp(UUID uuid) {
        if (uuid.version() != 1) {
            throw new IllegalArgumentException(String.format("Can only retrieve the unix timestamp for version 1 uuid (provided version %d)", uuid.version()));
        }

        long timestamp = uuid.timestamp();
        return (timestamp / 10000) + START_EPOCH;
    }

    /*
     * Note that currently we use System.currentTimeMillis() for a base time in
     * milliseconds, and then if we are in the same milliseconds that the
     * previous generation, we increment the number of nanoseconds.
     * However, since the precision is 100-nanoseconds intervals, we can only
     * generate 10K UUID within a millisecond safely. If we detect we have
     * already generated that much UUID within a millisecond (which, while
     * admittedly unlikely in a real application, is very achievable on even
     * modest machines), then we stall the generator (busy spin) until the next
     * millisecond as required by the RFC.
     */
    private static long getCurrentTimestamp() {
        while (true) {
            long now = fromUnixTimestamp(System.currentTimeMillis());
            long last = lastTimestamp.get();
            if (now > last) {
                if (lastTimestamp.compareAndSet(last, now)) {
                    return now;
                }
            } else {
                long lastMillis = millisOf(last);
                // If the clock went back in time, bail out
                if (millisOf(now) < millisOf(last)) {
                    return lastTimestamp.incrementAndGet();
                }

                long candidate = last + 1;
                // If we've generated more than 10k uuid in that millisecond,
                // we restart the whole process until we get to the next millis.
                // Otherwise, we try use our candidate ... unless we've been
                // beaten by another thread in which case we try again.
                if (millisOf(candidate) == lastMillis && lastTimestamp.compareAndSet(last, candidate)) {
                    return candidate;
                }
            }
        }
    }

    // Package visible for testing
    static long fromUnixTimestamp(long tstamp) {
        return (tstamp - START_EPOCH) * 10000;
    }

    private static long millisOf(long timestamp) {
        return timestamp / 10000;
    }

    // Package visible for testing
    static long makeMSB(long timestamp) {
        long msb = 0L;
        msb |= (0x00000000ffffffffL & timestamp) << 32;
        msb |= (0x0000ffff00000000L & timestamp) >>> 16;
        msb |= (0x0fff000000000000L & timestamp) >>> 48;
        msb |= 0x0000000000001000L; // sets the version to 1.
        return msb;
    }

    private static Set<String> getAllLocalAddresses() {
        Set<String> allIps = new HashSet<String>();
        try {
            InetAddress localhost = InetAddress.getLocalHost();
            allIps.add(localhost.toString());
            // Also return the hostname if available, it won't hurt (this does a dns lookup, it's only done once at startup)
            allIps.add(localhost.getCanonicalHostName());
            InetAddress[] allMyIps = InetAddress.getAllByName(localhost.getCanonicalHostName());
            if (allMyIps != null) {
                for (int i = 0; i < allMyIps.length; i++) {
                    allIps.add(allMyIps[i].toString());
                }
            }
        } catch (UnknownHostException e) {
            // Ignore, we'll try the network interfaces anyway
        }

        try {
            Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces();
            if (en != null) {
                while (en.hasMoreElements()) {
                    Enumeration<InetAddress> enumIpAddr = en.nextElement().getInetAddresses();
                    while (enumIpAddr.hasMoreElements()) {
                        allIps.add(enumIpAddr.nextElement().toString());
                    }
                }
            }
        } catch (SocketException e) {
            // Ignore, if we've really got nothing so far, we'll throw an exception
        }

        return allIps;
    }

    public static void main(String[] args) {
        long time = System.currentTimeMillis();
        System.out.println(UUIDs.getTimeUUID(time));
    }
}
 类似资料:
  • 我试图在Hibernate中映射PostgreSQL表。我正在写一个POJO类。有一列带有类型。如何在POJO类中为getters和setter方法声明java数据类型? 和不工作。

  • 我将MySQL与Spring JDBC模板一起用于我的web应用程序。我需要只存储数字(10)的电话号码。我对使用数据类型的数据类型有点困惑。 MySQL中更可取的数据类型是什么

  • 我正在做一个类项目的游戏,有人建议我用一个图ADT来表示世界地图上的一组领土,这样每个顶点都是一个领土,边代表玩家可以在其中移动的相邻领土。我找到了一个很好的图形ADT(JGraphT)Java库,但我完全不知道什么类型的边应该是... 例如,界面明确要求我为顶点定义一个对象类型(我认为使用我的类型非常有意义),但是边应该是什么?我想不出有什么对象类型可以作为边缘使用。

  • POST请求中的内容类型和数据类型是什么?假设我有这个: 是我们发送的吗?那么我们在上面的例子中发送的是JSON,而我们收到的是纯文本?我真的不明白。

  • 问题内容: 我有以下课程(来自简单的Spring教程) 其中Validator类是Spring 2.5中的类。 如果我尝试向其中添加参数,则supports方法显示警告(Class是原始类型。对泛型类型Class的引用应进行参数化) 我收到以下错误: 关于这种类型的问题有很多线索,但是我想获得一个完整的答案并真正理解它,而不会用“隐藏”这个问题! 问题答案: 接口使用原始类型声明该方法。在这种情况

  • 我目前正在通过做rosalind问题(基本上是一堆生物信息学相关的代码katas)来学习Go。 我当前表示的DNA链类型为: 我最初的原因是封装字节片,这样我就知道它只包含代表核苷酸的字节:。我意识到这显然不是瓜分,因为我可以简单地做到: 由于我的结构只包含一个字节数组,这样做是否更好/更理想: 还是让类型包含dna链更好?对于何时使用这两种方法中的任何一种,有什么经验法则吗?