com.setronica.ucs.storage.PgStructMapStorage.java Source code

Java tutorial

Introduction

Here is the source code for com.setronica.ucs.storage.PgStructMapStorage.java

Source

/*
 * Copyright (C) 2014 SETRONICA - setronica.com
 * This source code is available under the terms of the GNU Lesser General Public License
 * as published by The Open Source Initiative (OSI), either version 3 of the License,
 * or (at your option) any later version.
 *
 * UCS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * See the GNU Lesser General Public License for more details.
 * You should have received a copy of the GNU Lesser General Public License.
 */

package com.setronica.ucs.storage;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.setronica.ucs.attributes.ContentException;
import com.setronica.ucs.product.IdentityType;
import com.setronica.ucs.product.ProductIdentity;
import com.setronica.ucs.product.identity.ProductIdentityFactory;
import gnu.trove.set.TLongSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.sql.*;
import java.util.HashMap;
import java.util.Map;

/**
 * User: nikolay
 * Date: 9/2/13
 */
public class PgStructMapStorage<K, V> extends MemMapStorage<K, V> implements MapStorage<K, V> {
    private static final Logger L = LoggerFactory.getLogger(PgStructMapStorage.class);

    private DataSource ds;
    private Connection c;
    private String tableName;
    private PreparedStatement deletePs;
    private PreparedStatement updatePs;
    private PgStructSerialization<K> keyS;
    private ObjectMapper mapper = new ObjectMapper();
    private Class<V> cls;

    public PgStructMapStorage(DataSource ds, String tableName, PgStructSerialization<K> keyS,
            ProductIdentityFactory identityFactory) {
        this.ds = ds;
        this.tableName = "ucs." + tableName;
        this.keyS = keyS;
        SimpleModule enumModule = new SimpleModule("MyModule")
                .addDeserializer(ProductIdentity.class, new MemProductIdentityDeserializer(identityFactory))
                .addDeserializer(TLongSet.class, new PgCategoryStorage.TLongSetDeserializer())
                .addSerializer(TLongSet.class, new PgCategoryStorage.TLongSetSerializer());
        mapper.registerModule(enumModule);
        L.info("Create PgStructMapStorage for table: {}", tableName);
    }

    public void setProto(V proto) {
        this.cls = (Class<V>) proto.getClass();
    }

    public void open() throws Exception {
        c = ds.getConnection();
        if (c.getAutoCommit()) {
            c.setAutoCommit(false);
        }
        updatePs = c.prepareStatement("SET LOCAL synchronous_commit TO OFF; WITH upsert as (update " + tableName
                + " m set val=cast(? as json) where id=" + keyS.saveSQL() + " RETURNING m.*), tmp as (select 1) "
                + " insert into " + tableName + " select " + keyS.saveSQL()
                + ", cast(? as json) val from tmp where 0=(select count(0) from upsert);  commit;");
        deletePs = c.prepareStatement("SET LOCAL synchronous_commit TO OFF; delete from " + tableName + " where id="
                + keyS.saveSQL() + "; commit;");
        L.info("Starting populate PgStructMapStorage for table: {}", tableName);

        data.clear();
        try (Statement stmt = c.createStatement();
                ResultSet rs = stmt.executeQuery(
                        "select " + keyS.readSQL() + ", val json_val from " + tableName + " order by id")) {
            while (rs.next()) {
                K key = keyS.restore(rs);
                String val = rs.getString("json_val");
                if (val != null) {
                    data.put(key, mapper.readValue(val, cls));
                }
            }
        }
        L.info("PgStructMapStorage for table {} has size {}", tableName, data.size());
    }

    public void close() throws SQLException {
        L.info("Close PgStructMapStorage for table: {}", tableName);
        updatePs.close();
        deletePs.close();
        c.close();
    }

    @Override
    protected void persist(K key, V value) {
        try {
            L.trace("persist: {}/{}", key, value);
            String jsonVal = mapper.writeValueAsString(value);
            int idx = 1;
            updatePs.setString(idx++, jsonVal);
            idx = keyS.save(key, updatePs, idx);
            idx = keyS.save(key, updatePs, idx);
            updatePs.setString(idx, jsonVal);
            updatePs.executeUpdate();
        } catch (IOException | SQLException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    protected void delete(K key, V value) {
        try {
            L.trace("delete: {}", key);
            keyS.save(key, deletePs, 1);
            deletePs.executeUpdate();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    public static class MemProductIdentityDeserializer extends JsonDeserializer<ProductIdentity> {
        private ProductIdentityFactory identityFactory;

        public MemProductIdentityDeserializer(ProductIdentityFactory identityFactory) {
            this.identityFactory = identityFactory;
        }

        @Override
        public ProductIdentity deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
                throws IOException {
            Map<String, String> m = new HashMap<String, String>();
            jsonParser.nextToken();
            for (int i = 0; i < 3; i++) {
                String key = jsonParser.getText();
                jsonParser.nextToken();
                String val = jsonParser.getText();

                m.put(key, val);
                if (jsonParser.nextToken() == JsonToken.END_OBJECT) {
                    break;
                }
            }
            String type = m.get("identityType");
            if (type == null)
                return null;
            try {
                return identityFactory.getIdentity(IdentityType.valueOf(type), m.get("value"));
            } catch (ContentException e) {
                throw new RuntimeException(e);
            }
        }
    }
}