Commit 4351c30adfa2784329171c61af4b0c787b77fe3a

Authored by Volodymyr Babak
1 parent 44c28b5b

Added attribute jpa dao

... ... @@ -36,5 +36,5 @@ public interface AttributesDao {
36 36
37 37 ListenableFuture<Void> save(EntityId entityId, String attributeType, AttributeKvEntry attribute);
38 38
39   - ListenableFuture<List<Void>> removeAll(EntityId entityId, String scope, List<String> keys);
  39 + ListenableFuture<List<Void>> removeAll(EntityId entityId, String attributeType, List<String> keys);
40 40 }
... ...
dao/src/main/java/org/thingsboard/server/dao/model/sql/AttributeKvCompositeKey.java renamed from dao/src/main/java/org/thingsboard/server/dao/model/sql/AttributesKvCompositeKey.java
... ... @@ -15,13 +15,17 @@
15 15 */
16 16 package org.thingsboard.server.dao.model.sql;
17 17
  18 +import lombok.AllArgsConstructor;
18 19 import lombok.Data;
  20 +import lombok.NoArgsConstructor;
19 21
20 22 import java.io.Serializable;
21 23 import java.util.UUID;
22 24
23 25 @Data
24   -public class AttributesKvCompositeKey implements Serializable {
  26 +@AllArgsConstructor
  27 +@NoArgsConstructor
  28 +public class AttributeKvCompositeKey implements Serializable {
25 29 private String entityType;
26 30 private UUID entityId;
27 31 private String attributeType;
... ...
... ... @@ -16,21 +16,20 @@
16 16 package org.thingsboard.server.dao.model.sql;
17 17
18 18 import lombok.Data;
19   -import org.thingsboard.server.common.data.kv.AttributeKvEntry;
  19 +import org.thingsboard.server.common.data.kv.*;
20 20 import org.thingsboard.server.dao.model.ToData;
21 21
22   -import javax.persistence.Column;
23   -import javax.persistence.Entity;
24   -import javax.persistence.Id;
25   -import javax.persistence.Table;
  22 +import javax.persistence.*;
  23 +import java.io.Serializable;
26 24 import java.util.UUID;
27 25
28 26 import static org.thingsboard.server.dao.model.ModelConstants.*;
29 27
30 28 @Data
31 29 @Entity
32   -@Table(name = "attributes_kv")
33   -public class AttributeKvEntity implements ToData<AttributeKvEntry> {
  30 +@Table(name = "attribute_kv")
  31 +@IdClass(AttributeKvCompositeKey.class)
  32 +public class AttributeKvEntity implements ToData<AttributeKvEntry>, Serializable {
34 33
35 34 @Id
36 35 @Column(name = ENTITY_TYPE_COLUMN)
... ... @@ -65,7 +64,16 @@ public class AttributeKvEntity implements ToData<AttributeKvEntry> {
65 64
66 65 @Override
67 66 public AttributeKvEntry toData() {
68   - // TODO - add implementation
69   - return null;
  67 + KvEntry kvEntry = null;
  68 + if (strValue != null) {
  69 + kvEntry = new StringDataEntry(attributeKey, strValue);
  70 + } else if (booleanValue != null) {
  71 + kvEntry = new BooleanDataEntry(attributeKey, booleanValue);
  72 + } else if (doubleValue != null) {
  73 + kvEntry = new DoubleDataEntry(attributeKey, doubleValue);
  74 + } else if (longValue != null) {
  75 + kvEntry = new LongDataEntry(attributeKey, longValue);
  76 + }
  77 + return new BaseAttributeKvEntry(kvEntry, lastUpdateTs);
70 78 }
71 79 }
... ...
... ... @@ -38,7 +38,9 @@ import static org.springframework.transaction.annotation.Propagation.REQUIRES_NE
38 38 * @author Valerii Sosliuk
39 39 */
40 40 @Slf4j
41   -public abstract class JpaAbstractDao<E extends BaseEntity<D>, D> implements Dao<D> {
  41 +public abstract class JpaAbstractDao<E extends BaseEntity<D>, D>
  42 + extends JpaAbstractDaoListeningExecutorService
  43 + implements Dao<D> {
42 44
43 45 protected abstract Class<E> getEntityClass();
44 46
... ... @@ -48,8 +50,6 @@ public abstract class JpaAbstractDao<E extends BaseEntity<D>, D> implements Dao<
48 50 return false;
49 51 }
50 52
51   - protected ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
52   -
53 53 @Override
54 54 @Transactional(propagation = REQUIRES_NEW)
55 55 public D save(D domain) {
... ...
  1 +/**
  2 + * Copyright © 2016-2017 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.sql;
  17 +
  18 +import com.google.common.util.concurrent.ListeningExecutorService;
  19 +import com.google.common.util.concurrent.MoreExecutors;
  20 +
  21 +import java.util.concurrent.Executors;
  22 +
  23 +public abstract class JpaAbstractDaoListeningExecutorService {
  24 + protected ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
  25 +}
... ...
... ... @@ -17,9 +17,17 @@ package org.thingsboard.server.dao.sql.attributes;
17 17
18 18 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
19 19 import org.springframework.data.repository.CrudRepository;
  20 +import org.thingsboard.server.dao.model.sql.AttributeKvCompositeKey;
20 21 import org.thingsboard.server.dao.model.sql.AttributeKvEntity;
21   -import org.thingsboard.server.dao.model.sql.AttributesKvCompositeKey;
  22 +
  23 +import java.util.List;
  24 +import java.util.UUID;
22 25
23 26 @ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true")
24   -public interface AttributeKvRepository extends CrudRepository<AttributeKvEntity, AttributesKvCompositeKey> {
  27 +public interface AttributeKvRepository extends CrudRepository<AttributeKvEntity, AttributeKvCompositeKey> {
  28 +
  29 + List<AttributeKvEntity> findAllByEntityTypeAndEntityIdAndAttributeType(String entityType,
  30 + UUID entityId,
  31 + String attributeType);
25 32 }
  33 +
... ...
... ... @@ -15,6 +15,7 @@
15 15 */
16 16 package org.thingsboard.server.dao.sql.attributes;
17 17
  18 +import com.google.common.collect.Lists;
18 19 import com.google.common.util.concurrent.ListenableFuture;
19 20 import lombok.extern.slf4j.Slf4j;
20 21 import org.springframework.beans.factory.annotation.Autowired;
... ... @@ -22,42 +23,97 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
22 23 import org.springframework.stereotype.Component;
23 24 import org.thingsboard.server.common.data.id.EntityId;
24 25 import org.thingsboard.server.common.data.kv.AttributeKvEntry;
  26 +import org.thingsboard.server.dao.DaoUtil;
25 27 import org.thingsboard.server.dao.attributes.AttributesDao;
  28 +import org.thingsboard.server.dao.model.sql.AttributeKvCompositeKey;
  29 +import org.thingsboard.server.dao.model.sql.AttributeKvEntity;
  30 +import org.thingsboard.server.dao.sql.JpaAbstractDaoListeningExecutorService;
26 31
27 32 import java.util.Collection;
28 33 import java.util.List;
29 34 import java.util.Optional;
  35 +import java.util.stream.Collectors;
30 36
31 37 @Component
32 38 @Slf4j
33 39 @ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true")
34   -public class JpaAttributeDao implements AttributesDao {
  40 +public class JpaAttributeDao extends JpaAbstractDaoListeningExecutorService implements AttributesDao {
35 41
36 42 @Autowired
37 43 private AttributeKvRepository attributeKvRepository;
38 44
39 45 @Override
40 46 public ListenableFuture<Optional<AttributeKvEntry>> find(EntityId entityId, String attributeType, String attributeKey) {
41   - return null;
  47 + AttributeKvCompositeKey compositeKey =
  48 + new AttributeKvCompositeKey(
  49 + entityId.getEntityType().name(),
  50 + entityId.getId(),
  51 + attributeType,
  52 + attributeKey);
  53 + return service.submit(() ->
  54 + Optional.of(DaoUtil.getData(attributeKvRepository.findOne(compositeKey))));
42 55 }
43 56
44 57 @Override
45   - public ListenableFuture<List<AttributeKvEntry>> find(EntityId entityId, String attributeType, Collection<String> attributeKey) {
46   - return null;
  58 + public ListenableFuture<List<AttributeKvEntry>> find(EntityId entityId, String attributeType, Collection<String> attributeKeys) {
  59 + List<AttributeKvCompositeKey> compositeKeys =
  60 + attributeKeys
  61 + .stream()
  62 + .map(attributeKey ->
  63 + new AttributeKvCompositeKey(
  64 + entityId.getEntityType().name(),
  65 + entityId.getId(),
  66 + attributeType,
  67 + attributeKey))
  68 + .collect(Collectors.toList());
  69 + return service.submit(() ->
  70 + DaoUtil.convertDataList(Lists.newArrayList(attributeKvRepository.findAll(compositeKeys))));
47 71 }
48 72
49 73 @Override
50 74 public ListenableFuture<List<AttributeKvEntry>> findAll(EntityId entityId, String attributeType) {
51   - return null;
  75 + return service.submit(() ->
  76 + DaoUtil.convertDataList(Lists.newArrayList(
  77 + attributeKvRepository.findAllByEntityTypeAndEntityIdAndAttributeType(
  78 + entityId.getEntityType().name(),
  79 + entityId.getId(),
  80 + attributeType))));
52 81 }
53 82
54 83 @Override
55 84 public ListenableFuture<Void> save(EntityId entityId, String attributeType, AttributeKvEntry attribute) {
56   - return null;
  85 + AttributeKvEntity entity = new AttributeKvEntity();
  86 + entity.setEntityType(entityId.getEntityType().name());
  87 + entity.setEntityId(entityId.getId());
  88 + entity.setAttributeType(attributeType);
  89 + entity.setAttributeKey(attribute.getKey());
  90 + entity.setLastUpdateTs(attribute.getLastUpdateTs());
  91 + entity.setStrValue(attribute.getStrValue().orElse(null));
  92 + entity.setDoubleValue(attribute.getDoubleValue().orElse(null));
  93 + entity.setLongValue(attribute.getLongValue().orElse(null));
  94 + entity.setBooleanValue(attribute.getBooleanValue().orElse(null));
  95 + return service.submit(() -> {
  96 + attributeKvRepository.save(entity);
  97 + return null;
  98 + });
57 99 }
58 100
59 101 @Override
60   - public ListenableFuture<List<Void>> removeAll(EntityId entityId, String scope, List<String> keys) {
61   - return null;
  102 + public ListenableFuture<List<Void>> removeAll(EntityId entityId, String attributeType, List<String> keys) {
  103 + List<AttributeKvEntity> entitiesToDelete = keys
  104 + .stream()
  105 + .map(key -> {
  106 + AttributeKvEntity entityToDelete = new AttributeKvEntity();
  107 + entityToDelete.setEntityType(entityId.getEntityType().name());
  108 + entityToDelete.setEntityId(entityId.getId());
  109 + entityToDelete.setAttributeType(attributeType);
  110 + entityToDelete.setAttributeKey(key);
  111 + return entityToDelete;
  112 + }).collect(Collectors.toList());
  113 +
  114 + return service.submit(() -> {
  115 + attributeKvRepository.delete(entitiesToDelete);
  116 + return null;
  117 + });
62 118 }
63 119 }
... ...
... ... @@ -16,8 +16,6 @@
16 16 package org.thingsboard.server.dao.sql.relation;
17 17
18 18 import com.google.common.util.concurrent.ListenableFuture;
19   -import com.google.common.util.concurrent.ListeningExecutorService;
20   -import com.google.common.util.concurrent.MoreExecutors;
21 19 import lombok.extern.slf4j.Slf4j;
22 20 import org.springframework.beans.factory.annotation.Autowired;
23 21 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
... ... @@ -36,6 +34,7 @@ import org.thingsboard.server.dao.DaoUtil;
36 34 import org.thingsboard.server.dao.model.sql.RelationCompositeKey;
37 35 import org.thingsboard.server.dao.model.sql.RelationEntity;
38 36 import org.thingsboard.server.dao.relation.RelationDao;
  37 +import org.thingsboard.server.dao.sql.JpaAbstractDaoListeningExecutorService;
39 38 import org.thingsboard.server.dao.sql.JpaAbstractSearchTimeDao;
40 39
41 40 import javax.persistence.criteria.CriteriaBuilder;
... ... @@ -44,7 +43,6 @@ import javax.persistence.criteria.Predicate;
44 43 import javax.persistence.criteria.Root;
45 44 import java.util.ArrayList;
46 45 import java.util.List;
47   -import java.util.concurrent.Executors;
48 46
49 47 import static org.springframework.data.domain.Sort.Direction.ASC;
50 48 import static org.springframework.data.jpa.domain.Specifications.where;
... ... @@ -56,16 +54,14 @@ import static org.thingsboard.server.dao.model.ModelConstants.*;
56 54 @Slf4j
57 55 @Component
58 56 @ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false)
59   -public class JpaRelationDao implements RelationDao {
  57 +public class JpaRelationDao extends JpaAbstractDaoListeningExecutorService implements RelationDao {
60 58
61 59 @Autowired
62 60 private RelationRepository relationRepository;
63 61
64   - private ListeningExecutorService executorService = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
65   -
66 62 @Override
67 63 public ListenableFuture<List<EntityRelation>> findAllByFrom(EntityId from, RelationTypeGroup typeGroup) {
68   - return executorService.submit(() -> DaoUtil.convertDataList(
  64 + return service.submit(() -> DaoUtil.convertDataList(
69 65 relationRepository.findAllByFromIdAndFromTypeAndRelationTypeGroup(
70 66 from.getId(),
71 67 from.getEntityType().name(),
... ... @@ -74,7 +70,7 @@ public class JpaRelationDao implements RelationDao {
74 70
75 71 @Override
76 72 public ListenableFuture<List<EntityRelation>> findAllByFromAndType(EntityId from, String relationType, RelationTypeGroup typeGroup) {
77   - return executorService.submit(() -> DaoUtil.convertDataList(
  73 + return service.submit(() -> DaoUtil.convertDataList(
78 74 relationRepository.findAllByFromIdAndFromTypeAndRelationTypeAndRelationTypeGroup(
79 75 from.getId(),
80 76 from.getEntityType().name(),
... ... @@ -84,7 +80,7 @@ public class JpaRelationDao implements RelationDao {
84 80
85 81 @Override
86 82 public ListenableFuture<List<EntityRelation>> findAllByTo(EntityId to, RelationTypeGroup typeGroup) {
87   - return executorService.submit(() -> DaoUtil.convertDataList(
  83 + return service.submit(() -> DaoUtil.convertDataList(
88 84 relationRepository.findAllByToIdAndToTypeAndRelationTypeGroup(
89 85 to.getId(),
90 86 to.getEntityType().name(),
... ... @@ -93,7 +89,7 @@ public class JpaRelationDao implements RelationDao {
93 89
94 90 @Override
95 91 public ListenableFuture<List<EntityRelation>> findAllByToAndType(EntityId to, String relationType, RelationTypeGroup typeGroup) {
96   - return executorService.submit(() -> DaoUtil.convertDataList(
  92 + return service.submit(() -> DaoUtil.convertDataList(
97 93 relationRepository.findAllByToIdAndToTypeAndRelationTypeAndRelationTypeGroup(
98 94 to.getId(),
99 95 to.getEntityType().name(),
... ... @@ -110,18 +106,18 @@ public class JpaRelationDao implements RelationDao {
110 106 to.getEntityType().name(),
111 107 relationType,
112 108 typeGroup.name());
113   - return executorService.submit(() -> relationRepository.findOne(key) != null);
  109 + return service.submit(() -> relationRepository.findOne(key) != null);
114 110 }
115 111
116 112 @Override
117 113 public ListenableFuture<Boolean> saveRelation(EntityRelation relation) {
118   - return executorService.submit(() -> relationRepository.save(new RelationEntity(relation)) != null);
  114 + return service.submit(() -> relationRepository.save(new RelationEntity(relation)) != null);
119 115 }
120 116
121 117 @Override
122 118 public ListenableFuture<Boolean> deleteRelation(EntityRelation relation) {
123 119 RelationCompositeKey key = new RelationCompositeKey(relation);
124   - return executorService.submit(
  120 + return service.submit(
125 121 () -> {
126 122 boolean relationExistsBeforeDelete = relationRepository.exists(key);
127 123 relationRepository.delete(key);
... ... @@ -138,7 +134,7 @@ public class JpaRelationDao implements RelationDao {
138 134 to.getEntityType().name(),
139 135 relationType,
140 136 typeGroup.name());
141   - return executorService.submit(
  137 + return service.submit(
142 138 () -> {
143 139 boolean relationExistsBeforeDelete = relationRepository.exists(key);
144 140 relationRepository.delete(key);
... ... @@ -152,7 +148,7 @@ public class JpaRelationDao implements RelationDao {
152 148 relationEntity.setFromId(entity.getId());
153 149 relationEntity.setFromType(entity.getEntityType().name());
154 150
155   - return executorService.submit(
  151 + return service.submit(
156 152 () -> {
157 153 boolean relationExistsBeforeDelete = relationRepository
158 154 .findAllByFromIdAndFromType(relationEntity.getFromId(), relationEntity.getFromType())
... ... @@ -172,7 +168,7 @@ public class JpaRelationDao implements RelationDao {
172 168 new Order(ASC, RELATION_TYPE_PROPERTY),
173 169 new Order(ASC, RELATION_TO_TYPE_PROPERTY))
174 170 );
175   - return executorService.submit(() ->
  171 + return service.submit(() ->
176 172 DaoUtil.convertDataList(relationRepository.findAll(where(timeSearchSpec).and(fieldsSpec), pageable).getContent()));
177 173 }
178 174
... ...
... ... @@ -23,7 +23,7 @@ import java.util.Properties;
23 23 /**
24 24 * Created by Valerii Sosliuk on 5/12/2017.
25 25 */
26   -public class JsonBinaryType extends AbstractSingleColumnStandardBasicType<Object>
  26 +public class JsonBinaryType extends AbstractSingleColumnStandardBasicType<Object>
27 27 implements DynamicParameterizedType {
28 28
29 29 public JsonBinaryType() {
... ...
... ... @@ -74,7 +74,7 @@ CREATE TABLE IF NOT EXISTS asset (
74 74 );
75 75 ALTER TABLE asset OWNER TO postgres;
76 76
77   -CREATE TABLE IF NOT EXISTS attributes_kv (
  77 +CREATE TABLE IF NOT EXISTS attribute_kv (
78 78 entity_type character varying(255),
79 79 entity_id uuid,
80 80 attribute_type character varying(255),
... ... @@ -84,7 +84,7 @@ CREATE TABLE IF NOT EXISTS attributes_kv (
84 84 long_v bigint,
85 85 dbl_v double precision,
86 86 last_update_ts bigint,
87   - CONSTRAINT attributes_kv_unq_key UNIQUE (entity_type, entity_id, attribute_type, attribute_key)
  87 + CONSTRAINT attribute_kv_unq_key UNIQUE (entity_type, entity_id, attribute_type, attribute_key)
88 88 );
89 89 ALTER TABLE relation OWNER TO postgres;
90 90
... ...
... ... @@ -37,6 +37,6 @@ import org.springframework.test.context.support.DirtiesContextTestExecutionListe
37 37 DirtiesContextTestExecutionListener.class,
38 38 DbUnitTestExecutionListener.class })
39 39 @DbUnitConfiguration(databaseConnection = "dbUnitDatabaseConnection")
40   -public class AbstractJpaDaoTest extends AbstractTransactionalJUnit4SpringContextTests {
  40 +public abstract class AbstractJpaDaoTest extends AbstractTransactionalJUnit4SpringContextTests {
41 41
42 42 }
... ...
... ... @@ -38,8 +38,7 @@ public class DaoTestSuite {
38 38 public static CustomCassandraCQLUnit cassandraUnit =
39 39 new CustomCassandraCQLUnit(
40 40 Arrays.asList(new ClassPathCQLDataSet("cassandra/schema.cql", false, false),
41   - new ClassPathCQLDataSet("cassandra/system-data.cql", false, false),
42   - new ClassPathCQLDataSet("system-test.cql", false, false)),
  41 + new ClassPathCQLDataSet("cassandra/system-data.cql", false, false),
  42 + new ClassPathCQLDataSet("system-test.cql", false, false)),
43 43 "cassandra-test.yaml", 30000l);
44   -
45 44 }
... ...
... ... @@ -16,6 +16,10 @@
16 16 package org.thingsboard.server.dao.attributes;
17 17
18 18 import com.datastax.driver.core.utils.UUIDs;
  19 +import org.junit.Assert;
  20 +import org.junit.Before;
  21 +import org.junit.Test;
  22 +import org.springframework.beans.factory.annotation.Autowired;
19 23 import org.thingsboard.server.common.data.DataConstants;
20 24 import org.thingsboard.server.common.data.id.DeviceId;
21 25 import org.thingsboard.server.common.data.kv.AttributeKvEntry;
... ... @@ -23,20 +27,11 @@ import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry;
23 27 import org.thingsboard.server.common.data.kv.KvEntry;
24 28 import org.thingsboard.server.common.data.kv.StringDataEntry;
25 29 import org.thingsboard.server.dao.service.AbstractServiceTest;
26   -import org.junit.Assert;
27   -import org.junit.Before;
28   -import org.junit.Test;
29   -import org.slf4j.Logger;
30   -import org.slf4j.LoggerFactory;
31   -import org.springframework.beans.factory.annotation.Autowired;
32 30
33 31 import java.util.Collections;
34 32 import java.util.List;
35 33 import java.util.Optional;
36 34
37   -import static org.thingsboard.server.common.data.DataConstants.CLIENT_SCOPE;
38   -import static org.thingsboard.server.common.data.DataConstants.DEVICE;
39   -
40 35 /**
41 36 * @author Andrew Shvayka
42 37 */
... ...