How to get postgres create table sql

获取 postgres 的建表语句的几种方法

使用 pg_dump

可以使用 pg_dump 直接查看建表语句 以本机 docker 的 postgres 为例

docker run -it --rm  postgres pg_dump -h host.docker.internal -p 5432 -U postgres -d demo_ds_0 -s -t t_order_0

结果展示

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
--
-- PostgreSQL database dump
--

-- Dumped from database version 14.2 (Debian 14.2-1.pgdg110+1)
-- Dumped by pg_dump version 14.2 (Debian 14.2-1.pgdg110+1)

SET statement_timeout = 0;
SET lock_timeout = 0;
SET idle_in_transaction_session_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SELECT pg_catalog.set_config('search_path', '', false);
SET check_function_bodies = false;
SET xmloption = content;
SET client_min_messages = warning;
SET row_security = off;

SET default_tablespace = '';

SET default_table_access_method = heap;

--
-- Name: t_order_0; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.t_order_0 (
    order_id integer NOT NULL,
    user_id integer NOT NULL,
    status character varying(45)
);


ALTER TABLE public.t_order_0 OWNER TO postgres;

--
-- Name: TABLE t_order_0; Type: COMMENT; Schema: public; Owner: postgres
--

COMMENT ON TABLE public.t_order_0 IS 'haha';


--
-- Name: COLUMN t_order_0.order_id; Type: COMMENT; Schema: public; Owner: postgres
--

COMMENT ON COLUMN public.t_order_0.order_id IS 'haha';


--
-- Name: t_order_0 t_order_0_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres
--

ALTER TABLE ONLY public.t_order_0
    ADD CONSTRAINT t_order_0_pkey PRIMARY KEY (order_id);


--
-- PostgreSQL database dump complete
--

使用自定义函数

创建函数如下

guava EventBus 使用以及注意点

EventBus 的使用及注意点

使用

  • 创建全局实例
1
static final EventBus INSTANCE = new EventBus();
  • 将含有 @Subscribe 的方法注册到全局实例上
1
INSTANCE.register(this);
  • 发送 event
1
INSTANCE.post(event);

流程分析

采用上述方式时有以下几个注意点

  • 发送事件并且接受后处理事件是同步执行的,即同一个线程执行
  • 如果在接受事件方法中有嵌套发送事件,那么该嵌套发送的事件不会立即执行,会等到第一个事件的接收方法完成后,再执行第二个事件。

EventBus 调用流程分析

  • 创建 EventBus 实例
  • 将订阅者注册到 EventBus 实例上

创建 EventBus 实例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
public EventBus() {
    this("default");
  }

  /**
   * Creates a new EventBus with the given {@code identifier}.
   *
   * @param identifier a brief name for this bus, for logging purposes. Should be a valid Java
   *     identifier.
   */
  public EventBus(String identifier) {
    this(
        identifier,
        // 同步执行器
        MoreExecutors.directExecutor(),
        Dispatcher.perThreadDispatchQueue(),
        LoggingHandler.INSTANCE);
  }
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
private static final class PerThreadQueuedDispatcher extends Dispatcher {

    // This dispatcher matches the original dispatch behavior of EventBus.

    /** Per-thread queue of events to dispatch. */
    private final ThreadLocal<Queue<Event>> queue =
        new ThreadLocal<Queue<Event>>() {
          @Override
          protected Queue<Event> initialValue() {
            return Queues.newArrayDeque();
          }
    };

注册 EventBus 订阅者

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
  /**
   * Registers all subscriber methods on {@code object} to receive events.
   *
   * @param object object whose subscriber methods should be registered.
   */
  public void register(Object object) {
    subscribers.register(object);
  }

  /** Registers all subscriber methods on the given listener object. */
  void register(Object listener) {
    Multimap<Class<?>, Subscriber> listenerMethods = findAllSubscribers(listener);

    for (Entry<Class<?>, Collection<Subscriber>> entry : listenerMethods.asMap().entrySet()) {
      Class<?> eventType = entry.getKey();
      Collection<Subscriber> eventMethodsInListener = entry.getValue();

      CopyOnWriteArraySet<Subscriber> eventSubscribers = subscribers.get(eventType);

      if (eventSubscribers == null) {
        CopyOnWriteArraySet<Subscriber> newSet = new CopyOnWriteArraySet<>();
        eventSubscribers =
            MoreObjects.firstNonNull(subscribers.putIfAbsent(eventType, newSet), newSet);
      }

      eventSubscribers.addAll(eventMethodsInListener);
    }
  }

  /**
   * Returns all subscribers for the given listener grouped by the type of event they subscribe to.
   */
  private Multimap<Class<?>, Subscriber> findAllSubscribers(Object listener) {
    Multimap<Class<?>, Subscriber> methodsInListener = HashMultimap.create();
    Class<?> clazz = listener.getClass();
    for (Method method : getAnnotatedMethods(clazz)) {
      Class<?>[] parameterTypes = method.getParameterTypes();
      Class<?> eventType = parameterTypes[0];
      methodsInListener.put(eventType, Subscriber.create(bus, listener, method));
    }
    return methodsInListener;
  }

    /** Creates a {@code Subscriber} for {@code method} on {@code listener}. */
  static Subscriber create(EventBus bus, Object listener, Method method) {
    return isDeclaredThreadSafe(method)
        ? new Subscriber(bus, listener, method)
        // 调用方法采用 synchronized
        : new SynchronizedSubscriber(bus, listener, method);
  }

发送 event

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
 /**
   * Posts an event to all registered subscribers. This method will return successfully after the
   * event has been posted to all subscribers, and regardless of any exceptions thrown by
   * subscribers.
   *
   * <p>If no subscribers have been subscribed for {@code event}'s class, and {@code event} is not
   * already a {@link DeadEvent}, it will be wrapped in a DeadEvent and reposted.
   *
   * @param event event to post.
   */
  public void post(Object event) {
    Iterator<Subscriber> eventSubscribers = subscribers.getSubscribers(event);
    if (eventSubscribers.hasNext()) {
      dispatcher.dispatch(event, eventSubscribers);
    } else if (!(event instanceof DeadEvent)) {
      // the event had no subscribers and was not itself a DeadEvent
      post(new DeadEvent(this, event));
    }
  }
  // 这里需要注意,如果当前线程在调用的 post 方法中,嵌套调用 post,第二个 post方法不会立刻执行,而是会加入 队列中,等到队列中第一个任务处理完,才会继续处理。
  @Override
    void dispatch(Object event, Iterator<Subscriber> subscribers) {
      checkNotNull(event);
      checkNotNull(subscribers);
      Queue<Event> queueForThread = queue.get();
      queueForThread.offer(new Event(event, subscribers));

      if (!dispatching.get()) {
        dispatching.set(true);
        try {
          Event nextEvent;
          while ((nextEvent = queueForThread.poll()) != null) {
            while (nextEvent.subscribers.hasNext()) {
              nextEvent.subscribers.next().dispatchEvent(nextEvent.event);
            }
          }
        } finally {
          dispatching.remove();
          queue.remove();
        }
      }
    }

ShardingSphere Hint 实用指南

背景

Apache ShardingSphere 基于用户的实际使用场景,为用户打造了多种实用功能,包括数据分片、读写分离等。在数据分片功能中,Apache ShardingSphere 提供了标准分片、复合分片等多种实用的分片策略,在各种分片策略中,用户又可以配置相关分片算法,从而解决数据分片的问题。在读写分离功能中,ShardingSphere 为用户提供了静态和动态的两种读写分离类型以及丰富的负载均衡算法以满足用户实际需求。 可以看到 ShardingSphere 的分片和读写分离功能已经非常丰富,不过用户的真实使用场景是千变万化的。以多租户场景为例,用户期望按照登录账号所属租户进行分片,但是租户信息却并不是存在于每条业务 SQL 中,这时从 SQL 中提取分片字段的算法将无法发挥作用。再以读写分离为例,大部分场景下用户都希望能够将查询操作路由到从库上执行,但是在某些实时性要求很高的场景下,用户希望将 SQL 强制路由到主库执行,这时读写分离就无法满足业务要求。 基于以上痛点 Apache ShardingSphere 为用户提供了 Hint 功能,用户可以结合实际业务场景,利用 SQL 外部的逻辑进行强制路由或者分片。目前 ShardingSphere 为用户提供了两种 Hint 方式,一种通过 Java API 手动编程,利用 HintManager 进行强制路由和分片,这种方式对采用 JDBC 编程的应用非常友好,只需要少量的代码编写,就能够轻松实现不依赖 SQL 的分片或者强制路由功能。另外一种方式对于不懂开发的 DBA 而言更加友好,ShardingSphere 基于分布式 SQL 提供的使用方式,利用 SQL HINT 和 DistSQL HINT, 为用户提供了无需编码就能实现的分片和强制路由功能。接下来,让我们一起了解下这两种使用方式。