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,7 +142,7 @@ public class CassandraBaseEventDao extends CassandraAbstractSearchTimeDao<EventE | ||
142 | .value(ModelConstants.EVENT_ENTITY_TYPE_PROPERTY, entity.getEntityType()) | 142 | .value(ModelConstants.EVENT_ENTITY_TYPE_PROPERTY, entity.getEntityType()) |
143 | .value(ModelConstants.EVENT_ENTITY_ID_PROPERTY, entity.getEntityId()) | 143 | .value(ModelConstants.EVENT_ENTITY_ID_PROPERTY, entity.getEntityId()) |
144 | .value(ModelConstants.EVENT_TYPE_PROPERTY, entity.getEventType()) | 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 | .value(ModelConstants.EVENT_BODY_PROPERTY, entity.getBody()); | 146 | .value(ModelConstants.EVENT_BODY_PROPERTY, entity.getBody()); |
147 | if (ifNotExists) { | 147 | if (ifNotExists) { |
148 | insert = insert.ifNotExists(); | 148 | insert = insert.ifNotExists(); |
@@ -36,7 +36,7 @@ import java.util.UUID; | @@ -36,7 +36,7 @@ import java.util.UUID; | ||
36 | */ | 36 | */ |
37 | @Data | 37 | @Data |
38 | @NoArgsConstructor | 38 | @NoArgsConstructor |
39 | -@Table(name = DEVICE_COLUMN_FAMILY_NAME) | 39 | +@Table(name = EVENT_COLUMN_FAMILY_NAME) |
40 | public class EventEntity implements BaseEntity<Event> { | 40 | public class EventEntity implements BaseEntity<Event> { |
41 | 41 | ||
42 | @Transient | 42 | @Transient |
@@ -63,7 +63,7 @@ public class EventEntity implements BaseEntity<Event> { | @@ -63,7 +63,7 @@ public class EventEntity implements BaseEntity<Event> { | ||
63 | 63 | ||
64 | @ClusteringColumn(value = 1) | 64 | @ClusteringColumn(value = 1) |
65 | @Column(name = EVENT_UID_PROPERTY) | 65 | @Column(name = EVENT_UID_PROPERTY) |
66 | - private String eventUId; | 66 | + private String eventUid; |
67 | 67 | ||
68 | @Column(name = EVENT_BODY_PROPERTY, codec = JsonCodec.class) | 68 | @Column(name = EVENT_BODY_PROPERTY, codec = JsonCodec.class) |
69 | private JsonNode body; | 69 | private JsonNode body; |
@@ -80,7 +80,7 @@ public class EventEntity implements BaseEntity<Event> { | @@ -80,7 +80,7 @@ public class EventEntity implements BaseEntity<Event> { | ||
80 | this.entityId = event.getEntityId().getId(); | 80 | this.entityId = event.getEntityId().getId(); |
81 | } | 81 | } |
82 | this.eventType = event.getType(); | 82 | this.eventType = event.getType(); |
83 | - this.eventUId = event.getUid(); | 83 | + this.eventUid = event.getUid(); |
84 | this.body = event.getBody(); | 84 | this.body = event.getBody(); |
85 | } | 85 | } |
86 | 86 | ||
@@ -118,7 +118,7 @@ public class EventEntity implements BaseEntity<Event> { | @@ -118,7 +118,7 @@ public class EventEntity implements BaseEntity<Event> { | ||
118 | } | 118 | } |
119 | event.setBody(body); | 119 | event.setBody(body); |
120 | event.setType(eventType); | 120 | event.setType(eventType); |
121 | - event.setUid(eventUId); | 121 | + event.setUid(eventUid); |
122 | return event; | 122 | return event; |
123 | } | 123 | } |
124 | } | 124 | } |
@@ -22,46 +22,51 @@ import javax.persistence.Id; | @@ -22,46 +22,51 @@ import javax.persistence.Id; | ||
22 | import javax.persistence.Table; | 22 | import javax.persistence.Table; |
23 | import javax.persistence.Transient; | 23 | import javax.persistence.Transient; |
24 | import com.fasterxml.jackson.databind.JsonNode; | 24 | import com.fasterxml.jackson.databind.JsonNode; |
25 | +import com.fasterxml.jackson.databind.ObjectMapper; | ||
25 | import lombok.Data; | 26 | import lombok.Data; |
26 | import lombok.NoArgsConstructor; | 27 | import lombok.NoArgsConstructor; |
28 | +import lombok.extern.slf4j.Slf4j; | ||
27 | import org.thingsboard.server.common.data.EntityType; | 29 | import org.thingsboard.server.common.data.EntityType; |
28 | import org.thingsboard.server.common.data.Event; | 30 | import org.thingsboard.server.common.data.Event; |
29 | import org.thingsboard.server.common.data.id.*; | 31 | import org.thingsboard.server.common.data.id.*; |
30 | import org.thingsboard.server.dao.model.BaseEntity; | 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 | import java.util.UUID; | 37 | import java.util.UUID; |
34 | 38 | ||
35 | @Data | 39 | @Data |
40 | +@Slf4j | ||
36 | @NoArgsConstructor | 41 | @NoArgsConstructor |
37 | -//@Entity | ||
38 | -@Table(name = ModelConstants.DEVICE_COLUMN_FAMILY_NAME) | 42 | +@Entity |
43 | +@Table(name = EVENT_COLUMN_FAMILY_NAME) | ||
39 | public class EventEntity implements BaseEntity<Event> { | 44 | public class EventEntity implements BaseEntity<Event> { |
40 | 45 | ||
41 | @Transient | 46 | @Transient |
42 | private static final long serialVersionUID = -5717830061727466727L; | 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 | private UUID id; | 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 | private UUID tenantId; | 54 | private UUID tenantId; |
50 | 55 | ||
51 | - @Column(name = ModelConstants.EVENT_ENTITY_TYPE_PROPERTY) | 56 | + @Column(name = EVENT_ENTITY_TYPE_PROPERTY) |
52 | private EntityType entityType; | 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 | private UUID entityId; | 60 | private UUID entityId; |
56 | 61 | ||
57 | - @Column(name = ModelConstants.EVENT_TYPE_PROPERTY) | 62 | + @Column(name = EVENT_TYPE_PROPERTY) |
58 | private String eventType; | 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 | public EventEntity(Event event) { | 71 | public EventEntity(Event event) { |
67 | if (event.getId() != null) { | 72 | if (event.getId() != null) { |
@@ -75,8 +80,10 @@ public class EventEntity implements BaseEntity<Event> { | @@ -75,8 +80,10 @@ public class EventEntity implements BaseEntity<Event> { | ||
75 | this.entityId = event.getEntityId().getId(); | 80 | this.entityId = event.getEntityId().getId(); |
76 | } | 81 | } |
77 | this.eventType = event.getType(); | 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 | @Override | 89 | @Override |
@@ -111,9 +118,17 @@ public class EventEntity implements BaseEntity<Event> { | @@ -111,9 +118,17 @@ public class EventEntity implements BaseEntity<Event> { | ||
111 | event.setEntityId(new PluginId(entityId)); | 118 | event.setEntityId(new PluginId(entityId)); |
112 | break; | 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 | event.setType(eventType); | 130 | event.setType(eventType); |
116 | - event.setUid(eventUId); | 131 | + event.setUid(eventUid); |
117 | return event; | 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,6 +29,7 @@ import org.thingsboard.server.dao.model.ModelConstants; | ||
29 | import org.thingsboard.server.dao.model.sql.PluginMetaDataEntity; | 29 | import org.thingsboard.server.dao.model.sql.PluginMetaDataEntity; |
30 | import org.thingsboard.server.dao.plugin.PluginDao; | 30 | import org.thingsboard.server.dao.plugin.PluginDao; |
31 | import org.thingsboard.server.dao.sql.JpaAbstractDao; | 31 | import org.thingsboard.server.dao.sql.JpaAbstractDao; |
32 | +import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao; | ||
32 | 33 | ||
33 | import java.util.Arrays; | 34 | import java.util.Arrays; |
34 | import java.util.List; | 35 | import java.util.List; |
@@ -40,7 +41,7 @@ import java.util.UUID; | @@ -40,7 +41,7 @@ import java.util.UUID; | ||
40 | @Slf4j | 41 | @Slf4j |
41 | @Component | 42 | @Component |
42 | @ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false) | 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 | @Autowired | 46 | @Autowired |
46 | private PluginMetaDataRepository pluginMetaDataRepository; | 47 | private PluginMetaDataRepository pluginMetaDataRepository; |
@@ -61,11 +62,6 @@ public class JpaBasePluginDao extends JpaAbstractDao<PluginMetaDataEntity, Plugi | @@ -61,11 +62,6 @@ public class JpaBasePluginDao extends JpaAbstractDao<PluginMetaDataEntity, Plugi | ||
61 | } | 62 | } |
62 | 63 | ||
63 | @Override | 64 | @Override |
64 | - protected boolean isSearchTextDao() { | ||
65 | - return true; | ||
66 | - } | ||
67 | - | ||
68 | - @Override | ||
69 | public PluginMetaData findById(PluginId pluginId) { | 65 | public PluginMetaData findById(PluginId pluginId) { |
70 | log.debug("Search plugin meta-data entity by id [{}]", pluginId); | 66 | log.debug("Search plugin meta-data entity by id [{}]", pluginId); |
71 | PluginMetaData pluginMetaData = super.findById(pluginId.getId()); | 67 | PluginMetaData pluginMetaData = super.findById(pluginId.getId()); |
@@ -29,6 +29,7 @@ import org.thingsboard.server.dao.model.ModelConstants; | @@ -29,6 +29,7 @@ import org.thingsboard.server.dao.model.ModelConstants; | ||
29 | import org.thingsboard.server.dao.model.sql.RuleMetaDataEntity; | 29 | import org.thingsboard.server.dao.model.sql.RuleMetaDataEntity; |
30 | import org.thingsboard.server.dao.rule.RuleDao; | 30 | import org.thingsboard.server.dao.rule.RuleDao; |
31 | import org.thingsboard.server.dao.sql.JpaAbstractDao; | 31 | import org.thingsboard.server.dao.sql.JpaAbstractDao; |
32 | +import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao; | ||
32 | 33 | ||
33 | import java.util.Arrays; | 34 | import java.util.Arrays; |
34 | import java.util.List; | 35 | import java.util.List; |
@@ -40,7 +41,7 @@ import java.util.UUID; | @@ -40,7 +41,7 @@ import java.util.UUID; | ||
40 | @Slf4j | 41 | @Slf4j |
41 | @Component | 42 | @Component |
42 | @ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false) | 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 | @Autowired | 46 | @Autowired |
46 | private RuleMetaDataRepository ruleMetaDataRepository; | 47 | private RuleMetaDataRepository ruleMetaDataRepository; |
@@ -60,11 +61,6 @@ public class JpaBaseRuleDao extends JpaAbstractDao<RuleMetaDataEntity, RuleMetaD | @@ -60,11 +61,6 @@ public class JpaBaseRuleDao extends JpaAbstractDao<RuleMetaDataEntity, RuleMetaD | ||
60 | } | 61 | } |
61 | 62 | ||
62 | @Override | 63 | @Override |
63 | - protected boolean isSearchTextDao() { | ||
64 | - return true; | ||
65 | - } | ||
66 | - | ||
67 | - @Override | ||
68 | public RuleMetaData findById(RuleId ruleId) { | 64 | public RuleMetaData findById(RuleId ruleId) { |
69 | return findById(ruleId.getId()); | 65 | return findById(ruleId.getId()); |
70 | } | 66 | } |
@@ -24,6 +24,7 @@ import org.thingsboard.server.common.data.page.TextPageLink; | @@ -24,6 +24,7 @@ import org.thingsboard.server.common.data.page.TextPageLink; | ||
24 | import org.thingsboard.server.dao.DaoUtil; | 24 | import org.thingsboard.server.dao.DaoUtil; |
25 | import org.thingsboard.server.dao.model.sql.TenantEntity; | 25 | import org.thingsboard.server.dao.model.sql.TenantEntity; |
26 | import org.thingsboard.server.dao.sql.JpaAbstractDao; | 26 | import org.thingsboard.server.dao.sql.JpaAbstractDao; |
27 | +import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao; | ||
27 | import org.thingsboard.server.dao.tenant.TenantDao; | 28 | import org.thingsboard.server.dao.tenant.TenantDao; |
28 | 29 | ||
29 | import java.util.List; | 30 | import java.util.List; |
@@ -36,7 +37,7 @@ import static org.thingsboard.server.dao.model.ModelConstants.TENANT_COLUMN_FAMI | @@ -36,7 +37,7 @@ import static org.thingsboard.server.dao.model.ModelConstants.TENANT_COLUMN_FAMI | ||
36 | */ | 37 | */ |
37 | @Component | 38 | @Component |
38 | @ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false) | 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 | @Autowired | 42 | @Autowired |
42 | private TenantRepository tenantRepository; | 43 | private TenantRepository tenantRepository; |
@@ -57,11 +58,6 @@ public class JpaTenantDao extends JpaAbstractDao<TenantEntity, Tenant> implement | @@ -57,11 +58,6 @@ public class JpaTenantDao extends JpaAbstractDao<TenantEntity, Tenant> implement | ||
57 | } | 58 | } |
58 | 59 | ||
59 | @Override | 60 | @Override |
60 | - protected boolean isSearchTextDao() { | ||
61 | - return true; | ||
62 | - } | ||
63 | - | ||
64 | - @Override | ||
65 | public List<Tenant> findTenantsByRegion(String region, TextPageLink pageLink) { | 61 | public List<Tenant> findTenantsByRegion(String region, TextPageLink pageLink) { |
66 | if (pageLink.getIdOffset() == null) { | 62 | if (pageLink.getIdOffset() == null) { |
67 | return DaoUtil.convertDataList(tenantRepository.findByRegionFirstPage(pageLink.getLimit(), region, pageLink.getTextSearch())); | 63 | return DaoUtil.convertDataList(tenantRepository.findByRegionFirstPage(pageLink.getLimit(), region, pageLink.getTextSearch())); |
@@ -24,6 +24,7 @@ import org.thingsboard.server.common.data.widget.WidgetsBundle; | @@ -24,6 +24,7 @@ import org.thingsboard.server.common.data.widget.WidgetsBundle; | ||
24 | import org.thingsboard.server.dao.DaoUtil; | 24 | import org.thingsboard.server.dao.DaoUtil; |
25 | import org.thingsboard.server.dao.model.sql.WidgetsBundleEntity; | 25 | import org.thingsboard.server.dao.model.sql.WidgetsBundleEntity; |
26 | import org.thingsboard.server.dao.sql.JpaAbstractDao; | 26 | import org.thingsboard.server.dao.sql.JpaAbstractDao; |
27 | +import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao; | ||
27 | import org.thingsboard.server.dao.widget.WidgetsBundleDao; | 28 | import org.thingsboard.server.dao.widget.WidgetsBundleDao; |
28 | 29 | ||
29 | import java.util.List; | 30 | import java.util.List; |
@@ -36,7 +37,7 @@ import static org.thingsboard.server.dao.model.ModelConstants.WIDGETS_BUNDLE_COL | @@ -36,7 +37,7 @@ import static org.thingsboard.server.dao.model.ModelConstants.WIDGETS_BUNDLE_COL | ||
36 | */ | 37 | */ |
37 | @Component | 38 | @Component |
38 | @ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false) | 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 | @Autowired | 42 | @Autowired |
42 | private WidgetsBundleRepository widgetsBundleRepository; | 43 | private WidgetsBundleRepository widgetsBundleRepository; |
@@ -61,10 +62,6 @@ public class JpaWidgetsBundleDao extends JpaAbstractDao<WidgetsBundleEntity, Wid | @@ -61,10 +62,6 @@ public class JpaWidgetsBundleDao extends JpaAbstractDao<WidgetsBundleEntity, Wid | ||
61 | return DaoUtil.getData(widgetsBundleRepository.findWidgetsBundleByTenantIdAndAlias(tenantId, alias)); | 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 | @Override | 66 | @Override |
70 | public List<WidgetsBundle> findSystemWidgetsBundles(TextPageLink pageLink) { | 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> |