Refactor DatasetOwner using readonly model (#702)

This commit is contained in:
Yi (Alan) Wang 2017-08-30 18:29:30 -07:00 committed by GitHub
parent 38a376243e
commit f861fdeaae
7 changed files with 212 additions and 69 deletions

View File

@ -14,13 +14,19 @@
package wherehows.dao; package wherehows.dao;
import javax.persistence.EntityManagerFactory; import javax.persistence.EntityManagerFactory;
import wherehows.models.DictDataset;
public class DaoFactory { public class DaoFactory {
protected final EntityManagerFactory entityManagerFactory;
private static DatasetsDao datasetsDao; private static DatasetsDao datasetsDao;
private final EntityManagerFactory entityManagerFactory;
private static MetadataReadOnlyDao metadataReadOnlyDao;
public DaoFactory(EntityManagerFactory entityManagerFactory) {
this.entityManagerFactory = entityManagerFactory;
}
public DatasetsDao getDatasetsDao() { public DatasetsDao getDatasetsDao() {
if (datasetsDao == null) { if (datasetsDao == null) {
@ -29,8 +35,11 @@ public class DaoFactory {
return datasetsDao; return datasetsDao;
} }
public DaoFactory(EntityManagerFactory entityManagerFactory) { public MetadataReadOnlyDao getMetadataReadOnlyDao() {
this.entityManagerFactory = entityManagerFactory; if (metadataReadOnlyDao == null) {
metadataReadOnlyDao = new MetadataReadOnlyDao(entityManagerFactory);
}
return metadataReadOnlyDao;
} }
public DatasetClassificationDao getDatasetClassificationDao() { public DatasetClassificationDao getDatasetClassificationDao() {

View File

@ -30,7 +30,6 @@ import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import wherehows.mapper.DatasetColumnRowMapper; import wherehows.mapper.DatasetColumnRowMapper;
import wherehows.mapper.DatasetOwnerRowMapper;
import wherehows.models.DatasetColumn; import wherehows.models.DatasetColumn;
import wherehows.models.DatasetCompliance; import wherehows.models.DatasetCompliance;
import wherehows.models.DatasetFieldEntity; import wherehows.models.DatasetFieldEntity;
@ -64,13 +63,6 @@ public class DatasetsDao {
+ "(ddfc.field_id = dfd.field_id AND ddfc.is_default = true) LEFT JOIN comments c ON " + "(ddfc.field_id = dfd.field_id AND ddfc.is_default = true) LEFT JOIN comments c ON "
+ "c.id = ddfc.comment_id WHERE dfd.dataset_id = ? AND dfd.field_id = ? ORDER BY dfd.sort_id"; + "c.id = ddfc.comment_id WHERE dfd.dataset_id = ? AND dfd.field_id = ? ORDER BY dfd.sort_id";
private final static String GET_DATASET_OWNERS_BY_ID =
"SELECT o.owner_id, u.display_name, o.sort_id, o.owner_type, o.namespace, o.owner_id_type, o.owner_source, "
+ "o.owner_sub_type, o.confirmed_by, u.email, u.is_active, is_group, o.modified_time "
+ "FROM dataset_owner o "
+ "LEFT JOIN dir_external_user_info u on (o.owner_id = u.user_id and u.app_id = 300) "
+ "WHERE o.dataset_id = ? and (o.is_deleted is null OR o.is_deleted != 'Y') ORDER BY o.sort_id";
private final static String UPDATE_DATASET_CONFIRMED_OWNERS = private final static String UPDATE_DATASET_CONFIRMED_OWNERS =
"INSERT INTO dataset_owner (dataset_id, owner_id, app_id, namespace, owner_type, is_group, is_active, " "INSERT INTO dataset_owner (dataset_id, owner_id, app_id, namespace, owner_type, is_group, is_active, "
+ "is_deleted, sort_id, created_time, modified_time, wh_etl_exec_id, dataset_urn, owner_sub_type, " + "is_deleted, sort_id, created_time, modified_time, wh_etl_exec_id, dataset_urn, owner_sub_type, "
@ -124,11 +116,6 @@ public class DatasetsDao {
columnId); columnId);
} }
public List<DatasetOwner> getDatasetOwnersByID(JdbcTemplate jdbcTemplate,
NamedParameterJdbcTemplate namedJdbcTemplate, int datasetId) {
return jdbcTemplate.query(GET_DATASET_OWNERS_BY_ID, new DatasetOwnerRowMapper(), datasetId);
}
public void updateDatasetOwners(JdbcTemplate jdbcTemplate, String user, int datasetId, List<DatasetOwner> owners) public void updateDatasetOwners(JdbcTemplate jdbcTemplate, String user, int datasetId, List<DatasetOwner> owners)
throws Exception { throws Exception {
// first mark existing owners as deleted, new owners will be updated later // first mark existing owners as deleted, new owners will be updated later

View File

@ -0,0 +1,190 @@
/**
* Copyright 2015 LinkedIn Corp. All rights reserved.
*
* 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.
*/
package wherehows.dao;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Query;
import lombok.SneakyThrows;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import wherehows.models.DatasetOwner;
/**
* Intended to be used for Front-end readonly functions
* Use native SQL and then map to entity
*/
public class MetadataReadOnlyDao {
private static final Logger log = LoggerFactory.getLogger(MetadataReadOnlyDao.class);
private final EntityManagerFactory _emFactory;
public MetadataReadOnlyDao(EntityManagerFactory factory) {
this._emFactory = factory;
}
private static final String GET_DATASET_URN_BY_ID = "SELECT urn FROM dict_dataset WHERE id = :id";
private final static String GET_DATASET_OWNERS_BY_ID =
"SELECT o.owner_id, u.display_name, o.sort_id, o.owner_type, o.namespace, o.owner_id_type, o.owner_source, "
+ "o.owner_sub_type, o.confirmed_by, u.email, u.is_active, is_group, o.modified_time "
+ "FROM dataset_owner o "
+ "LEFT JOIN dir_external_user_info u on (o.owner_id = u.user_id and u.app_id = 300) "
+ "WHERE o.dataset_id = :datasetId and (o.is_deleted is null OR o.is_deleted != 'Y') ORDER BY o.sort_id";
/**
* get dataset URN by dataset ID
* @param datasetId int
* @return URN String, if not found, return null
*/
public String getDatasetUrnById(int datasetId) {
Map<String, Object> params = new HashMap<>();
params.put("id", datasetId);
List<Object> result = getObjectListBy(GET_DATASET_URN_BY_ID, params);
if (result == null || result.size() == 0) {
log.error("Can not find URN for dataset id: " + datasetId + " : ");
return null;
}
return (String) result.get(0);
}
/**
* Get dataset owner list by dataset ID
* @param datasetId int
* @return List of DatasetOwner
*/
public List<DatasetOwner> getDatasetOwnersByID(int datasetId) {
Map<String, Object> params = new HashMap<>();
params.put("datasetId", datasetId);
List<DatasetOwner> owners = getEntityListBy(GET_DATASET_OWNERS_BY_ID, DatasetOwner.class, params);
for (DatasetOwner owner : owners) {
owner.setModifiedTime(owner.getModifiedTime() * 1000);
}
return owners;
}
/**
* get dataset URN by dataset ID and do simple validate
* @param datasetId int
* @return valid Wherehows URN
* @throws IllegalArgumentException when dataset URN not found or invalid
*/
public String validateUrn(int datasetId) throws IllegalArgumentException {
String urn = getDatasetUrnById(datasetId);
if (urn == null || urn.length() < 6 || urn.split(":///").length != 2) {
throw new IllegalArgumentException("Dataset id not found: " + datasetId);
}
return urn;
}
/**
* generic function to fetch a list of entities using native SQL with named parameters.
* @param sqlQuery SQL query string
* @param classType T.class the return class type
* @param params named parameters map
* @param <T> Generic return Data type
* @return List of records T
*/
@SneakyThrows
@SuppressWarnings("unchecked")
protected <T> List<T> getEntityListBy(String sqlQuery, Class classType, Map<String, Object> params) {
EntityManager entityManager = _emFactory.createEntityManager();
Query query = entityManager.createNativeQuery(sqlQuery, classType);
for (Map.Entry<String, Object> param : params.entrySet()) {
query.setParameter(param.getKey(), param.getValue());
}
try {
return (List<T>) query.getResultList();
} finally {
entityManager.close();
}
}
/**
* generic function to fetch a single entity using native SQL with named parameters.
* @param sqlQuery SQL query string
* @param classType T.class the return class type
* @param params named parameters map
* @param <T> Generic return Data type
* @return a single record T
*/
@SneakyThrows
@SuppressWarnings("unchecked")
protected <T> T getEntityBy(String sqlQuery, Class classType, Map<String, Object> params) {
EntityManager entityManager = _emFactory.createEntityManager();
Query query = entityManager.createNativeQuery(sqlQuery, classType);
for (Map.Entry<String, Object> param : params.entrySet()) {
query.setParameter(param.getKey(), param.getValue());
}
try {
return (T) query.getSingleResult();
} finally {
entityManager.close();
}
}
/**
* generic function to fetch records using native SQL with named parameters and return multiple column
* @param sqlQuery SQL query string
* @param params named parameters map
* @return List of Object[]
*/
@SneakyThrows
@SuppressWarnings("unchecked")
protected List<Object[]> getObjectArrayListBy(String sqlQuery, Map<String, Object> params) {
EntityManager entityManager = _emFactory.createEntityManager();
Query query = entityManager.createNativeQuery(sqlQuery);
for (Map.Entry<String, Object> param : params.entrySet()) {
query.setParameter(param.getKey(), param.getValue());
}
try {
return query.getResultList();
} finally {
entityManager.close();
}
}
/**
* generic function to fetch records using native SQL with named parameters and return single column
* @param sqlQuery SQL query string
* @param params named parameters map
* @return List of Object
*/
@SneakyThrows
@SuppressWarnings("unchecked")
protected List<Object> getObjectListBy(String sqlQuery, Map<String, Object> params) {
EntityManager entityManager = _emFactory.createEntityManager();
Query query = entityManager.createNativeQuery(sqlQuery);
for (Map.Entry<String, Object> param : params.entrySet()) {
query.setParameter(param.getKey(), param.getValue());
}
try {
return query.getResultList();
} finally {
entityManager.close();
}
}
}

View File

@ -1,43 +0,0 @@
/**
* Copyright 2015 LinkedIn Corp. All rights reserved.
*
* 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.
*/
package wherehows.mapper;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.jdbc.core.RowMapper;
import wherehows.models.DatasetOwner;
public class DatasetOwnerRowMapper implements RowMapper<DatasetOwner> {
@Override
public DatasetOwner mapRow(ResultSet rs, int rowNum) throws SQLException {
final DatasetOwner owner = new DatasetOwner();
owner.setUserName(rs.getString("owner_id"));
owner.setName(rs.getString("display_name"));
owner.setNamespace(rs.getString("namespace"));
owner.setEmail(rs.getString("email"));
owner.setType(rs.getString("owner_type"));
owner.setSubType(rs.getString("owner_sub_type"));
owner.setIdType(rs.getString("owner_id_type"));
owner.setSource(rs.getString("owner_source"));
owner.setIsGroup("Y".equalsIgnoreCase(rs.getString("is_group")));
owner.setIsActive("Y".equalsIgnoreCase(rs.getString("is_active")));
owner.setSortId(rs.getInt("sort_id"));
owner.setConfirmedBy(rs.getString("confirmed_by"));
owner.setModifiedTime(rs.getLong("modified_time") * 1000);
return owner;
}
}

View File

@ -18,8 +18,6 @@ import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.Id; import javax.persistence.Id;
import javax.persistence.IdClass; import javax.persistence.IdClass;
import javax.persistence.Table;
import javax.persistence.Transient;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
@ -28,7 +26,6 @@ import lombok.NoArgsConstructor;
@NoArgsConstructor @NoArgsConstructor
@Entity @Entity
@IdClass(DatasetOwner.DatasetOwnerKey.class) @IdClass(DatasetOwner.DatasetOwnerKey.class)
@Table(name = "dataset_owner")
public class DatasetOwner { public class DatasetOwner {
@Id @Id
@ -42,10 +39,10 @@ public class DatasetOwner {
@Column(name = "namespace") @Column(name = "namespace")
private String namespace; private String namespace;
@Transient @Column(name = "display_name")
private String name; private String name;
@Transient @Column(name = "email")
private String email; private String email;
@Column(name = "is_group") @Column(name = "is_group")

View File

@ -98,9 +98,9 @@ public class Urn {
public static boolean validateUrn(String urnString) { public static boolean validateUrn(String urnString) {
String[] splitResult = urnString.split(":///"); String[] splitResult = urnString.split(":///");
if ((datasetTypes.contains(splitResult[0]) || splitResult[0].matches("\\w+")) && if ((datasetTypes.contains(splitResult[0]) || splitResult[0].matches("\\w+")) && splitResult.length > 1) {
splitResult.length > 1)
return true; return true;
}
return false; return false;
} }
} }

View File

@ -36,6 +36,7 @@ import play.mvc.Controller;
import play.mvc.Result; import play.mvc.Result;
import wherehows.dao.DatasetClassificationDao; import wherehows.dao.DatasetClassificationDao;
import wherehows.dao.DatasetsDao; import wherehows.dao.DatasetsDao;
import wherehows.dao.MetadataReadOnlyDao;
import wherehows.models.DatasetClassification; import wherehows.models.DatasetClassification;
import wherehows.models.DatasetColumn; import wherehows.models.DatasetColumn;
import wherehows.models.DatasetCompliance; import wherehows.models.DatasetCompliance;
@ -55,6 +56,8 @@ public class Dataset extends Controller {
private static final DatasetClassificationDao CLASSIFICATION_DAO = private static final DatasetClassificationDao CLASSIFICATION_DAO =
Application.DAO_FACTORY.getDatasetClassificationDao(); Application.DAO_FACTORY.getDatasetClassificationDao();
private static final MetadataReadOnlyDao READONLY_DAO = Application.DAO_FACTORY.getMetadataReadOnlyDao();
public static Result getDatasetOwnerTypes() { public static Result getDatasetOwnerTypes() {
ObjectNode result = Json.newObject(); ObjectNode result = Json.newObject();
@ -198,7 +201,7 @@ public class Dataset extends Controller {
ObjectNode result = Json.newObject(); ObjectNode result = Json.newObject();
try { try {
result.set("owners", Json.toJson(DATASETS_DAO.getDatasetOwnersByID(JDBC_TEMPLATE, NAMED_JDBC_TEMPLATE, id))); result.set("owners", Json.toJson(READONLY_DAO.getDatasetOwnersByID(id)));
result.put("status", "ok"); result.put("status", "ok");
} catch (Exception e) { } catch (Exception e) {
Logger.warn("Failed to get owners: " + e.toString()); Logger.warn("Failed to get owners: " + e.toString());