com.univocity.app.data.Dao.java Source code

Java tutorial

Introduction

Here is the source code for com.univocity.app.data.Dao.java

Source

/*******************************************************************************
 * Copyright (c) 2014 uniVocity Software Pty Ltd. All rights reserved.
 * This file is subject to the terms and conditions defined in file
 * 'LICENSE.txt', which is part of this source code package.
 ******************************************************************************/
package com.univocity.app.data;

import java.sql.*;
import java.util.*;
import java.util.Map.Entry;

import org.slf4j.*;
import org.springframework.dao.*;
import org.springframework.jdbc.core.*;

import com.univocity.app.utils.*;

public class Dao {

    private static final Logger log = LoggerFactory.getLogger(Dao.class);

    private final Database database;
    private final String tableName;
    private Set<String> primaryKeys;

    public Dao(Database database, String tableName) {
        this.database = database;
        this.tableName = tableName;
    }

    private String escape(String s) {
        List<String> toEscape = Arrays.asList("max", "min");

        if (toEscape.contains(s.toLowerCase())) {
            return "\"" + s + "\"";
        }
        return s;
    }

    private void removeSuffix(StringBuilder script, String str) {
        if (script.toString().endsWith(str)) {
            script.delete(script.length() - str.length(), script.length());
        }
    }

    private String createDeleteScript(Set<Entry<String, Object>> matchingData) {
        final StringBuilder script = new StringBuilder("delete from ").append(tableName);

        script.append(createWhereClause(matchingData));

        return script.toString();
    }

    private String createWhereClause(Set<Entry<String, Object>> whereClauseEntries) {
        if (whereClauseEntries.isEmpty()) {
            return "";
        }

        final StringBuilder script = new StringBuilder(" where ");
        for (Entry<String, Object> e : whereClauseEntries) {
            script.append(escape(e.getKey()));
            script.append(" = ? and ");
        }

        removeSuffix(script, " and ");

        return script.toString();
    }

    private String createUpdateScript(Set<Entry<String, Object>> data, Set<Entry<String, Object>> matchingData) {
        final StringBuilder script = new StringBuilder("update ").append(tableName);

        if (!data.isEmpty()) {
            script.append(" set ");
            for (Entry<String, Object> e : data) {
                script.append(escape(e.getKey()));
                script.append(" = ?,");
            }
            removeSuffix(script, ",");
        }

        script.append(createWhereClause(matchingData));

        return script.toString();
    }

    private String createInsertScript(Set<Entry<String, Object>> newData) {
        final StringBuilder script = new StringBuilder("insert into ").append(tableName);

        if (newData.isEmpty()) {
            script.append("(null)");
        } else {
            script.append("(");
            for (Entry<String, Object> e : newData) {
                script.append(escape(e.getKey()));
                script.append(",");
            }
            removeSuffix(script, ",");

            script.append(") values (");

            for (@SuppressWarnings("unused")
            Entry<String, Object> e : newData) {
                script.append("?,");
            }
            removeSuffix(script, ",");

            script.append(")");
        }
        return script.toString();
    }

    private void execute(final Set<Entry<String, Object>> data, final Set<Entry<String, Object>> matchingEntries,
            final String script) {

        log.debug("Executing SQL: {}", script);

        database.getJdbcTemplate().execute(new ConnectionCallback<Void>() {
            @Override
            public Void doInConnection(Connection connection) throws SQLException, DataAccessException {
                PreparedStatement statement = connection.prepareStatement(script);
                try {
                    int idx = 1;
                    for (Entry<String, Object> e : data) {
                        log.debug("Parameter {}: {}", idx, e);
                        statement.setObject(idx++, e.getValue());
                    }

                    for (Entry<String, Object> e : matchingEntries) {
                        log.debug("Parameter {}: {}", idx, e);
                        statement.setObject(idx++, e.getValue());
                    }

                    statement.executeUpdate();
                } finally {
                    statement.close();
                }

                return null;
            }
        });
    }

    private Set<Entry<String, Object>> extractPrimaryKeyValues(Map<String, Object> rowData) {
        Map<String, Object> idsToMatch = new HashMap<String, Object>();
        for (String id : getPrimaryKeys()) {
            Object idValue = rowData.remove(id);
            idsToMatch.put(id, idValue);
        }
        return idsToMatch.entrySet();
    }

    public Set<String> getPrimaryKeys() {
        if (primaryKeys != null) {
            return primaryKeys;
        }

        primaryKeys = new HashSet<String>();
        database.getJdbcTemplate().execute(new ConnectionCallback<Void>() {
            @Override
            public Void doInConnection(Connection con) throws SQLException, DataAccessException {
                DatabaseMetaData metadata = con.getMetaData();
                //if the table name is in lower case it won't work (at least not with HSQLDB)
                ResultSet rs = metadata.getPrimaryKeys(null, null, tableName.toUpperCase());
                try {
                    while (rs.next()) {
                        primaryKeys.add(rs.getString("COLUMN_NAME"));
                    }
                } finally {
                    rs.close();
                }
                return null;
            }

        });

        return primaryKeys;
    }

    @SuppressWarnings("unchecked")
    public void insert(Map<String, Object> rowData) {
        final Set<Entry<String, Object>> entries = rowData.entrySet();
        final String insertScript = createInsertScript(entries);

        execute(entries, Collections.EMPTY_SET, insertScript);
    }

    @SuppressWarnings("unchecked")
    public void delete(Map<String, Object> rowData) {
        final Set<Entry<String, Object>> keys = extractPrimaryKeyValues(rowData);
        final String delete = createDeleteScript(keys);

        execute(Collections.EMPTY_SET, keys, delete);
    }

    public void update(Map<String, Object> rowData) {
        final Set<Entry<String, Object>> entries = rowData.entrySet();
        final Set<Entry<String, Object>> keys = extractPrimaryKeyValues(rowData);

        final String updateScript = createUpdateScript(entries, keys);

        execute(entries, keys, updateScript);
    }
}