diff --git a/wherehows-dao/src/main/java/wherehows/dao/DaoFactory.java b/wherehows-dao/src/main/java/wherehows/dao/DaoFactory.java index dc0d5bd082..3bc990faef 100644 --- a/wherehows-dao/src/main/java/wherehows/dao/DaoFactory.java +++ b/wherehows-dao/src/main/java/wherehows/dao/DaoFactory.java @@ -14,13 +14,19 @@ package wherehows.dao; import javax.persistence.EntityManagerFactory; -import wherehows.models.DictDataset; public class DaoFactory { + protected final EntityManagerFactory entityManagerFactory; + private static DatasetsDao datasetsDao; - private final EntityManagerFactory entityManagerFactory; + + private static MetadataReadOnlyDao metadataReadOnlyDao; + + public DaoFactory(EntityManagerFactory entityManagerFactory) { + this.entityManagerFactory = entityManagerFactory; + } public DatasetsDao getDatasetsDao() { if (datasetsDao == null) { @@ -29,8 +35,11 @@ public class DaoFactory { return datasetsDao; } - public DaoFactory(EntityManagerFactory entityManagerFactory) { - this.entityManagerFactory = entityManagerFactory; + public MetadataReadOnlyDao getMetadataReadOnlyDao() { + if (metadataReadOnlyDao == null) { + metadataReadOnlyDao = new MetadataReadOnlyDao(entityManagerFactory); + } + return metadataReadOnlyDao; } public DatasetClassificationDao getDatasetClassificationDao() { @@ -52,4 +61,4 @@ public class DaoFactory { public ClusterInfoDao getClusterInfoDao() { return new ClusterInfoDao(entityManagerFactory); } -} \ No newline at end of file +} diff --git a/wherehows-dao/src/main/java/wherehows/dao/DatasetsDao.java b/wherehows-dao/src/main/java/wherehows/dao/DatasetsDao.java index c40000a124..4cf7509558 100644 --- a/wherehows-dao/src/main/java/wherehows/dao/DatasetsDao.java +++ b/wherehows-dao/src/main/java/wherehows/dao/DatasetsDao.java @@ -30,7 +30,6 @@ import org.springframework.jdbc.core.BatchPreparedStatementSetter; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import wherehows.mapper.DatasetColumnRowMapper; -import wherehows.mapper.DatasetOwnerRowMapper; import wherehows.models.DatasetColumn; import wherehows.models.DatasetCompliance; 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 " + "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 = "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, " @@ -124,11 +116,6 @@ public class DatasetsDao { columnId); } - public List 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 owners) throws Exception { // first mark existing owners as deleted, new owners will be updated later diff --git a/wherehows-dao/src/main/java/wherehows/dao/MetadataReadOnlyDao.java b/wherehows-dao/src/main/java/wherehows/dao/MetadataReadOnlyDao.java new file mode 100644 index 0000000000..7e9c4ef094 --- /dev/null +++ b/wherehows-dao/src/main/java/wherehows/dao/MetadataReadOnlyDao.java @@ -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 params = new HashMap<>(); + params.put("id", datasetId); + + List 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 getDatasetOwnersByID(int datasetId) { + Map params = new HashMap<>(); + params.put("datasetId", datasetId); + + List 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 Generic return Data type + * @return List of records T + */ + @SneakyThrows + @SuppressWarnings("unchecked") + protected List getEntityListBy(String sqlQuery, Class classType, Map params) { + EntityManager entityManager = _emFactory.createEntityManager(); + Query query = entityManager.createNativeQuery(sqlQuery, classType); + for (Map.Entry param : params.entrySet()) { + query.setParameter(param.getKey(), param.getValue()); + } + + try { + return (List) 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 Generic return Data type + * @return a single record T + */ + @SneakyThrows + @SuppressWarnings("unchecked") + protected T getEntityBy(String sqlQuery, Class classType, Map params) { + EntityManager entityManager = _emFactory.createEntityManager(); + Query query = entityManager.createNativeQuery(sqlQuery, classType); + for (Map.Entry 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 getObjectArrayListBy(String sqlQuery, Map params) { + EntityManager entityManager = _emFactory.createEntityManager(); + Query query = entityManager.createNativeQuery(sqlQuery); + for (Map.Entry 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 getObjectListBy(String sqlQuery, Map params) { + EntityManager entityManager = _emFactory.createEntityManager(); + Query query = entityManager.createNativeQuery(sqlQuery); + for (Map.Entry param : params.entrySet()) { + query.setParameter(param.getKey(), param.getValue()); + } + + try { + return query.getResultList(); + } finally { + entityManager.close(); + } + } +} diff --git a/wherehows-dao/src/main/java/wherehows/mapper/DatasetOwnerRowMapper.java b/wherehows-dao/src/main/java/wherehows/mapper/DatasetOwnerRowMapper.java deleted file mode 100644 index df21b27648..0000000000 --- a/wherehows-dao/src/main/java/wherehows/mapper/DatasetOwnerRowMapper.java +++ /dev/null @@ -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 { - @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; - } -} diff --git a/wherehows-dao/src/main/java/wherehows/models/DatasetOwner.java b/wherehows-dao/src/main/java/wherehows/models/DatasetOwner.java index 27423cbe79..5175e762fc 100644 --- a/wherehows-dao/src/main/java/wherehows/models/DatasetOwner.java +++ b/wherehows-dao/src/main/java/wherehows/models/DatasetOwner.java @@ -18,8 +18,6 @@ import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.IdClass; -import javax.persistence.Table; -import javax.persistence.Transient; import lombok.Data; import lombok.NoArgsConstructor; @@ -28,7 +26,6 @@ import lombok.NoArgsConstructor; @NoArgsConstructor @Entity @IdClass(DatasetOwner.DatasetOwnerKey.class) -@Table(name = "dataset_owner") public class DatasetOwner { @Id @@ -42,10 +39,10 @@ public class DatasetOwner { @Column(name = "namespace") private String namespace; - @Transient + @Column(name = "display_name") private String name; - @Transient + @Column(name = "email") private String email; @Column(name = "is_group") diff --git a/wherehows-dao/src/main/java/wherehows/util/Urn.java b/wherehows-dao/src/main/java/wherehows/util/Urn.java index ba0f1089ac..537cdf71bd 100644 --- a/wherehows-dao/src/main/java/wherehows/util/Urn.java +++ b/wherehows-dao/src/main/java/wherehows/util/Urn.java @@ -98,9 +98,9 @@ public class Urn { public static boolean validateUrn(String urnString) { String[] splitResult = urnString.split(":///"); - if ((datasetTypes.contains(splitResult[0]) || splitResult[0].matches("\\w+")) && - splitResult.length > 1) + if ((datasetTypes.contains(splitResult[0]) || splitResult[0].matches("\\w+")) && splitResult.length > 1) { return true; + } return false; } } diff --git a/wherehows-frontend/app/controllers/api/v1/Dataset.java b/wherehows-frontend/app/controllers/api/v1/Dataset.java index dd79a402b9..af7a2acff6 100644 --- a/wherehows-frontend/app/controllers/api/v1/Dataset.java +++ b/wherehows-frontend/app/controllers/api/v1/Dataset.java @@ -36,6 +36,7 @@ import play.mvc.Controller; import play.mvc.Result; import wherehows.dao.DatasetClassificationDao; import wherehows.dao.DatasetsDao; +import wherehows.dao.MetadataReadOnlyDao; import wherehows.models.DatasetClassification; import wherehows.models.DatasetColumn; import wherehows.models.DatasetCompliance; @@ -55,6 +56,8 @@ public class Dataset extends Controller { private static final DatasetClassificationDao CLASSIFICATION_DAO = Application.DAO_FACTORY.getDatasetClassificationDao(); + private static final MetadataReadOnlyDao READONLY_DAO = Application.DAO_FACTORY.getMetadataReadOnlyDao(); + public static Result getDatasetOwnerTypes() { ObjectNode result = Json.newObject(); @@ -198,7 +201,7 @@ public class Dataset extends Controller { ObjectNode result = Json.newObject(); 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"); } catch (Exception e) { Logger.warn("Failed to get owners: " + e.toString());