Details
diff --git a/dao/src/main/java/org/thingsboard/server/dao/attributes/AttributesDao.java b/dao/src/main/java/org/thingsboard/server/dao/attributes/AttributesDao.java
index 4f0af49..704210e 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/attributes/AttributesDao.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/attributes/AttributesDao.java
@@ -36,5 +36,5 @@ public interface AttributesDao {
ListenableFuture<Void> save(EntityId entityId, String attributeType, AttributeKvEntry attribute);
- ListenableFuture<List<Void>> removeAll(EntityId entityId, String scope, List<String> keys);
+ ListenableFuture<List<Void>> removeAll(EntityId entityId, String attributeType, List<String> keys);
}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AttributeKvEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AttributeKvEntity.java
index 90bf2ab..2ea58af 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AttributeKvEntity.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AttributeKvEntity.java
@@ -16,21 +16,20 @@
package org.thingsboard.server.dao.model.sql;
import lombok.Data;
-import org.thingsboard.server.common.data.kv.AttributeKvEntry;
+import org.thingsboard.server.common.data.kv.*;
import org.thingsboard.server.dao.model.ToData;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.Id;
-import javax.persistence.Table;
+import javax.persistence.*;
+import java.io.Serializable;
import java.util.UUID;
import static org.thingsboard.server.dao.model.ModelConstants.*;
@Data
@Entity
-@Table(name = "attributes_kv")
-public class AttributeKvEntity implements ToData<AttributeKvEntry> {
+@Table(name = "attribute_kv")
+@IdClass(AttributeKvCompositeKey.class)
+public class AttributeKvEntity implements ToData<AttributeKvEntry>, Serializable {
@Id
@Column(name = ENTITY_TYPE_COLUMN)
@@ -65,7 +64,16 @@ public class AttributeKvEntity implements ToData<AttributeKvEntry> {
@Override
public AttributeKvEntry toData() {
- // TODO - add implementation
- return null;
+ KvEntry kvEntry = null;
+ if (strValue != null) {
+ kvEntry = new StringDataEntry(attributeKey, strValue);
+ } else if (booleanValue != null) {
+ kvEntry = new BooleanDataEntry(attributeKey, booleanValue);
+ } else if (doubleValue != null) {
+ kvEntry = new DoubleDataEntry(attributeKey, doubleValue);
+ } else if (longValue != null) {
+ kvEntry = new LongDataEntry(attributeKey, longValue);
+ }
+ return new BaseAttributeKvEntry(kvEntry, lastUpdateTs);
}
}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/attributes/AttributeKvRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/attributes/AttributeKvRepository.java
index ecb5fbe..a231f87 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/sql/attributes/AttributeKvRepository.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/attributes/AttributeKvRepository.java
@@ -17,9 +17,17 @@ package org.thingsboard.server.dao.sql.attributes;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.data.repository.CrudRepository;
+import org.thingsboard.server.dao.model.sql.AttributeKvCompositeKey;
import org.thingsboard.server.dao.model.sql.AttributeKvEntity;
-import org.thingsboard.server.dao.model.sql.AttributesKvCompositeKey;
+
+import java.util.List;
+import java.util.UUID;
@ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true")
-public interface AttributeKvRepository extends CrudRepository<AttributeKvEntity, AttributesKvCompositeKey> {
+public interface AttributeKvRepository extends CrudRepository<AttributeKvEntity, AttributeKvCompositeKey> {
+
+ List<AttributeKvEntity> findAllByEntityTypeAndEntityIdAndAttributeType(String entityType,
+ UUID entityId,
+ String attributeType);
}
+
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/attributes/JpaAttributeDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/attributes/JpaAttributeDao.java
index eb02aca..3260335 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/sql/attributes/JpaAttributeDao.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/attributes/JpaAttributeDao.java
@@ -15,6 +15,7 @@
*/
package org.thingsboard.server.dao.sql.attributes;
+import com.google.common.collect.Lists;
import com.google.common.util.concurrent.ListenableFuture;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
@@ -22,42 +23,97 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.kv.AttributeKvEntry;
+import org.thingsboard.server.dao.DaoUtil;
import org.thingsboard.server.dao.attributes.AttributesDao;
+import org.thingsboard.server.dao.model.sql.AttributeKvCompositeKey;
+import org.thingsboard.server.dao.model.sql.AttributeKvEntity;
+import org.thingsboard.server.dao.sql.JpaAbstractDaoListeningExecutorService;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
+import java.util.stream.Collectors;
@Component
@Slf4j
@ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true")
-public class JpaAttributeDao implements AttributesDao {
+public class JpaAttributeDao extends JpaAbstractDaoListeningExecutorService implements AttributesDao {
@Autowired
private AttributeKvRepository attributeKvRepository;
@Override
public ListenableFuture<Optional<AttributeKvEntry>> find(EntityId entityId, String attributeType, String attributeKey) {
- return null;
+ AttributeKvCompositeKey compositeKey =
+ new AttributeKvCompositeKey(
+ entityId.getEntityType().name(),
+ entityId.getId(),
+ attributeType,
+ attributeKey);
+ return service.submit(() ->
+ Optional.of(DaoUtil.getData(attributeKvRepository.findOne(compositeKey))));
}
@Override
- public ListenableFuture<List<AttributeKvEntry>> find(EntityId entityId, String attributeType, Collection<String> attributeKey) {
- return null;
+ public ListenableFuture<List<AttributeKvEntry>> find(EntityId entityId, String attributeType, Collection<String> attributeKeys) {
+ List<AttributeKvCompositeKey> compositeKeys =
+ attributeKeys
+ .stream()
+ .map(attributeKey ->
+ new AttributeKvCompositeKey(
+ entityId.getEntityType().name(),
+ entityId.getId(),
+ attributeType,
+ attributeKey))
+ .collect(Collectors.toList());
+ return service.submit(() ->
+ DaoUtil.convertDataList(Lists.newArrayList(attributeKvRepository.findAll(compositeKeys))));
}
@Override
public ListenableFuture<List<AttributeKvEntry>> findAll(EntityId entityId, String attributeType) {
- return null;
+ return service.submit(() ->
+ DaoUtil.convertDataList(Lists.newArrayList(
+ attributeKvRepository.findAllByEntityTypeAndEntityIdAndAttributeType(
+ entityId.getEntityType().name(),
+ entityId.getId(),
+ attributeType))));
}
@Override
public ListenableFuture<Void> save(EntityId entityId, String attributeType, AttributeKvEntry attribute) {
- return null;
+ AttributeKvEntity entity = new AttributeKvEntity();
+ entity.setEntityType(entityId.getEntityType().name());
+ entity.setEntityId(entityId.getId());
+ entity.setAttributeType(attributeType);
+ entity.setAttributeKey(attribute.getKey());
+ entity.setLastUpdateTs(attribute.getLastUpdateTs());
+ entity.setStrValue(attribute.getStrValue().orElse(null));
+ entity.setDoubleValue(attribute.getDoubleValue().orElse(null));
+ entity.setLongValue(attribute.getLongValue().orElse(null));
+ entity.setBooleanValue(attribute.getBooleanValue().orElse(null));
+ return service.submit(() -> {
+ attributeKvRepository.save(entity);
+ return null;
+ });
}
@Override
- public ListenableFuture<List<Void>> removeAll(EntityId entityId, String scope, List<String> keys) {
- return null;
+ public ListenableFuture<List<Void>> removeAll(EntityId entityId, String attributeType, List<String> keys) {
+ List<AttributeKvEntity> entitiesToDelete = keys
+ .stream()
+ .map(key -> {
+ AttributeKvEntity entityToDelete = new AttributeKvEntity();
+ entityToDelete.setEntityType(entityId.getEntityType().name());
+ entityToDelete.setEntityId(entityId.getId());
+ entityToDelete.setAttributeType(attributeType);
+ entityToDelete.setAttributeKey(key);
+ return entityToDelete;
+ }).collect(Collectors.toList());
+
+ return service.submit(() -> {
+ attributeKvRepository.delete(entitiesToDelete);
+ return null;
+ });
}
}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractDao.java
index aeaac25..a911711 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractDao.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractDao.java
@@ -38,7 +38,9 @@ import static org.springframework.transaction.annotation.Propagation.REQUIRES_NE
* @author Valerii Sosliuk
*/
@Slf4j
-public abstract class JpaAbstractDao<E extends BaseEntity<D>, D> implements Dao<D> {
+public abstract class JpaAbstractDao<E extends BaseEntity<D>, D>
+ extends JpaAbstractDaoListeningExecutorService
+ implements Dao<D> {
protected abstract Class<E> getEntityClass();
@@ -48,8 +50,6 @@ public abstract class JpaAbstractDao<E extends BaseEntity<D>, D> implements Dao<
return false;
}
- protected ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
-
@Override
@Transactional(propagation = REQUIRES_NEW)
public D save(D domain) {
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractDaoListeningExecutorService.java b/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractDaoListeningExecutorService.java
new file mode 100644
index 0000000..47df102
--- /dev/null
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractDaoListeningExecutorService.java
@@ -0,0 +1,25 @@
+/**
+ * Copyright © 2016-2017 The Thingsboard Authors
+ *
+ * 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.dao.sql;
+
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+
+import java.util.concurrent.Executors;
+
+public abstract class JpaAbstractDaoListeningExecutorService {
+ protected ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
+}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/relation/JpaRelationDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/relation/JpaRelationDao.java
index 3dadbf0..db33808 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/sql/relation/JpaRelationDao.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/relation/JpaRelationDao.java
@@ -16,8 +16,6 @@
package org.thingsboard.server.dao.sql.relation;
import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@@ -36,6 +34,7 @@ import org.thingsboard.server.dao.DaoUtil;
import org.thingsboard.server.dao.model.sql.RelationCompositeKey;
import org.thingsboard.server.dao.model.sql.RelationEntity;
import org.thingsboard.server.dao.relation.RelationDao;
+import org.thingsboard.server.dao.sql.JpaAbstractDaoListeningExecutorService;
import org.thingsboard.server.dao.sql.JpaAbstractSearchTimeDao;
import javax.persistence.criteria.CriteriaBuilder;
@@ -44,7 +43,6 @@ import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;
-import java.util.concurrent.Executors;
import static org.springframework.data.domain.Sort.Direction.ASC;
import static org.springframework.data.jpa.domain.Specifications.where;
@@ -56,16 +54,14 @@ import static org.thingsboard.server.dao.model.ModelConstants.*;
@Slf4j
@Component
@ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false)
-public class JpaRelationDao implements RelationDao {
+public class JpaRelationDao extends JpaAbstractDaoListeningExecutorService implements RelationDao {
@Autowired
private RelationRepository relationRepository;
- private ListeningExecutorService executorService = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
-
@Override
public ListenableFuture<List<EntityRelation>> findAllByFrom(EntityId from, RelationTypeGroup typeGroup) {
- return executorService.submit(() -> DaoUtil.convertDataList(
+ return service.submit(() -> DaoUtil.convertDataList(
relationRepository.findAllByFromIdAndFromTypeAndRelationTypeGroup(
from.getId(),
from.getEntityType().name(),
@@ -74,7 +70,7 @@ public class JpaRelationDao implements RelationDao {
@Override
public ListenableFuture<List<EntityRelation>> findAllByFromAndType(EntityId from, String relationType, RelationTypeGroup typeGroup) {
- return executorService.submit(() -> DaoUtil.convertDataList(
+ return service.submit(() -> DaoUtil.convertDataList(
relationRepository.findAllByFromIdAndFromTypeAndRelationTypeAndRelationTypeGroup(
from.getId(),
from.getEntityType().name(),
@@ -84,7 +80,7 @@ public class JpaRelationDao implements RelationDao {
@Override
public ListenableFuture<List<EntityRelation>> findAllByTo(EntityId to, RelationTypeGroup typeGroup) {
- return executorService.submit(() -> DaoUtil.convertDataList(
+ return service.submit(() -> DaoUtil.convertDataList(
relationRepository.findAllByToIdAndToTypeAndRelationTypeGroup(
to.getId(),
to.getEntityType().name(),
@@ -93,7 +89,7 @@ public class JpaRelationDao implements RelationDao {
@Override
public ListenableFuture<List<EntityRelation>> findAllByToAndType(EntityId to, String relationType, RelationTypeGroup typeGroup) {
- return executorService.submit(() -> DaoUtil.convertDataList(
+ return service.submit(() -> DaoUtil.convertDataList(
relationRepository.findAllByToIdAndToTypeAndRelationTypeAndRelationTypeGroup(
to.getId(),
to.getEntityType().name(),
@@ -110,18 +106,18 @@ public class JpaRelationDao implements RelationDao {
to.getEntityType().name(),
relationType,
typeGroup.name());
- return executorService.submit(() -> relationRepository.findOne(key) != null);
+ return service.submit(() -> relationRepository.findOne(key) != null);
}
@Override
public ListenableFuture<Boolean> saveRelation(EntityRelation relation) {
- return executorService.submit(() -> relationRepository.save(new RelationEntity(relation)) != null);
+ return service.submit(() -> relationRepository.save(new RelationEntity(relation)) != null);
}
@Override
public ListenableFuture<Boolean> deleteRelation(EntityRelation relation) {
RelationCompositeKey key = new RelationCompositeKey(relation);
- return executorService.submit(
+ return service.submit(
() -> {
boolean relationExistsBeforeDelete = relationRepository.exists(key);
relationRepository.delete(key);
@@ -138,7 +134,7 @@ public class JpaRelationDao implements RelationDao {
to.getEntityType().name(),
relationType,
typeGroup.name());
- return executorService.submit(
+ return service.submit(
() -> {
boolean relationExistsBeforeDelete = relationRepository.exists(key);
relationRepository.delete(key);
@@ -152,7 +148,7 @@ public class JpaRelationDao implements RelationDao {
relationEntity.setFromId(entity.getId());
relationEntity.setFromType(entity.getEntityType().name());
- return executorService.submit(
+ return service.submit(
() -> {
boolean relationExistsBeforeDelete = relationRepository
.findAllByFromIdAndFromType(relationEntity.getFromId(), relationEntity.getFromType())
@@ -172,7 +168,7 @@ public class JpaRelationDao implements RelationDao {
new Order(ASC, RELATION_TYPE_PROPERTY),
new Order(ASC, RELATION_TO_TYPE_PROPERTY))
);
- return executorService.submit(() ->
+ return service.submit(() ->
DaoUtil.convertDataList(relationRepository.findAll(where(timeSearchSpec).and(fieldsSpec), pageable).getContent()));
}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/util/JsonBinaryType.java b/dao/src/main/java/org/thingsboard/server/dao/util/JsonBinaryType.java
index 96a49c9..81d776b 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/util/JsonBinaryType.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/util/JsonBinaryType.java
@@ -23,7 +23,7 @@ import java.util.Properties;
/**
* Created by Valerii Sosliuk on 5/12/2017.
*/
-public class JsonBinaryType extends AbstractSingleColumnStandardBasicType<Object>
+public class JsonBinaryType extends AbstractSingleColumnStandardBasicType<Object>
implements DynamicParameterizedType {
public JsonBinaryType() {
diff --git a/dao/src/main/resources/postgres/schema.sql b/dao/src/main/resources/postgres/schema.sql
index 684ec00..e78199f 100644
--- a/dao/src/main/resources/postgres/schema.sql
+++ b/dao/src/main/resources/postgres/schema.sql
@@ -74,7 +74,7 @@ CREATE TABLE IF NOT EXISTS asset (
);
ALTER TABLE asset OWNER TO postgres;
-CREATE TABLE IF NOT EXISTS attributes_kv (
+CREATE TABLE IF NOT EXISTS attribute_kv (
entity_type character varying(255),
entity_id uuid,
attribute_type character varying(255),
@@ -84,7 +84,7 @@ CREATE TABLE IF NOT EXISTS attributes_kv (
long_v bigint,
dbl_v double precision,
last_update_ts bigint,
- CONSTRAINT attributes_kv_unq_key UNIQUE (entity_type, entity_id, attribute_type, attribute_key)
+ CONSTRAINT attribute_kv_unq_key UNIQUE (entity_type, entity_id, attribute_type, attribute_key)
);
ALTER TABLE relation OWNER TO postgres;
diff --git a/dao/src/test/java/org/thingsboard/server/dao/AbstractJpaDaoTest.java b/dao/src/test/java/org/thingsboard/server/dao/AbstractJpaDaoTest.java
index c8e715f..daf59f3 100644
--- a/dao/src/test/java/org/thingsboard/server/dao/AbstractJpaDaoTest.java
+++ b/dao/src/test/java/org/thingsboard/server/dao/AbstractJpaDaoTest.java
@@ -37,6 +37,6 @@ import org.springframework.test.context.support.DirtiesContextTestExecutionListe
DirtiesContextTestExecutionListener.class,
DbUnitTestExecutionListener.class })
@DbUnitConfiguration(databaseConnection = "dbUnitDatabaseConnection")
-public class AbstractJpaDaoTest extends AbstractTransactionalJUnit4SpringContextTests {
+public abstract class AbstractJpaDaoTest extends AbstractTransactionalJUnit4SpringContextTests {
}
diff --git a/dao/src/test/java/org/thingsboard/server/dao/attributes/BaseAttributesServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/attributes/BaseAttributesServiceTest.java
index 559a313..61b5329 100644
--- a/dao/src/test/java/org/thingsboard/server/dao/attributes/BaseAttributesServiceTest.java
+++ b/dao/src/test/java/org/thingsboard/server/dao/attributes/BaseAttributesServiceTest.java
@@ -16,6 +16,10 @@
package org.thingsboard.server.dao.attributes;
import com.datastax.driver.core.utils.UUIDs;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
import org.thingsboard.server.common.data.DataConstants;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.kv.AttributeKvEntry;
@@ -23,20 +27,11 @@ import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry;
import org.thingsboard.server.common.data.kv.KvEntry;
import org.thingsboard.server.common.data.kv.StringDataEntry;
import org.thingsboard.server.dao.service.AbstractServiceTest;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
-import static org.thingsboard.server.common.data.DataConstants.CLIENT_SCOPE;
-import static org.thingsboard.server.common.data.DataConstants.DEVICE;
-
/**
* @author Andrew Shvayka
*/
diff --git a/dao/src/test/java/org/thingsboard/server/dao/DaoTestSuite.java b/dao/src/test/java/org/thingsboard/server/dao/DaoTestSuite.java
index 26d9223..845c4c6 100644
--- a/dao/src/test/java/org/thingsboard/server/dao/DaoTestSuite.java
+++ b/dao/src/test/java/org/thingsboard/server/dao/DaoTestSuite.java
@@ -38,8 +38,7 @@ public class DaoTestSuite {
public static CustomCassandraCQLUnit cassandraUnit =
new CustomCassandraCQLUnit(
Arrays.asList(new ClassPathCQLDataSet("cassandra/schema.cql", false, false),
- new ClassPathCQLDataSet("cassandra/system-data.cql", false, false),
- new ClassPathCQLDataSet("system-test.cql", false, false)),
+ new ClassPathCQLDataSet("cassandra/system-data.cql", false, false),
+ new ClassPathCQLDataSet("system-test.cql", false, false)),
"cassandra-test.yaml", 30000l);
-
}