Browse Source

Added attribute jpa dao

pull/152/head
Volodymyr Babak 9 years ago
parent
commit
4351c30adf
  1. 2
      dao/src/main/java/org/thingsboard/server/dao/attributes/AttributesDao.java
  2. 6
      dao/src/main/java/org/thingsboard/server/dao/model/sql/AttributeKvCompositeKey.java
  3. 26
      dao/src/main/java/org/thingsboard/server/dao/model/sql/AttributeKvEntity.java
  4. 6
      dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractDao.java
  5. 25
      dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractDaoListeningExecutorService.java
  6. 12
      dao/src/main/java/org/thingsboard/server/dao/sql/attributes/AttributeKvRepository.java
  7. 72
      dao/src/main/java/org/thingsboard/server/dao/sql/attributes/JpaAttributeDao.java
  8. 28
      dao/src/main/java/org/thingsboard/server/dao/sql/relation/JpaRelationDao.java
  9. 2
      dao/src/main/java/org/thingsboard/server/dao/util/JsonBinaryType.java
  10. 4
      dao/src/main/resources/postgres/schema.sql
  11. 2
      dao/src/test/java/org/thingsboard/server/dao/AbstractJpaDaoTest.java
  12. 5
      dao/src/test/java/org/thingsboard/server/dao/DaoTestSuite.java
  13. 13
      dao/src/test/java/org/thingsboard/server/dao/attributes/BaseAttributesServiceTest.java

2
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);
}

6
dao/src/main/java/org/thingsboard/server/dao/model/sql/AttributesKvCompositeKey.java → dao/src/main/java/org/thingsboard/server/dao/model/sql/AttributeKvCompositeKey.java

@ -15,13 +15,17 @@
*/
package org.thingsboard.server.dao.model.sql;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.UUID;
@Data
public class AttributesKvCompositeKey implements Serializable {
@AllArgsConstructor
@NoArgsConstructor
public class AttributeKvCompositeKey implements Serializable {
private String entityType;
private UUID entityId;
private String attributeType;

26
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);
}
}

6
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) {

25
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));
}

12
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);
}

72
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;
});
}
}

28
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()));
}

2
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() {

4
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;

2
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 {
}

5
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);
}

13
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
*/

Loading…
Cancel
Save