Commit bfd0118881db0da5a671f3e9035c62e57ddd319d
1 parent
d65d788b
JpaAbstractSearchTimeDao JpaBaseEventDao
Showing
13 changed files
with
445 additions
and
45 deletions
... | ... | @@ -142,7 +142,7 @@ public class CassandraBaseEventDao extends CassandraAbstractSearchTimeDao<EventE |
142 | 142 | .value(ModelConstants.EVENT_ENTITY_TYPE_PROPERTY, entity.getEntityType()) |
143 | 143 | .value(ModelConstants.EVENT_ENTITY_ID_PROPERTY, entity.getEntityId()) |
144 | 144 | .value(ModelConstants.EVENT_TYPE_PROPERTY, entity.getEventType()) |
145 | - .value(ModelConstants.EVENT_UID_PROPERTY, entity.getEventUId()) | |
145 | + .value(ModelConstants.EVENT_UID_PROPERTY, entity.getEventUid()) | |
146 | 146 | .value(ModelConstants.EVENT_BODY_PROPERTY, entity.getBody()); |
147 | 147 | if (ifNotExists) { |
148 | 148 | insert = insert.ifNotExists(); | ... | ... |
... | ... | @@ -36,7 +36,7 @@ import java.util.UUID; |
36 | 36 | */ |
37 | 37 | @Data |
38 | 38 | @NoArgsConstructor |
39 | -@Table(name = DEVICE_COLUMN_FAMILY_NAME) | |
39 | +@Table(name = EVENT_COLUMN_FAMILY_NAME) | |
40 | 40 | public class EventEntity implements BaseEntity<Event> { |
41 | 41 | |
42 | 42 | @Transient |
... | ... | @@ -63,7 +63,7 @@ public class EventEntity implements BaseEntity<Event> { |
63 | 63 | |
64 | 64 | @ClusteringColumn(value = 1) |
65 | 65 | @Column(name = EVENT_UID_PROPERTY) |
66 | - private String eventUId; | |
66 | + private String eventUid; | |
67 | 67 | |
68 | 68 | @Column(name = EVENT_BODY_PROPERTY, codec = JsonCodec.class) |
69 | 69 | private JsonNode body; |
... | ... | @@ -80,7 +80,7 @@ public class EventEntity implements BaseEntity<Event> { |
80 | 80 | this.entityId = event.getEntityId().getId(); |
81 | 81 | } |
82 | 82 | this.eventType = event.getType(); |
83 | - this.eventUId = event.getUid(); | |
83 | + this.eventUid = event.getUid(); | |
84 | 84 | this.body = event.getBody(); |
85 | 85 | } |
86 | 86 | |
... | ... | @@ -118,7 +118,7 @@ public class EventEntity implements BaseEntity<Event> { |
118 | 118 | } |
119 | 119 | event.setBody(body); |
120 | 120 | event.setType(eventType); |
121 | - event.setUid(eventUId); | |
121 | + event.setUid(eventUid); | |
122 | 122 | return event; |
123 | 123 | } |
124 | 124 | } | ... | ... |
... | ... | @@ -22,46 +22,51 @@ import javax.persistence.Id; |
22 | 22 | import javax.persistence.Table; |
23 | 23 | import javax.persistence.Transient; |
24 | 24 | import com.fasterxml.jackson.databind.JsonNode; |
25 | +import com.fasterxml.jackson.databind.ObjectMapper; | |
25 | 26 | import lombok.Data; |
26 | 27 | import lombok.NoArgsConstructor; |
28 | +import lombok.extern.slf4j.Slf4j; | |
27 | 29 | import org.thingsboard.server.common.data.EntityType; |
28 | 30 | import org.thingsboard.server.common.data.Event; |
29 | 31 | import org.thingsboard.server.common.data.id.*; |
30 | 32 | import org.thingsboard.server.dao.model.BaseEntity; |
31 | -import org.thingsboard.server.dao.model.ModelConstants; | |
32 | 33 | |
34 | +import static org.thingsboard.server.dao.model.ModelConstants.*; | |
35 | + | |
36 | +import java.io.IOException; | |
33 | 37 | import java.util.UUID; |
34 | 38 | |
35 | 39 | @Data |
40 | +@Slf4j | |
36 | 41 | @NoArgsConstructor |
37 | -//@Entity | |
38 | -@Table(name = ModelConstants.DEVICE_COLUMN_FAMILY_NAME) | |
42 | +@Entity | |
43 | +@Table(name = EVENT_COLUMN_FAMILY_NAME) | |
39 | 44 | public class EventEntity implements BaseEntity<Event> { |
40 | 45 | |
41 | 46 | @Transient |
42 | 47 | private static final long serialVersionUID = -5717830061727466727L; |
43 | 48 | |
44 | - @Column(name = ModelConstants.ID_PROPERTY) | |
49 | + @Id | |
50 | + @Column(name = ID_PROPERTY, columnDefinition = "BINARY(16)") | |
45 | 51 | private UUID id; |
46 | 52 | |
47 | - @Id | |
48 | - @Column(name = ModelConstants.EVENT_TENANT_ID_PROPERTY) | |
53 | + @Column(name = EVENT_TENANT_ID_PROPERTY, columnDefinition = "BINARY(16)") | |
49 | 54 | private UUID tenantId; |
50 | 55 | |
51 | - @Column(name = ModelConstants.EVENT_ENTITY_TYPE_PROPERTY) | |
56 | + @Column(name = EVENT_ENTITY_TYPE_PROPERTY) | |
52 | 57 | private EntityType entityType; |
53 | 58 | |
54 | - @Column(name = ModelConstants.EVENT_ENTITY_ID_PROPERTY) | |
59 | + @Column(name = EVENT_ENTITY_ID_PROPERTY, columnDefinition = "BINARY(16)") | |
55 | 60 | private UUID entityId; |
56 | 61 | |
57 | - @Column(name = ModelConstants.EVENT_TYPE_PROPERTY) | |
62 | + @Column(name = EVENT_TYPE_PROPERTY) | |
58 | 63 | private String eventType; |
59 | 64 | |
60 | - @Column(name = ModelConstants.EVENT_UID_PROPERTY) | |
61 | - private String eventUId; | |
65 | + @Column(name = EVENT_UID_PROPERTY) | |
66 | + private String eventUid; | |
62 | 67 | |
63 | - @Column(name = ModelConstants.EVENT_BODY_PROPERTY) | |
64 | - private JsonNode body; | |
68 | + @Column(name = EVENT_BODY_PROPERTY) | |
69 | + private String body; | |
65 | 70 | |
66 | 71 | public EventEntity(Event event) { |
67 | 72 | if (event.getId() != null) { |
... | ... | @@ -75,8 +80,10 @@ public class EventEntity implements BaseEntity<Event> { |
75 | 80 | this.entityId = event.getEntityId().getId(); |
76 | 81 | } |
77 | 82 | this.eventType = event.getType(); |
78 | - this.eventUId = event.getUid(); | |
79 | - this.body = event.getBody(); | |
83 | + this.eventUid = event.getUid(); | |
84 | + if (event.getBody() != null) { | |
85 | + this.body = event.getBody().toString(); | |
86 | + } | |
80 | 87 | } |
81 | 88 | |
82 | 89 | @Override |
... | ... | @@ -111,9 +118,17 @@ public class EventEntity implements BaseEntity<Event> { |
111 | 118 | event.setEntityId(new PluginId(entityId)); |
112 | 119 | break; |
113 | 120 | } |
114 | - event.setBody(body); | |
121 | + ObjectMapper mapper = new ObjectMapper(); | |
122 | + if (body != null) { | |
123 | + try { | |
124 | + JsonNode jsonNode = mapper.readTree(body); | |
125 | + event.setBody(jsonNode); | |
126 | + } catch (IOException e) { | |
127 | + log.warn(String.format("Error parsing JsonNode: %s. Reason: %s ", body, e.getMessage()), e); | |
128 | + } | |
129 | + } | |
115 | 130 | event.setType(eventType); |
116 | - event.setUid(eventUId); | |
131 | + event.setUid(eventUid); | |
117 | 132 | return event; |
118 | 133 | } |
119 | 134 | } | ... | ... |
1 | +package org.thingsboard.server.dao.sql; | |
2 | + | |
3 | +import org.thingsboard.server.dao.model.BaseEntity; | |
4 | + | |
5 | +/** | |
6 | + * Created by Valerii Sosliuk on 5/6/2017. | |
7 | + */ | |
8 | +public abstract class JpaAbstractSearchTextDao <E extends BaseEntity<D>, D> extends JpaAbstractDao<E, D> { | |
9 | + | |
10 | + @Override | |
11 | + protected boolean isSearchTextDao() { | |
12 | + return true; | |
13 | + } | |
14 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.sql; | |
2 | + | |
3 | +import com.datastax.driver.core.utils.UUIDs; | |
4 | +import org.springframework.data.jpa.domain.Specification; | |
5 | +import org.thingsboard.server.common.data.page.TimePageLink; | |
6 | +import org.thingsboard.server.dao.model.BaseEntity; | |
7 | +import static org.thingsboard.server.dao.model.ModelConstants.*; | |
8 | + | |
9 | +import javax.persistence.criteria.CriteriaBuilder; | |
10 | +import javax.persistence.criteria.CriteriaQuery; | |
11 | +import javax.persistence.criteria.Predicate; | |
12 | +import javax.persistence.criteria.Root; | |
13 | +import java.util.ArrayList; | |
14 | +import java.util.List; | |
15 | +import java.util.UUID; | |
16 | + | |
17 | +/** | |
18 | + * Created by Valerii Sosliuk on 5/4/2017. | |
19 | + */ | |
20 | +public abstract class JpaAbstractSearchTimeDao<E extends BaseEntity<D>, D> extends JpaAbstractDao<E, D> { | |
21 | + | |
22 | + protected Specification<E> getTimeSearchPageSpec(TimePageLink pageLink) { | |
23 | + return new Specification<E>() { | |
24 | + @Override | |
25 | + public Predicate toPredicate(Root<E> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) { | |
26 | + Predicate lowerBound = null; | |
27 | + Predicate upperBound = null; | |
28 | + List<Predicate> predicates = new ArrayList<>(); | |
29 | + if (pageLink.isAscOrder()) { | |
30 | + if (pageLink.getIdOffset() != null) { | |
31 | + lowerBound = criteriaBuilder.greaterThan(root.get(ID_PROPERTY), pageLink.getIdOffset()); | |
32 | + predicates.add(lowerBound); | |
33 | + } else if (pageLink.getStartTime() != null) { | |
34 | + UUID startOf = UUIDs.startOf(pageLink.getStartTime()); | |
35 | + lowerBound = criteriaBuilder.greaterThanOrEqualTo(root.get(ID_PROPERTY), startOf); | |
36 | + predicates.add(lowerBound); | |
37 | + } | |
38 | + if (pageLink.getEndTime() != null) { | |
39 | + UUID endOf = UUIDs.endOf(pageLink.getEndTime()); | |
40 | + upperBound = criteriaBuilder.lessThanOrEqualTo(root.get(ID_PROPERTY), endOf); | |
41 | + predicates.add(upperBound); | |
42 | + } | |
43 | + } else { | |
44 | + if (pageLink.getIdOffset() != null) { | |
45 | + lowerBound = criteriaBuilder.lessThan(root.get(ID_PROPERTY), pageLink.getIdOffset()); | |
46 | + predicates.add(lowerBound); | |
47 | + } else if (pageLink.getEndTime() != null) { | |
48 | + UUID endOf = UUIDs.endOf(pageLink.getEndTime()); | |
49 | + lowerBound = criteriaBuilder.lessThanOrEqualTo(root.get(ID_PROPERTY), endOf); | |
50 | + predicates.add(lowerBound); | |
51 | + } | |
52 | + if (pageLink.getStartTime() != null) { | |
53 | + UUID startOf = UUIDs.startOf(pageLink.getStartTime()); | |
54 | + upperBound = criteriaBuilder.greaterThanOrEqualTo(root.get(ID_PROPERTY), startOf); | |
55 | + predicates.add(upperBound); | |
56 | + } | |
57 | + } | |
58 | + return criteriaBuilder.and(predicates.toArray(new Predicate[0])); | |
59 | + } | |
60 | + }; | |
61 | + } | |
62 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.sql.event; | |
2 | + | |
3 | +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | |
4 | +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; | |
5 | +import org.springframework.data.jpa.repository.Query; | |
6 | +import org.springframework.data.repository.CrudRepository; | |
7 | +import org.springframework.data.repository.query.Param; | |
8 | +import org.thingsboard.server.common.data.EntityType; | |
9 | +import org.thingsboard.server.common.data.Event; | |
10 | +import org.thingsboard.server.dao.model.sql.EventEntity; | |
11 | + | |
12 | +import java.util.List; | |
13 | +import java.util.UUID; | |
14 | + | |
15 | +/** | |
16 | + * Created by Valerii Sosliuk on 5/3/2017. | |
17 | + */ | |
18 | +@ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false) | |
19 | +public interface EventRepository extends CrudRepository<EventEntity, UUID>, JpaSpecificationExecutor<EventEntity> { | |
20 | + | |
21 | + EventEntity findByTenantIdAndEntityTypeAndEntityIdAndEventTypeAndEventUid( | |
22 | + UUID tenantId, EntityType entityType, UUID id, String eventType, String eventUid); | |
23 | + | |
24 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.sql.event; | |
2 | + | |
3 | +import com.datastax.driver.core.utils.UUIDs; | |
4 | +import lombok.extern.slf4j.Slf4j; | |
5 | +import org.apache.commons.lang3.StringUtils; | |
6 | +import org.springframework.beans.factory.annotation.Autowired; | |
7 | +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | |
8 | +import org.springframework.data.domain.PageRequest; | |
9 | +import org.springframework.data.domain.Pageable; | |
10 | +import org.springframework.data.domain.Sort; | |
11 | +import org.springframework.data.jpa.domain.Specification; | |
12 | +import org.springframework.data.repository.CrudRepository; | |
13 | +import org.springframework.stereotype.Component; | |
14 | +import org.thingsboard.server.common.data.Event; | |
15 | +import org.thingsboard.server.common.data.id.EntityId; | |
16 | +import org.thingsboard.server.common.data.page.TimePageLink; | |
17 | +import org.thingsboard.server.dao.DaoUtil; | |
18 | +import org.thingsboard.server.dao.event.EventDao; | |
19 | +import org.thingsboard.server.dao.model.sql.EventEntity; | |
20 | +import org.thingsboard.server.dao.sql.JpaAbstractSearchTimeDao; | |
21 | + | |
22 | +import javax.persistence.criteria.CriteriaBuilder; | |
23 | +import javax.persistence.criteria.CriteriaQuery; | |
24 | +import javax.persistence.criteria.Predicate; | |
25 | +import javax.persistence.criteria.Root; | |
26 | +import java.util.ArrayList; | |
27 | +import java.util.List; | |
28 | +import java.util.Optional; | |
29 | +import java.util.UUID; | |
30 | + | |
31 | +import static org.springframework.data.jpa.domain.Specifications.where; | |
32 | +import static org.thingsboard.server.dao.model.ModelConstants.EVENT_COLUMN_FAMILY_NAME; | |
33 | +import static org.thingsboard.server.dao.model.ModelConstants.ID_PROPERTY; | |
34 | +import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID; | |
35 | + | |
36 | +/** | |
37 | + * Created by Valerii Sosliuk on 5/3/2017. | |
38 | + */ | |
39 | +@Slf4j | |
40 | +@Component | |
41 | +@ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false) | |
42 | +public class JpaBaseEventDao extends JpaAbstractSearchTimeDao<EventEntity, Event> implements EventDao { | |
43 | + | |
44 | + private final UUID systemTenantId = NULL_UUID; | |
45 | + | |
46 | + @Autowired | |
47 | + private EventRepository eventRepository; | |
48 | + | |
49 | + @Override | |
50 | + protected Class<EventEntity> getEntityClass() { | |
51 | + return EventEntity.class; | |
52 | + } | |
53 | + | |
54 | + @Override | |
55 | + protected String getColumnFamilyName() { | |
56 | + return EVENT_COLUMN_FAMILY_NAME; | |
57 | + } | |
58 | + | |
59 | + @Override | |
60 | + protected CrudRepository<EventEntity, UUID> getCrudRepository() { | |
61 | + return eventRepository; | |
62 | + } | |
63 | + | |
64 | + @Override | |
65 | + public Event save(Event event) { | |
66 | + if (StringUtils.isEmpty(event.getUid())) { | |
67 | + event.setUid(event.getId().toString()); | |
68 | + } | |
69 | + return save(new EventEntity(event), false).orElse(null); | |
70 | + } | |
71 | + | |
72 | + @Override | |
73 | + public Optional<Event> saveIfNotExists(Event event) { | |
74 | + return save(new EventEntity(event), true); | |
75 | + } | |
76 | + | |
77 | + @Override | |
78 | + public Event findEvent(UUID tenantId, EntityId entityId, String eventType, String eventUid) { | |
79 | + return DaoUtil.getData(eventRepository.findByTenantIdAndEntityTypeAndEntityIdAndEventTypeAndEventUid( | |
80 | + tenantId, entityId.getEntityType(), entityId.getId(), eventType, eventUid)); | |
81 | + } | |
82 | + | |
83 | + @Override | |
84 | + public List<Event> findEvents(UUID tenantId, EntityId entityId, TimePageLink pageLink) { | |
85 | + return findEvents(tenantId, entityId, null, pageLink); | |
86 | + } | |
87 | + @Override | |
88 | + public List<Event> findEvents(UUID tenantId, EntityId entityId, String eventType, TimePageLink pageLink) { | |
89 | + Specification<EventEntity> timeSearchSpec = getTimeSearchPageSpec(pageLink); | |
90 | + Specification<EventEntity> fieldsSpec = getEntityFieldsSpec(tenantId, entityId, eventType); | |
91 | + Sort.Direction sortDirection = pageLink.isAscOrder() ? Sort.Direction.ASC : Sort.Direction.DESC; | |
92 | + Pageable pageable = new PageRequest(0, pageLink.getLimit(), sortDirection, ID_PROPERTY); | |
93 | + return DaoUtil.convertDataList(eventRepository.findAll(where(timeSearchSpec).and(fieldsSpec), pageable).getContent()); | |
94 | + } | |
95 | + | |
96 | + public Optional<Event> save(EventEntity entity, boolean ifNotExists) { | |
97 | + log.debug("Save event [{}] ", entity); | |
98 | + if (entity.getTenantId() == null) { | |
99 | + log.trace("Save system event with predefined id {}", systemTenantId); | |
100 | + entity.setTenantId(systemTenantId); | |
101 | + } | |
102 | + if (entity.getId() == null) { | |
103 | + entity.setId(UUIDs.timeBased()); | |
104 | + } | |
105 | + if (StringUtils.isEmpty(entity.getEventUid())) { | |
106 | + entity.setEventUid(entity.getId().toString()); | |
107 | + } | |
108 | + if (ifNotExists && findById(entity.getId()) != null) { | |
109 | + return Optional.empty(); | |
110 | + } | |
111 | + return Optional.of(DaoUtil.getData(eventRepository.save(entity))); | |
112 | + } | |
113 | + | |
114 | + private Specification<EventEntity> getEntityFieldsSpec(UUID tenantId, EntityId entityId, String eventType) { | |
115 | + return new Specification<EventEntity>() { | |
116 | + @Override | |
117 | + public Predicate toPredicate(Root<EventEntity> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) { | |
118 | + List<Predicate> predicates = new ArrayList<Predicate>(); | |
119 | + if (tenantId != null) { | |
120 | + Predicate tenantIdPredicate = criteriaBuilder.equal(root.get("tenantId"), tenantId); | |
121 | + predicates.add(tenantIdPredicate); | |
122 | + } | |
123 | + if (entityId != null) { | |
124 | + Predicate entityTypePredicate = criteriaBuilder.equal(root.get("entityType"), entityId.getEntityType()); | |
125 | + Predicate entityIdPredicate = criteriaBuilder.equal(root.get("entityId"), entityId.getId()); | |
126 | + predicates.add(entityTypePredicate); | |
127 | + predicates.add(entityIdPredicate); | |
128 | + } | |
129 | + if (eventType != null) { | |
130 | + Predicate eventTypePredicate = criteriaBuilder.equal(root.get("eventType"), eventType); | |
131 | + predicates.add(eventTypePredicate); | |
132 | + } | |
133 | + return criteriaBuilder.and(predicates.toArray(new Predicate[0])); | |
134 | + } | |
135 | + }; | |
136 | + } | |
137 | +} | ... | ... |
... | ... | @@ -29,6 +29,7 @@ import org.thingsboard.server.dao.model.ModelConstants; |
29 | 29 | import org.thingsboard.server.dao.model.sql.PluginMetaDataEntity; |
30 | 30 | import org.thingsboard.server.dao.plugin.PluginDao; |
31 | 31 | import org.thingsboard.server.dao.sql.JpaAbstractDao; |
32 | +import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao; | |
32 | 33 | |
33 | 34 | import java.util.Arrays; |
34 | 35 | import java.util.List; |
... | ... | @@ -40,7 +41,7 @@ import java.util.UUID; |
40 | 41 | @Slf4j |
41 | 42 | @Component |
42 | 43 | @ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false) |
43 | -public class JpaBasePluginDao extends JpaAbstractDao<PluginMetaDataEntity, PluginMetaData> implements PluginDao { | |
44 | +public class JpaBasePluginDao extends JpaAbstractSearchTextDao<PluginMetaDataEntity, PluginMetaData> implements PluginDao { | |
44 | 45 | |
45 | 46 | @Autowired |
46 | 47 | private PluginMetaDataRepository pluginMetaDataRepository; |
... | ... | @@ -61,11 +62,6 @@ public class JpaBasePluginDao extends JpaAbstractDao<PluginMetaDataEntity, Plugi |
61 | 62 | } |
62 | 63 | |
63 | 64 | @Override |
64 | - protected boolean isSearchTextDao() { | |
65 | - return true; | |
66 | - } | |
67 | - | |
68 | - @Override | |
69 | 65 | public PluginMetaData findById(PluginId pluginId) { |
70 | 66 | log.debug("Search plugin meta-data entity by id [{}]", pluginId); |
71 | 67 | PluginMetaData pluginMetaData = super.findById(pluginId.getId()); | ... | ... |
... | ... | @@ -29,6 +29,7 @@ import org.thingsboard.server.dao.model.ModelConstants; |
29 | 29 | import org.thingsboard.server.dao.model.sql.RuleMetaDataEntity; |
30 | 30 | import org.thingsboard.server.dao.rule.RuleDao; |
31 | 31 | import org.thingsboard.server.dao.sql.JpaAbstractDao; |
32 | +import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao; | |
32 | 33 | |
33 | 34 | import java.util.Arrays; |
34 | 35 | import java.util.List; |
... | ... | @@ -40,7 +41,7 @@ import java.util.UUID; |
40 | 41 | @Slf4j |
41 | 42 | @Component |
42 | 43 | @ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false) |
43 | -public class JpaBaseRuleDao extends JpaAbstractDao<RuleMetaDataEntity, RuleMetaData> implements RuleDao { | |
44 | +public class JpaBaseRuleDao extends JpaAbstractSearchTextDao<RuleMetaDataEntity, RuleMetaData> implements RuleDao { | |
44 | 45 | |
45 | 46 | @Autowired |
46 | 47 | private RuleMetaDataRepository ruleMetaDataRepository; |
... | ... | @@ -60,11 +61,6 @@ public class JpaBaseRuleDao extends JpaAbstractDao<RuleMetaDataEntity, RuleMetaD |
60 | 61 | } |
61 | 62 | |
62 | 63 | @Override |
63 | - protected boolean isSearchTextDao() { | |
64 | - return true; | |
65 | - } | |
66 | - | |
67 | - @Override | |
68 | 64 | public RuleMetaData findById(RuleId ruleId) { |
69 | 65 | return findById(ruleId.getId()); |
70 | 66 | } | ... | ... |
... | ... | @@ -24,6 +24,7 @@ import org.thingsboard.server.common.data.page.TextPageLink; |
24 | 24 | import org.thingsboard.server.dao.DaoUtil; |
25 | 25 | import org.thingsboard.server.dao.model.sql.TenantEntity; |
26 | 26 | import org.thingsboard.server.dao.sql.JpaAbstractDao; |
27 | +import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao; | |
27 | 28 | import org.thingsboard.server.dao.tenant.TenantDao; |
28 | 29 | |
29 | 30 | import java.util.List; |
... | ... | @@ -36,7 +37,7 @@ import static org.thingsboard.server.dao.model.ModelConstants.TENANT_COLUMN_FAMI |
36 | 37 | */ |
37 | 38 | @Component |
38 | 39 | @ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false) |
39 | -public class JpaTenantDao extends JpaAbstractDao<TenantEntity, Tenant> implements TenantDao { | |
40 | +public class JpaTenantDao extends JpaAbstractSearchTextDao<TenantEntity, Tenant> implements TenantDao { | |
40 | 41 | |
41 | 42 | @Autowired |
42 | 43 | private TenantRepository tenantRepository; |
... | ... | @@ -57,11 +58,6 @@ public class JpaTenantDao extends JpaAbstractDao<TenantEntity, Tenant> implement |
57 | 58 | } |
58 | 59 | |
59 | 60 | @Override |
60 | - protected boolean isSearchTextDao() { | |
61 | - return true; | |
62 | - } | |
63 | - | |
64 | - @Override | |
65 | 61 | public List<Tenant> findTenantsByRegion(String region, TextPageLink pageLink) { |
66 | 62 | if (pageLink.getIdOffset() == null) { |
67 | 63 | return DaoUtil.convertDataList(tenantRepository.findByRegionFirstPage(pageLink.getLimit(), region, pageLink.getTextSearch())); | ... | ... |
... | ... | @@ -24,6 +24,7 @@ import org.thingsboard.server.common.data.widget.WidgetsBundle; |
24 | 24 | import org.thingsboard.server.dao.DaoUtil; |
25 | 25 | import org.thingsboard.server.dao.model.sql.WidgetsBundleEntity; |
26 | 26 | import org.thingsboard.server.dao.sql.JpaAbstractDao; |
27 | +import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao; | |
27 | 28 | import org.thingsboard.server.dao.widget.WidgetsBundleDao; |
28 | 29 | |
29 | 30 | import java.util.List; |
... | ... | @@ -36,7 +37,7 @@ import static org.thingsboard.server.dao.model.ModelConstants.WIDGETS_BUNDLE_COL |
36 | 37 | */ |
37 | 38 | @Component |
38 | 39 | @ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false) |
39 | -public class JpaWidgetsBundleDao extends JpaAbstractDao<WidgetsBundleEntity, WidgetsBundle> implements WidgetsBundleDao { | |
40 | +public class JpaWidgetsBundleDao extends JpaAbstractSearchTextDao<WidgetsBundleEntity, WidgetsBundle> implements WidgetsBundleDao { | |
40 | 41 | |
41 | 42 | @Autowired |
42 | 43 | private WidgetsBundleRepository widgetsBundleRepository; |
... | ... | @@ -61,10 +62,6 @@ public class JpaWidgetsBundleDao extends JpaAbstractDao<WidgetsBundleEntity, Wid |
61 | 62 | return DaoUtil.getData(widgetsBundleRepository.findWidgetsBundleByTenantIdAndAlias(tenantId, alias)); |
62 | 63 | } |
63 | 64 | |
64 | - @Override | |
65 | - protected boolean isSearchTextDao() { | |
66 | - return true; | |
67 | - } | |
68 | 65 | |
69 | 66 | @Override |
70 | 67 | public List<WidgetsBundle> findSystemWidgetsBundles(TextPageLink pageLink) { | ... | ... |
1 | +package org.thingsboard.server.dao.sql.event; | |
2 | + | |
3 | +import ch.qos.logback.core.net.SyslogOutputStream; | |
4 | +import com.datastax.driver.core.utils.UUIDs; | |
5 | +import com.fasterxml.jackson.databind.JsonNode; | |
6 | +import com.fasterxml.jackson.databind.ObjectMapper; | |
7 | +import com.github.springtestdbunit.annotation.DatabaseSetup; | |
8 | +import lombok.extern.slf4j.Slf4j; | |
9 | +import org.junit.Test; | |
10 | +import org.springframework.beans.factory.annotation.Autowired; | |
11 | +import org.thingsboard.server.common.data.Event; | |
12 | +import org.thingsboard.server.common.data.id.DeviceId; | |
13 | +import org.thingsboard.server.common.data.id.EntityId; | |
14 | +import org.thingsboard.server.common.data.id.EventId; | |
15 | +import org.thingsboard.server.common.data.id.TenantId; | |
16 | +import org.thingsboard.server.common.data.page.TimePageLink; | |
17 | +import org.thingsboard.server.dao.AbstractJpaDaoTest; | |
18 | +import org.thingsboard.server.dao.event.EventDao; | |
19 | + | |
20 | +import java.io.IOException; | |
21 | +import java.text.SimpleDateFormat; | |
22 | +import java.util.Date; | |
23 | +import java.util.List; | |
24 | +import java.util.Optional; | |
25 | +import java.util.UUID; | |
26 | + | |
27 | +import static org.junit.Assert.*; | |
28 | +import static org.thingsboard.server.common.data.DataConstants.STATS; | |
29 | + | |
30 | +/** | |
31 | + * Created by Valerii Sosliuk on 5/5/2017. | |
32 | + */ | |
33 | +@Slf4j | |
34 | +public class JpaBaseEventDaoTest extends AbstractJpaDaoTest { | |
35 | + | |
36 | + public static final long HOUR_MILLISECONDS = (long) 3.6e+6; | |
37 | + @Autowired | |
38 | + private EventDao eventDao; | |
39 | + | |
40 | + @Test | |
41 | + @DatabaseSetup("classpath:dbunit/empty_dataset.xml") | |
42 | + public void testSaveIfNotExists() { | |
43 | + UUID eventId = UUIDs.timeBased(); | |
44 | + UUID tenantId = UUIDs.timeBased(); | |
45 | + UUID entityId = UUIDs.timeBased(); | |
46 | + Event event = getEvent(eventId, tenantId, entityId); | |
47 | + Optional<Event> optEvent1 = eventDao.saveIfNotExists(event); | |
48 | + assertTrue("Optional is expected to be non-empty", optEvent1.isPresent()); | |
49 | + assertEquals(optEvent1.get(), event); | |
50 | + Optional<Event> optEvent2 = eventDao.saveIfNotExists(event); | |
51 | + assertFalse("Optional is expected to be empty", optEvent2.isPresent()); | |
52 | + } | |
53 | + | |
54 | + @Test | |
55 | + @DatabaseSetup("classpath:dbunit/events.xml") | |
56 | + public void findEvent() { | |
57 | + UUID tenantId = UUID.fromString("be41c7a0-31f5-11e7-9cfd-2786e6aa2046"); | |
58 | + UUID entityId = UUID.fromString("be41c7a1-31f5-11e7-9cfd-2786e6aa2046"); | |
59 | + String eventType = STATS; | |
60 | + String eventUid = "be41c7a3-31f5-11e7-9cfd-2786e6aa2046"; | |
61 | + Event event = eventDao.findEvent(tenantId, new DeviceId(entityId), eventType, eventUid); | |
62 | + assertNotNull("Event expected to be not null", event); | |
63 | + assertEquals("be41c7a2-31f5-11e7-9cfd-2786e6aa2046", event.getId().getId().toString()); | |
64 | + } | |
65 | + | |
66 | + @Test | |
67 | + @DatabaseSetup("classpath:dbunit/empty_dataset.xml") | |
68 | + public void findEventsByEntityIdAndPageLink() { | |
69 | + UUID tenantId = UUIDs.timeBased(); | |
70 | + UUID entityId1 = UUIDs.timeBased(); | |
71 | + UUID entityId2 = UUIDs.timeBased(); | |
72 | + long startTime = System.currentTimeMillis(); | |
73 | + long endTime = createEventsTwoEntities(tenantId, entityId1, entityId2, startTime, 20); | |
74 | + List<Event> allEvents = eventDao.find(); | |
75 | + | |
76 | + assertEquals(20, allEvents.size()); | |
77 | + | |
78 | + TimePageLink pageLink1 = new TimePageLink(30, null, null, true); | |
79 | + List<Event> events1 = eventDao.findEvents(tenantId, new DeviceId(entityId1), pageLink1); | |
80 | + assertEquals(10, events1.size()); | |
81 | + | |
82 | + TimePageLink pageLink2 = new TimePageLink(30, startTime, null, true); | |
83 | + List<Event> events2 = eventDao.findEvents(tenantId, new DeviceId(entityId1), pageLink2); | |
84 | + assertEquals(10, events2.size()); | |
85 | + | |
86 | + TimePageLink pageLink3 = new TimePageLink(30, startTime, endTime, true); | |
87 | + List<Event> events3 = eventDao.findEvents(tenantId, new DeviceId(entityId1), pageLink3); | |
88 | + assertEquals(10, events3.size()); | |
89 | + | |
90 | + TimePageLink pageLink4 = new TimePageLink(5, startTime, endTime, true); | |
91 | + List<Event> events4 = eventDao.findEvents(tenantId, new DeviceId(entityId1), pageLink4); | |
92 | + assertEquals(5, events4.size()); | |
93 | + | |
94 | + UUID idOffset = events4.get(4).getId().getId(); | |
95 | + TimePageLink pageLink5 = new TimePageLink(10, startTime, endTime, true, idOffset); | |
96 | + List<Event> events5 = eventDao.findEvents(tenantId, new DeviceId(entityId1), pageLink5); | |
97 | + assertEquals(5, events5.size()); | |
98 | + | |
99 | + } | |
100 | + | |
101 | + private long createEventsTwoEntities(UUID tenantId, UUID entityId1, UUID entityId2, long startTime, int count) { | |
102 | + // Generate #count events for two entities with timestamps from an hour ago till now | |
103 | + | |
104 | + // Distribute events uniformly | |
105 | + long step = HOUR_MILLISECONDS / count; | |
106 | + long timestamp = startTime; | |
107 | + for (int i = 0; i < count / 2; i++) { | |
108 | + //UUID eventId1 = UUIDs.startOf(timestamp); | |
109 | + UUID eventId1 = UUIDs.timeBased(); | |
110 | + Event event1 = getEvent(eventId1, tenantId, entityId1); | |
111 | + eventDao.save(event1); | |
112 | + timestamp += step; | |
113 | + //UUID eventId2 = UUIDs.startOf(timestamp); | |
114 | + UUID eventId2 = UUIDs.timeBased(); | |
115 | + Event event2 = getEvent(eventId2, tenantId, entityId2); | |
116 | + eventDao.save(event2); | |
117 | + timestamp += step; | |
118 | + } | |
119 | + return System.currentTimeMillis(); | |
120 | + } | |
121 | + | |
122 | + @Test | |
123 | + @DatabaseSetup("classpath:dbunit/empty_dataset.xml") | |
124 | + public void findEventsByEntityIdAndEventTypeAndPageLink() { | |
125 | + | |
126 | + } | |
127 | + | |
128 | + private Event getEvent(UUID eventId, UUID tenantId, UUID entityId) { | |
129 | + Event event = new Event(); | |
130 | + event.setId(new EventId(eventId)); | |
131 | + event.setTenantId(new TenantId(tenantId)); | |
132 | + EntityId deviceId = new DeviceId(entityId); | |
133 | + event.setEntityId(deviceId); | |
134 | + event.setUid(entityId.toString()); | |
135 | + event.setType(STATS); | |
136 | + ObjectMapper mapper = new ObjectMapper(); | |
137 | + try { | |
138 | + JsonNode jsonNode = mapper.readTree("{\"key\":\"value\"}"); | |
139 | + event.setBody(jsonNode); | |
140 | + } catch (IOException e) { | |
141 | + log.error(e.getMessage(), e); | |
142 | + } | |
143 | + return event; | |
144 | + } | |
145 | +} | ... | ... |
dao/src/test/resources/dbunit/events.xml
0 → 100644
1 | +<dataset> | |
2 | + <event | |
3 | + id="uuid'be41c7a2-31f5-11e7-9cfd-2786e6aa2046'" | |
4 | + tenant_id="uuid'be41c7a0-31f5-11e7-9cfd-2786e6aa2046'" | |
5 | + entity_id="uuid'be41c7a1-31f5-11e7-9cfd-2786e6aa2046'" | |
6 | + entity_type="1" | |
7 | + event_type="STATS" | |
8 | + event_uid="be41c7a3-31f5-11e7-9cfd-2786e6aa2046" | |
9 | + /> | |
10 | + <event | |
11 | + id="uuid'be41c7a4-31f5-11e7-9cfd-2786e6aa2046'" | |
12 | + tenant_id="uuid'be41c7a0-31f5-11e7-9cfd-2786e6aa2046'" | |
13 | + entity_id="uuid'be41c7a1-31f5-11e7-9cfd-2786e6aa2046'" | |
14 | + entity_type="1" | |
15 | + event_type="STATS" | |
16 | + event_uid="be41c7a5-31f5-11e7-9cfd-2786e6aa2046" | |
17 | + /> | |
18 | +</dataset> | |
\ No newline at end of file | ... | ... |