me.ronghai.sa.dao.impl.AbstractModelDAOWithJDBCImpl.java Source code

Java tutorial

Introduction

Here is the source code for me.ronghai.sa.dao.impl.AbstractModelDAOWithJDBCImpl.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package me.ronghai.sa.dao.impl;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;

import me.ronghai.sa.dao.AbstractModelDAO;
import me.ronghai.sa.dao.DAODelegate;
import me.ronghai.sa.model.AbstractModel;
import me.ronghai.sa.model.ModelMeta;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;

import com.ecbeta.common.core.db.DatabaseHandler;
import com.ecbeta.common.core.reflect.ReflectUtils;

/**
 *
 * @author L5M
 * @param <E>
 */
public class AbstractModelDAOWithJDBCImpl<E extends AbstractModel> implements AbstractModelDAO<E>, Serializable {

    private static final long serialVersionUID = 1L;

    @Autowired
    public DatabaseHandler databaseHandler;

    protected transient DAODelegate<E> delegate;

    public DAODelegate<E> getDelegate() {
        return delegate;
    }

    @Override
    public void setDelegate(DAODelegate<E> delegate) {
        this.delegate = delegate;
        if (this.delegate != null) {
            this.delegate.setDao(this);
        }
    }

    protected Class<E> entityClass;
    private static final Logger logger = Logger.getLogger(AbstractModelDAOWithJDBCImpl.class.getName());

    @SuppressWarnings("unchecked")
    public AbstractModelDAOWithJDBCImpl() {
        ParameterizedType type = (ParameterizedType) getClass().getGenericSuperclass();
        this.entityClass = (Class<E>) type.getActualTypeArguments()[0];
    }

    private List<?>[] findColumnsAndValues(boolean excludeId, E entity) {

        List<String> columnNames = new ArrayList<>();
        List<Object> values = new ArrayList<>();

        Map<String, Field> columnFields = entity.modelMeta().getColumnFields();
        Map<String, Method> field2Getter = entity.modelMeta().getField2Getter();

        for (Map.Entry<String, Field> entry : columnFields.entrySet()) {
            Field field = entry.getValue();
            if (excludeId && field.isAnnotationPresent(Id.class)) {
                continue;
            }
            String cname = entry.getKey();
            Object value = null;
            try {
                value = field2Getter.get(field.getName()).invoke(entity);
            } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException
                    | NullPointerException e) {
                logger.log(Level.WARNING, "filed is {0}  ", field);
                logger.log(Level.WARNING, "{0}", e);
            }
            Column annotation = field.isAnnotationPresent(Column.class) ? (Column) field.getAnnotation(Column.class)
                    : null;
            if (annotation != null && value == null && !annotation.nullable()) {
                logger.log(Level.SEVERE, "{0}", cname + " is not null. ");
                return null;
            } else if (value != null) {
                columnNames.add(cname);
                values.add(value);
            }
        }

        /*
            
         List<Field> allFieldList =  ReflectUtils.getDeclaredFields((List<Field>)null, entityClass, false);
         Map<String, PropertyDescriptor> fieldName2PropertyDescriptor =  ReflectUtils.findFieldName2PropertyDescriptor(entityClass);    
            
         for ( Field field : allFieldList) {
         if (field.isAnnotationPresent(Column.class) && !field.isAnnotationPresent(Id.class)) {
         Column annotation = field.isAnnotationPresent(Column.class) ?  (Column) field.getAnnotation(Column.class) : null;
         String cname;
         if(annotation  != null && org.apache.commons.lang.StringUtils.isNotEmpty(annotation.name())){
         cname = annotation.name();
         cname = cname.replaceAll("[\\[\\]]", "`");
         }else{
         cname = field.getName();
         }
         Method getter = ReflectUtils.findGetter(entity, field, fieldName2PropertyDescriptor, null);
         try {
         Object value =  getter.invoke(entity);
         if(value == null && annotation != null && !annotation.nullable()){
         logger.log(Level.SEVERE, "{0}",  cname + " is not null. ");
         return null;
         }else if(value != null){
         columnNames.add(cname);
         values.add(value);
         }
         }catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { 
         if(annotation != null && !annotation.nullable()){
         logger.log(Level.SEVERE, "{0}", ex);
         return null;
         }else{
         logger.log(Level.WARNING, "{0}", ex);
         }
         }
         }
         }
         */
        return new List[] { columnNames, values };
    }

    @Override
    public E persistent(E entity) {
        if (delegate != null) {
            delegate.beforePersistent(entity);
        }
        List<?>[] columnsAndValues = findColumnsAndValues(true, entity);
        @SuppressWarnings("unchecked")
        List<String> columnNames = columnsAndValues == null ? null : (List<String>) columnsAndValues[0];
        @SuppressWarnings("unchecked")
        List<Object> values = columnsAndValues == null ? null : (List<Object>) columnsAndValues[1];

        logger.log(Level.INFO, "values\n{0}", values);

        if (columnNames != null && !columnNames.isEmpty()) {
            String[] ph = new String[columnNames.size()];
            Arrays.fill(ph, "?");
            final String sql = " INSERT INTO " + table(entityClass) + "( "
                    + org.apache.commons.lang.StringUtils.join(columnNames, " , ") + " ) VALUES ( "
                    + org.apache.commons.lang.StringUtils.join(ph, " , ") + ")";
            this.databaseHandler.update(sql, values.toArray());

            E ne = this.find(" ORDER BY ID DESC LIMIT 1 ").get(0);
            entity.setId(ne.getId());
            return ne;
        }
        if (delegate != null) {
            delegate.afterPersistent(entity);
        }
        return entity;

    }

    @Override
    public void remove(E entity, boolean force) {
        if (delegate != null) {
            delegate.beforeRemove(entity);
        }
        if (force) {
            remove(entity);
        } else {
            entity.setDisabled(true);
            merge(entity);
        }
        if (delegate != null) {
            delegate.afterRemove(entity);
        }
    }

    @Override
    public void remove(E entity) {
        this.remove(true, Arrays.asList(entity.getId()));
    }

    @Override
    public int remove(boolean force, Collection<Long> ids) {
        int n = this.remove(force, ids, "");
        return n;
    }

    public void beforeRemove(boolean force, Collection<Long> ids, String configure) {

    }

    public void afterRemove(boolean force, Collection<Long> ids, String configure) {

    }

    @Override
    public int remove(boolean force, Collection<Long> ids, String configure) {
        if (ids == null || ids.isEmpty()) {
            return 0;
        }
        this.beforeRemove(force, ids, configure);
        String sql;
        String table = table(entityClass);
        if (force) {
            sql = "DELETE FROM " + table + "  e  WHERE id IN (:ids) ";
        } else {
            sql = "UPDATE " + table + "  SET disabled = 1  WHERE id IN (:ids) ";
        }
        if (StringUtils.isNotEmpty(configure)) {
            if (!configure.trim().toUpperCase().startsWith("AND")) {
                sql += " AND  ";
            }
            sql += configure;
        }
        logger.info("remove ids " + ids);
        MapSqlParameterSource parameters = new MapSqlParameterSource();
        parameters.addValue("ids", new ArrayList<>(ids));
        int n = this.databaseHandler.update(sql, parameters);

        this.afterRemove(force, ids, configure);
        return n;

    }

    @Override
    public E update(E entity) {
        return merge(entity);
    }

    @Override
    public E merge(E entity) {
        if (delegate != null) {
            delegate.beforeUpdate(entity);
        }
        List<?>[] columnsAndValues = findColumnsAndValues(true, entity);
        @SuppressWarnings("unchecked")
        List<String> columnNames = columnsAndValues == null ? null : (List<String>) columnsAndValues[0];
        @SuppressWarnings("unchecked")
        List<Object> values = columnsAndValues == null ? null : (List<Object>) columnsAndValues[1];
        if (columnNames != null && !columnNames.isEmpty()) {
            String sql = " UPDATE " + table(entityClass) + " SET ";
            for (int i = 0; i < columnNames.size(); i++) {
                sql += "  " + columnNames.get(i) + " = ? ";
                if (i != columnNames.size() - 1) {
                    sql += ", ";
                }
            }
            logger.log(Level.INFO, "{0}", values);
            logger.log(Level.INFO, "{0}", columnNames);
            sql += " WHERE ID =  " + entity.getId();
            this.databaseHandler.update(sql, values.toArray());

            return find(entity.getId());
        }
        if (delegate != null) {
            delegate.afterUpdate(entity);
        }
        return entity;
    }

    @SuppressWarnings("unchecked")
    @Override
    public RowMapper<E> createRowMapper() {
        Method m = ReflectUtils.findMethod(entityClass, "_getModelMeta", null);
        ModelMeta<E> me;
        try {
            me = (ModelMeta<E>) m.invoke(null);
            return me.getRowMapper();
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
            logger.log(Level.SEVERE, null, ex);
        }
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public E find(Object id) {
        String sql = "SELECT * FROM " + table(entityClass) + " WHERE id = ? ";
        E e = this.databaseHandler.queryForObject(sql, new Object[] { id }, createRowMapper());
        if (delegate != null) {
            e = delegate.afterFind(e);
        }
        return e;
    }

    @Override
    public boolean exsit(Object id) {

        String sql = "SELECT count(*) FROM " + table(entityClass) + " WHERE id = ? ";
        return this.databaseHandler.queryForInt(sql, new Object[] { id }) != 0;

    }

    @Override
    public E find(Object id, String configure) {
        String sql = "SELECT * FROM " + table(entityClass) + " WHERE id = ? ";
        if (org.apache.commons.lang.StringUtils.isNotEmpty(configure)) {
            sql += " " + configure.replaceAll("'", "''");
        }
        E entity = this.databaseHandler.queryForObject(sql, new Object[] { id }, createRowMapper());
        if (delegate != null) {
            return delegate.afterFind(entity);
        }
        return entity;
    }

    @Override
    public boolean exsit(Object id, String configure) {
        String sql = "SELECT count(*) FROM " + table(entityClass) + " WHERE id = ? ";
        if (org.apache.commons.lang.StringUtils.isNotEmpty(configure)) {
            sql += " " + configure.replaceAll("'", "''");
        }
        return this.databaseHandler.queryForInt(sql, new Object[] { id }) != 0;

    }

    @Override
    public List<E> find() {
        String sql = "SELECT * FROM " + table(entityClass);
        List<E> entity = this.databaseHandler.query(sql, createRowMapper());
        if (delegate != null) {
            return delegate.afterFind(entity);
        }
        return entity;
    }

    @Override
    public List<E> find(String configure) {
        return find(-1, 0, configure);
    }

    @Override
    public List<E> find(int from, int size, String configure) {
        String sql = "SELECT * FROM " + table(entityClass);
        if (org.apache.commons.lang.StringUtils.isNotEmpty(configure)) {
            sql += " " + configure;
        }
        String part = from < 0 ? "" : " ROW_NUMBER >= " + from + " AND ROW_NUMBER <= " + (from + size);
        if (org.apache.commons.lang.StringUtils.isNotEmpty(part)) {
            if (sql.toUpperCase().contains("WHERE")) {
                sql += " AND " + part;
            } else {

                sql += " WHERE " + part;
            }
        }
        logger.log(Level.INFO, "{0}", sql);
        List<E> entity = this.databaseHandler.query(sql, createRowMapper());
        if (delegate != null) {
            return delegate.afterFind(entity);
        }
        return entity;

    }

    public static String table(Class<?> entityClass) {
        String table = entityClass.getSimpleName();
        if (entityClass.isAnnotationPresent(Entity.class)) {
            String t = ((Entity) entityClass.getAnnotation(Entity.class)).name();
            if (org.apache.commons.lang.StringUtils.isNotEmpty(t)) {
                table = t;
            }
        }
        return table;
    }

    public static String column(Class<?> entityClass) {
        return "";
    }

    @Override
    public long count(String configure) {
        String sql = " SELECT COUNT (*)  FROM " + table(entityClass);
        if (org.apache.commons.lang.StringUtils.isNotEmpty(configure)) {
            sql += " " + configure;
        }
        try {
            Collection<Object> values = this.databaseHandler.execute(sql).get(0).values();
            for (Object o : values) {
                return Long.parseLong(o.toString());
            }
        } catch (SQLException | ClassNotFoundException ex) {
            logger.log(Level.SEVERE, "{0}", ex);
        }
        return 0;

    }

    @Override
    public List<Map<String, Object>> execute(String sql) {
        try {
            return this.databaseHandler.execute(sql);
        } catch (SQLException | ClassNotFoundException ex) {
            logger.log(Level.SEVERE, "{0}", ex);
        }
        return null;
    }

    @Override
    public int update(String sql) {
        try {
            return this.databaseHandler.update(sql);
        } catch (SQLException | ClassNotFoundException ex) {
            logger.log(Level.SEVERE, null, ex);
        }
        return 0;
    }

    @Override
    public List<E> find(List<Object> ids) {
        if (ids == null || ids.isEmpty())
            return null;
        String sql = "SELECT * FROM " + table(entityClass) + " WHERE id IN (:ids) ";
        MapSqlParameterSource parameters = new MapSqlParameterSource();
        parameters.addValue("ids", ids);
        List<E> entity = this.databaseHandler.query(sql, parameters, createRowMapper());
        if (delegate != null) {
            return delegate.afterFind(entity);
        }
        return entity;
    }

    public List<Object> findRelatedIDs(final String relationTable, final String returnColumn,
            final String whereColumn, final Long productId) {
        String sql = " SELECT " + returnColumn + " FROM `" + relationTable + "`  WHERE " + whereColumn + " = ? ";
        List<Object> ids = this.databaseHandler.query(sql, new Object[] { productId }, new RowMapper<Object>() {
            @Override
            public Object mapRow(ResultSet arg0, int arg1) throws SQLException {
                return arg0.getLong(returnColumn);
            }
        });

        return ids;
    }

    /* 
     pSqlParameterSource parameters = new MapSqlParameterSource();
     parameters.addValue("ids", ids);
        
     List<Foo> foo = getJdbcTemplate().query("SELECT * FROM foo WHERE a IN (:ids)",
     getRowMapper(), parameters);*/
}