thingsboard-developers

Configured tests to run against postgresql. JpaDeviceCredentialsDao

5/6/2017 10:26:20 PM

Changes

dao/pom.xml 4(+4 -0)

pom.xml 6(+6 -0)

Details

dao/pom.xml 4(+4 -0)

diff --git a/dao/pom.xml b/dao/pom.xml
index fddc440..d95521d 100644
--- a/dao/pom.xml
+++ b/dao/pom.xml
@@ -57,6 +57,10 @@
             <artifactId>logback-classic</artifactId>
         </dependency>
         <dependency>
+            <groupId>org.postgresql</groupId>
+            <artifactId>postgresql</artifactId>
+        </dependency>
+        <dependency>
             <groupId>org.springframework</groupId>
             <artifactId>spring-test</artifactId>
         </dependency>
diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java
index 584beed..b721780 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java
@@ -45,6 +45,7 @@ public class ModelConstants {
      * Cassandra user constants.
      */
     public static final String USER_COLUMN_FAMILY_NAME = "user";
+    public static final String USER_PG_HIBERNATE_COLUMN_FAMILY_NAME = "tb_user";
     public static final String USER_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY;
     public static final String USER_CUSTOMER_ID_PROPERTY = CUSTOMER_ID_PROPERTY;
     public static final String USER_EMAIL_PROPERTY = "email";
diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceCredentialsEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceCredentialsEntity.java
index 56ebc43..b55b9b3 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceCredentialsEntity.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceCredentialsEntity.java
@@ -21,6 +21,8 @@ import javax.persistence.Entity;
 import javax.persistence.Id;
 import javax.persistence.Table;
 import javax.persistence.Transient;
+
+import lombok.Data;
 import org.thingsboard.server.common.data.id.DeviceCredentialsId;
 import org.thingsboard.server.common.data.id.DeviceId;
 import org.thingsboard.server.common.data.security.DeviceCredentials;
@@ -30,7 +32,8 @@ import org.thingsboard.server.dao.model.ModelConstants;
 
 import java.util.UUID;
 
-//@Entity
+@Data
+@Entity
 @Table(name = ModelConstants.DEVICE_CREDENTIALS_COLUMN_FAMILY_NAME)
 public final class DeviceCredentialsEntity implements BaseEntity<DeviceCredentials> {
 
@@ -68,46 +71,6 @@ public final class DeviceCredentialsEntity implements BaseEntity<DeviceCredentia
         this.credentialsValue = deviceCredentials.getCredentialsValue(); 
     }
     
-    public UUID getId() {
-        return id;
-    }
-
-    public void setId(UUID id) {
-        this.id = id;
-    }
-
-    public UUID getDeviceId() {
-        return deviceId;
-    }
-
-    public void setDeviceId(UUID deviceId) {
-        this.deviceId = deviceId;
-    }
-
-    public DeviceCredentialsType getCredentialsType() {
-        return credentialsType;
-    }
-
-    public void setCredentialsType(DeviceCredentialsType credentialsType) {
-        this.credentialsType = credentialsType;
-    }
-
-    public String getCredentialsId() {
-        return credentialsId;
-    }
-
-    public void setCredentialsId(String credentialsId) {
-        this.credentialsId = credentialsId;
-    }
-
-    public String getCredentialsValue() {
-        return credentialsValue;
-    }
-
-    public void setCredentialsValue(String credentialsValue) {
-        this.credentialsValue = credentialsValue;
-    }
-
     @Override
     public int hashCode() {
         final int prime = 31;
diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceEntity.java
index 4cab621..0b1ecdf 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceEntity.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceEntity.java
@@ -22,6 +22,9 @@ import javax.persistence.Id;
 import javax.persistence.Table;
 import javax.persistence.Transient;
 import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
 import org.thingsboard.server.common.data.Device;
 import org.thingsboard.server.common.data.id.CustomerId;
 import org.thingsboard.server.common.data.id.DeviceId;
@@ -29,9 +32,12 @@ import org.thingsboard.server.common.data.id.TenantId;
 import org.thingsboard.server.dao.model.ModelConstants;
 import org.thingsboard.server.dao.model.SearchTextEntity;
 
+import java.io.IOException;
 import java.util.UUID;
 
-//@Entity
+@Data
+@Slf4j
+@Entity
 @Table(name = ModelConstants.DEVICE_COLUMN_FAMILY_NAME)
 public final class DeviceEntity implements SearchTextEntity<Device> {
 
@@ -55,7 +61,7 @@ public final class DeviceEntity implements SearchTextEntity<Device> {
     private String searchText;
     
     @Column(name = ModelConstants.DEVICE_ADDITIONAL_INFO_PROPERTY)
-    private JsonNode additionalInfo;
+    private String additionalInfo;
 
     public DeviceEntity() {
         super();
@@ -72,49 +78,11 @@ public final class DeviceEntity implements SearchTextEntity<Device> {
             this.customerId = device.getCustomerId().getId();
         }
         this.name = device.getName();
-        this.additionalInfo = device.getAdditionalInfo();
-    }
-    
-    public UUID getId() {
-        return id;
-    }
-
-    public void setId(UUID id) {
-        this.id = id;
-    }
-
-    public UUID getTenantId() {
-        return tenantId;
-    }
-
-    public void setTenantId(UUID tenantId) {
-        this.tenantId = tenantId;
-    }
-
-    public UUID getCustomerId() {
-        return customerId;
-    }
-
-    public void setCustomerId(UUID customerId) {
-        this.customerId = customerId;
-    }
-    
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public JsonNode getAdditionalInfo() {
-        return additionalInfo;
+        if (additionalInfo != null) {
+            this.additionalInfo = device.getAdditionalInfo().toString();
+        }
     }
 
-    public void setAdditionalInfo(JsonNode additionalInfo) {
-        this.additionalInfo = additionalInfo;
-    }
-    
     @Override
     public String getSearchTextSource() {
         return name;
@@ -206,8 +174,16 @@ public final class DeviceEntity implements SearchTextEntity<Device> {
             device.setCustomerId(new CustomerId(customerId));
         }
         device.setName(name);
-        device.setAdditionalInfo(additionalInfo);
+        if (additionalInfo != null) {
+            ObjectMapper mapper = new ObjectMapper();
+            JsonNode jsonNode = null;
+            try {
+                jsonNode = mapper.readTree(additionalInfo);
+                device.setAdditionalInfo(jsonNode);
+            } catch (IOException e) {
+                log.error(e.getMessage(), e);
+            }
+        }
         return device;
     }
-
 }
\ No newline at end of file
diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/EventEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/EventEntity.java
index 9bfa663..a0cce5c 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/EventEntity.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/EventEntity.java
@@ -47,16 +47,16 @@ public class EventEntity implements BaseEntity<Event> {
     private static final long serialVersionUID = -5717830061727466727L;
 
     @Id
-    @Column(name = ID_PROPERTY, columnDefinition = "BINARY(16)")
+    @Column(name = ID_PROPERTY)
     private UUID id;
 
-    @Column(name = EVENT_TENANT_ID_PROPERTY, columnDefinition = "BINARY(16)")
+    @Column(name = EVENT_TENANT_ID_PROPERTY)
     private UUID tenantId;
 
     @Column(name = EVENT_ENTITY_TYPE_PROPERTY)
     private EntityType entityType;
 
-    @Column(name = EVENT_ENTITY_ID_PROPERTY, columnDefinition = "BINARY(16)")
+    @Column(name = EVENT_ENTITY_ID_PROPERTY)
     private UUID entityId;
 
     @Column(name = EVENT_TYPE_PROPERTY)
diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/PluginMetaDataEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/PluginMetaDataEntity.java
index 46f1e32..1e5d1b0 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/PluginMetaDataEntity.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/PluginMetaDataEntity.java
@@ -44,13 +44,13 @@ public class PluginMetaDataEntity implements SearchTextEntity<PluginMetaData> {
     @Transient
     private static final long serialVersionUID = -6164321050824823149L;
     @Id
-    @Column(name = ModelConstants.ID_PROPERTY, columnDefinition = "BINARY(16)")
+    @Column(name = ModelConstants.ID_PROPERTY)
     private UUID id;
 
     @Column(name = ModelConstants.PLUGIN_API_TOKEN_PROPERTY)
     private String apiToken;
 
-    @Column(name = ModelConstants.PLUGIN_TENANT_ID_PROPERTY, columnDefinition = "BINARY(16)")
+    @Column(name = ModelConstants.PLUGIN_TENANT_ID_PROPERTY)
     private UUID tenantId;
 
     @Column(name = ModelConstants.PLUGIN_NAME_PROPERTY)
diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleMetaDataEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleMetaDataEntity.java
index 54b74b4..54359a3 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleMetaDataEntity.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleMetaDataEntity.java
@@ -48,9 +48,9 @@ public class RuleMetaDataEntity implements SearchTextEntity<RuleMetaData> {
     @Transient
     private static final long serialVersionUID = -1506905644259463884L;
     @Id
-    @Column(name = ModelConstants.ID_PROPERTY, columnDefinition = "BINARY(16)")
+    @Column(name = ModelConstants.ID_PROPERTY)
     private UUID id;
-    @Column(name = ModelConstants.RULE_TENANT_ID_PROPERTY, columnDefinition = "BINARY(16)")
+    @Column(name = ModelConstants.RULE_TENANT_ID_PROPERTY)
     private UUID tenantId;
     @Column(name = ModelConstants.RULE_NAME_PROPERTY)
     private String name;
diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/TenantEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/TenantEntity.java
index aa388d2..6a2e8a0 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/TenantEntity.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/TenantEntity.java
@@ -45,7 +45,7 @@ public final class TenantEntity implements SearchTextEntity<Tenant> {
     private static final long serialVersionUID = -4330655990232136337L;
 
     @Id
-    @Column(name = ModelConstants.ID_PROPERTY, columnDefinition = "BINARY(16)")
+    @Column(name = ModelConstants.ID_PROPERTY)
     private UUID id;
 
     @Column(name = ModelConstants.TENANT_TITLE_PROPERTY)
diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserCredentialsEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserCredentialsEntity.java
index b750ece..8e228d5 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserCredentialsEntity.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserCredentialsEntity.java
@@ -41,10 +41,10 @@ public final class UserCredentialsEntity implements BaseEntity<UserCredentials> 
     private static final long serialVersionUID = -3989724854149114846L;
 
     @Id
-    @Column(name = ModelConstants.ID_PROPERTY, columnDefinition = "BINARY(16)")
+    @Column(name = ModelConstants.ID_PROPERTY)
     private UUID id;
 
-    @Column(name = ModelConstants.USER_CREDENTIALS_USER_ID_PROPERTY, columnDefinition = "BINARY(16)", unique = true)
+    @Column(name = ModelConstants.USER_CREDENTIALS_USER_ID_PROPERTY, unique = true)
     private UUID userId;
 
     @Column(name = ModelConstants.USER_CREDENTIALS_ENABLED_PROPERTY)
diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserEntity.java
index 9df32e3..c85b2aa 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserEntity.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserEntity.java
@@ -38,19 +38,19 @@ import java.util.UUID;
 @Slf4j
 @Data
 @Entity
-@Table(name = ModelConstants.USER_COLUMN_FAMILY_NAME)
+@Table(name = ModelConstants.USER_PG_HIBERNATE_COLUMN_FAMILY_NAME)
 public class UserEntity implements SearchTextEntity<User> {
     @Transient
     private static final long serialVersionUID = -271106508790582977L;
 
     @Id
-    @Column(name = ModelConstants.ID_PROPERTY, columnDefinition = "BINARY(16)")
+    @Column(name = ModelConstants.ID_PROPERTY)
     private UUID id;
 
-    @Column(name = ModelConstants.USER_TENANT_ID_PROPERTY, columnDefinition = "BINARY(16)")
+    @Column(name = ModelConstants.USER_TENANT_ID_PROPERTY)
     private UUID tenantId;
 
-    @Column(name = ModelConstants.USER_CUSTOMER_ID_PROPERTY, columnDefinition = "BINARY(16)")
+    @Column(name = ModelConstants.USER_CUSTOMER_ID_PROPERTY)
     private UUID customerId;
 
     @Column(name = ModelConstants.USER_AUTHORITY_PROPERTY)
diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetsBundleEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetsBundleEntity.java
index 92f2e41..3e72606 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetsBundleEntity.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetsBundleEntity.java
@@ -42,10 +42,10 @@ public final class WidgetsBundleEntity implements SearchTextEntity<WidgetsBundle
     private static final long serialVersionUID = 6897035686422298096L;
 
     @Id
-    @Column(name = ModelConstants.ID_PROPERTY, columnDefinition = "BINARY(16)")
+    @Column(name = ModelConstants.ID_PROPERTY)
     private UUID id;
 
-    @Column(name = ModelConstants.WIDGETS_BUNDLE_TENANT_ID_PROPERTY, columnDefinition = "BINARY(16)")
+    @Column(name = ModelConstants.WIDGETS_BUNDLE_TENANT_ID_PROPERTY)
     private UUID tenantId;
 
     @Column(name = ModelConstants.WIDGETS_BUNDLE_ALIAS_PROPERTY)
diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetTypeEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetTypeEntity.java
index 00ff205..4f31e70 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetTypeEntity.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetTypeEntity.java
@@ -46,11 +46,11 @@ public final class WidgetTypeEntity implements BaseEntity<WidgetType> {
     private static final long serialVersionUID = -5436279069884988630L;
 
     @Id
-    @Column(name = ModelConstants.ID_PROPERTY, columnDefinition = "BINARY(16)")
+    @Column(name = ModelConstants.ID_PROPERTY)
     private UUID id;
 
     @PartitionKey(value = 1)
-    @Column(name = ModelConstants.WIDGET_TYPE_TENANT_ID_PROPERTY, columnDefinition = "BINARY(16)")
+    @Column(name = ModelConstants.WIDGET_TYPE_TENANT_ID_PROPERTY)
     private UUID tenantId;
 
     @PartitionKey(value = 2)
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceCredentialsRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceCredentialsRepository.java
new file mode 100644
index 0000000..cc0f600
--- /dev/null
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceCredentialsRepository.java
@@ -0,0 +1,19 @@
+package org.thingsboard.server.dao.sql.device;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Component;
+import org.thingsboard.server.dao.model.sql.DeviceCredentialsEntity;
+
+import java.util.UUID;
+
+/**
+ * Created by Valerii Sosliuk on 5/6/2017.
+ */
+@ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false)
+public interface DeviceCredentialsRepository extends CrudRepository<DeviceCredentialsEntity, UUID> {
+
+    DeviceCredentialsEntity findByDeviceId(UUID deviceId);
+
+    DeviceCredentialsEntity findByCredentialsId(String credentialsId);
+}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceRepository.java
new file mode 100644
index 0000000..486305b
--- /dev/null
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceRepository.java
@@ -0,0 +1,47 @@
+package org.thingsboard.server.dao.sql.device;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.util.concurrent.ListenableFuture;
+import org.thingsboard.server.dao.model.sql.DeviceEntity;
+
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * Created by Valerii Sosliuk on 5/6/2017.
+ */
+@ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false)
+public interface DeviceRepository extends CrudRepository<DeviceEntity, UUID> {
+
+    @Query(nativeQuery = true, value = "SELECT * FROM DEVICE WHERE TENANT_ID = ?2 " +
+            "AND CUSTOMER_ID = ?3 " +
+            "AND LOWER(SEARCH_TEXT) LIKE LOWER(CONCAT(?4, '%')) " +
+            "ORDER BY ID LIMIT ?1")
+    List<DeviceEntity> findByTenantIdAndCustomerIdFirstPage(int limit, UUID tenantId, UUID customerId, String searchText);
+
+    @Query(nativeQuery = true, value = "SELECT * FROM DEVICE WHERE TENANT_ID = ?2 " +
+            "AND CUSTOMER_ID = ?3 " +
+            "AND LOWER(SEARCH_TEXT) LIKE LOWER(CONCAT(?4, '%')) " +
+            "AND ID > ?5 ORDER BY ID LIMIT ?1")
+    List<DeviceEntity> findByTenantIdAndCustomerIdNextPage(int limit, UUID tenantId, UUID customerId, String searchText, UUID idOffset);
+
+    @Query(nativeQuery = true, value = "SELECT * FROM DEVICE WHERE TENANT_ID = ?2 " +
+            "AND LOWER(SEARCH_TEXT) LIKE LOWER(CONCAT(?3, '%')) " +
+            "ORDER BY ID LIMIT ?1")
+    List<DeviceEntity> findByTenantIdFirstPage(int limit, UUID tenantId, String textSearch);
+
+    @Query(nativeQuery = true, value = "SELECT * FROM DEVICE WHERE TENANT_ID = ?2 " +
+            "AND LOWER(SEARCH_TEXT) LIKE LOWER(CONCAT(?3, '%')) " +
+            "AND ID > ?4 ORDER BY ID LIMIT ?1")
+    List<DeviceEntity> findByTenantIdNextPage(int limit, UUID tenantId, String textSearch, UUID idOffset);
+
+    DeviceEntity findByTenantIdAndName(UUID tenantId, String name);
+
+    List<DeviceEntity> findDevicesByTenantIdAndCustomerIdAndIdIn(UUID tenantId, UUID customerId, List<UUID> deviceIds);
+
+    List<DeviceEntity> findDevicesByTenantId(UUID tenantId);
+    List<DeviceEntity> findDevicesByTenantIdAndIdIn(UUID tenantId, List<UUID> deviceIds);
+}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceCredentialsDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceCredentialsDao.java
new file mode 100644
index 0000000..5538d96
--- /dev/null
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceCredentialsDao.java
@@ -0,0 +1,52 @@
+package org.thingsboard.server.dao.sql.device;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Component;
+import org.thingsboard.server.common.data.security.DeviceCredentials;
+import org.thingsboard.server.dao.DaoUtil;
+import org.thingsboard.server.dao.device.DeviceCredentialsDao;
+import org.thingsboard.server.dao.model.ModelConstants;
+import org.thingsboard.server.dao.model.sql.DeviceCredentialsEntity;
+import org.thingsboard.server.dao.sql.JpaAbstractDao;
+
+import java.util.UUID;
+
+/**
+ * Created by Valerii Sosliuk on 5/6/2017.
+ */
+@Component
+@ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false)
+public class JpaDeviceCredentialsDao extends JpaAbstractDao<DeviceCredentialsEntity, DeviceCredentials> implements DeviceCredentialsDao {
+
+    @Autowired
+    private DeviceCredentialsRepository deviceCredentialsRepository;
+
+    @Override
+    protected Class<DeviceCredentialsEntity> getEntityClass() {
+        return DeviceCredentialsEntity.class;
+    }
+
+    @Override
+    protected String getColumnFamilyName() {
+        {
+            return ModelConstants.DEVICE_CREDENTIALS_COLUMN_FAMILY_NAME;
+        }
+    }
+
+    @Override
+    protected CrudRepository<DeviceCredentialsEntity, UUID> getCrudRepository() {
+        return deviceCredentialsRepository;
+    }
+
+    @Override
+    public DeviceCredentials findByDeviceId(UUID deviceId) {
+        return DaoUtil.getData(deviceCredentialsRepository.findByDeviceId(deviceId));
+    }
+
+    @Override
+    public DeviceCredentials findByCredentialsId(String credentialsId) {
+        return DaoUtil.getData(deviceCredentialsRepository.findByCredentialsId(credentialsId));
+    }
+}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java
new file mode 100644
index 0000000..eefedd0
--- /dev/null
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java
@@ -0,0 +1,91 @@
+package org.thingsboard.server.dao.sql.device;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Component;
+import org.thingsboard.server.common.data.Device;
+import org.thingsboard.server.common.data.page.TextPageLink;
+import org.thingsboard.server.dao.DaoUtil;
+import org.thingsboard.server.dao.device.DeviceDao;
+import org.thingsboard.server.dao.model.sql.DeviceEntity;
+import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.UUID;
+import java.util.concurrent.Executors;
+
+import static org.thingsboard.server.dao.model.ModelConstants.DEVICE_COLUMN_FAMILY_NAME;
+
+/**
+ * Created by Valerii Sosliuk on 5/6/2017.
+ */
+@Component
+@ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false)
+public class JpaDeviceDao extends JpaAbstractSearchTextDao<DeviceEntity, Device> implements DeviceDao {
+
+    @Autowired
+    DeviceRepository deviceRepository;
+
+    @Override
+    protected Class<DeviceEntity> getEntityClass() {
+        return DeviceEntity.class;
+    }
+
+    @Override
+    protected String getColumnFamilyName() {
+        return DEVICE_COLUMN_FAMILY_NAME;
+    }
+
+    @Override
+    protected CrudRepository<DeviceEntity, UUID> getCrudRepository() {
+        return deviceRepository;
+    }
+
+    @Override
+    public List<Device> findDevicesByTenantId(UUID tenantId, TextPageLink pageLink) {
+        if (pageLink.getIdOffset() == null) {
+            return DaoUtil.convertDataList(deviceRepository.findByTenantIdFirstPage(
+                    pageLink.getLimit(), tenantId, pageLink.getTextSearch()));
+        } else {
+            return DaoUtil.convertDataList(deviceRepository.findByTenantIdNextPage(
+                    pageLink.getLimit(), tenantId, pageLink.getTextSearch(), pageLink.getIdOffset()));
+        }
+    }
+
+    @Override
+    public ListenableFuture<List<Device>> findDevicesByTenantIdAndIdsAsync(UUID tenantId, List<UUID> deviceIds) {
+        System.out.println(deviceRepository.findDevicesByTenantIdAndIdIn(tenantId, deviceIds).size());
+        ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
+        return service.submit(() -> DaoUtil.convertDataList(deviceRepository.findDevicesByTenantIdAndIdIn(tenantId, deviceIds)));
+    }
+
+    @Override
+    public List<Device> findDevicesByTenantIdAndCustomerId(UUID tenantId, UUID customerId, TextPageLink pageLink) {
+        if (pageLink.getIdOffset() == null) {
+            return DaoUtil.convertDataList(deviceRepository.findByTenantIdAndCustomerIdFirstPage(pageLink.getLimit(),
+                    tenantId, customerId, pageLink.getTextSearch()));
+        } else {
+            return DaoUtil.convertDataList(deviceRepository.findByTenantIdAndCustomerIdNextPage(pageLink.getLimit(),
+                    tenantId, customerId, pageLink.getTextSearch(), pageLink.getIdOffset()));
+        }
+    }
+
+    @Override
+    public ListenableFuture<List<Device>> findDevicesByTenantIdCustomerIdAndIdsAsync(UUID tenantId, UUID customerId, List<UUID> deviceIds) {
+        ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
+        return service.submit(() -> DaoUtil.convertDataList(
+                deviceRepository.findDevicesByTenantIdAndCustomerIdAndIdIn(tenantId, customerId, deviceIds)));
+    }
+
+    @Override
+    // Probably findDevice, not findDevices?
+    public Optional<Device> findDevicesByTenantIdAndName(UUID tenantId, String name) {
+        Device device = DaoUtil.getData(deviceRepository.findByTenantIdAndName(tenantId, name));
+        return Optional.ofNullable(device);
+    }
+}
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 8d064c3..0d04577 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
@@ -21,6 +21,7 @@ import com.google.common.util.concurrent.ListeningExecutorService;
 import com.google.common.util.concurrent.MoreExecutors;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.data.repository.CrudRepository;
+import org.springframework.transaction.annotation.Transactional;
 import org.thingsboard.server.dao.Dao;
 import org.thingsboard.server.dao.DaoUtil;
 import org.thingsboard.server.dao.model.BaseEntity;
@@ -30,6 +31,8 @@ import java.util.List;
 import java.util.UUID;
 import java.util.concurrent.Executors;
 
+import static org.springframework.transaction.annotation.Propagation.REQUIRES_NEW;
+
 /**
  * @author Valerii Sosliuk
  */
@@ -47,6 +50,7 @@ public abstract class JpaAbstractDao<E extends BaseEntity<D>, D> implements Dao<
     }
 
     @Override
+    @Transactional(propagation = REQUIRES_NEW)
     public D save(D domain) {
         E entity;
         try {
@@ -80,6 +84,7 @@ public abstract class JpaAbstractDao<E extends BaseEntity<D>, D> implements Dao<
     }
 
     @Override
+    @Transactional(propagation = REQUIRES_NEW)
     public boolean removeById(UUID key) {
         getCrudRepository().delete(key);
         log.debug("Remove request: {}", key);
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/user/UserRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/user/UserRepository.java
index de32f06..585bf38 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/sql/user/UserRepository.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/user/UserRepository.java
@@ -31,22 +31,22 @@ public interface UserRepository extends CrudRepository<UserEntity, UUID> {
 
     UserEntity findByEmail(String email);
 
-    @Query(nativeQuery = true, value = "SELECT * FROM USER WHERE TENANT_ID = ?2 " +
+    @Query(nativeQuery = true, value = "SELECT * FROM TB_USER WHERE TENANT_ID = ?2 " +
             "AND CUSTOMER_ID IS NULL AND AUTHORITY = 1 " +
             "ORDER BY ID LIMIT ?1")
     List<UserEntity> findTenantAdminsFirstPage(int limit, UUID tenantId);
 
-    @Query(nativeQuery = true, value = "SELECT * FROM USER WHERE TENANT_ID = ?2 " +
+    @Query(nativeQuery = true, value = "SELECT * FROM TB_USER WHERE TENANT_ID = ?2 " +
             "AND CUSTOMER_ID IS NULL AND AUTHORITY = 1 " +
             "AND ID > ?3 ORDER BY ID LIMIT ?1")
     List<UserEntity> findTenantAdminsNextPage(int limit, UUID tenantId, UUID idOffset);
 
-    @Query(nativeQuery = true, value = "SELECT * FROM USER WHERE TENANT_ID = ?2 " +
+    @Query(nativeQuery = true, value = "SELECT * FROM TB_USER WHERE TENANT_ID = ?2 " +
             "AND CUSTOMER_ID = ?3 AND AUTHORITY = 2 " +
             "ORDER BY ID LIMIT ?1")
     List<UserEntity> findCustomerUsersFirstPage(int limit, UUID tenantId, UUID customerId);
 
-    @Query(nativeQuery = true, value = "SELECT * FROM USER WHERE TENANT_ID = ?2 " +
+    @Query(nativeQuery = true, value = "SELECT * FROM TB_USER WHERE TENANT_ID = ?2 " +
             "AND CUSTOMER_ID = ?3 AND AUTHORITY = 2 " +
             "AND ID > ?4 ORDER BY ID LIMIT ?1")
     List<UserEntity> findCustomerUsersNextPage(int limit, UUID tenantId, UUID customerId, UUID idOffset);
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 e610245..f6b6b73 100644
--- a/dao/src/test/java/org/thingsboard/server/dao/AbstractJpaDaoTest.java
+++ b/dao/src/test/java/org/thingsboard/server/dao/AbstractJpaDaoTest.java
@@ -16,6 +16,7 @@
 package org.thingsboard.server.dao;
 
 import com.github.springtestdbunit.DbUnitTestExecutionListener;
+import com.github.springtestdbunit.annotation.DbUnitConfiguration;
 import org.junit.runner.RunWith;
 import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.TestExecutionListeners;
@@ -29,11 +30,12 @@ import org.springframework.test.context.support.DirtiesContextTestExecutionListe
  * Created by Valerii Sosliuk on 4/22/2017.
  */
 @RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration(classes = {JpaDaoConfig.class})
+@ContextConfiguration(classes = {JpaDaoConfig.class, JpaDbunitTestConfig.class})
 @TestPropertySource("classpath:jpa-test.properties")
 @TestExecutionListeners({ DependencyInjectionTestExecutionListener.class,
         DirtiesContextTestExecutionListener.class,
         DbUnitTestExecutionListener.class })
+@DbUnitConfiguration(databaseConnection = "dbUnitDatabaseConnection")
 public class AbstractJpaDaoTest extends AbstractTransactionalJUnit4SpringContextTests {
 
 }
diff --git a/dao/src/test/java/org/thingsboard/server/dao/JpaDbunitTestConfig.java b/dao/src/test/java/org/thingsboard/server/dao/JpaDbunitTestConfig.java
new file mode 100644
index 0000000..0c064d4
--- /dev/null
+++ b/dao/src/test/java/org/thingsboard/server/dao/JpaDbunitTestConfig.java
@@ -0,0 +1,39 @@
+package org.thingsboard.server.dao;
+
+import com.github.springtestdbunit.bean.DatabaseConfigBean;
+import com.github.springtestdbunit.bean.DatabaseDataSourceConnectionFactoryBean;
+import org.dbunit.DatabaseUnitException;
+import org.dbunit.ext.postgresql.PostgresqlDataTypeFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.sql.DataSource;
+import java.io.IOException;
+import java.sql.SQLException;
+
+/**
+ * Created by Valerii Sosliuk on 5/6/2017.
+ */
+@Configuration
+public class JpaDbunitTestConfig {
+
+    @Autowired
+    private DataSource dataSource;
+
+    @Bean
+    public DatabaseConfigBean databaseConfigBean() {
+        DatabaseConfigBean databaseConfigBean = new DatabaseConfigBean();
+        databaseConfigBean.setDatatypeFactory(new PostgresqlDataTypeFactory());
+        return databaseConfigBean;
+    }
+
+    @Bean(name = "dbUnitDatabaseConnection")
+    public DatabaseDataSourceConnectionFactoryBean dbUnitDatabaseConnection() throws SQLException, DatabaseUnitException, IOException {
+        DatabaseDataSourceConnectionFactoryBean databaseDataSourceConnectionFactoryBean = new DatabaseDataSourceConnectionFactoryBean();
+        databaseDataSourceConnectionFactoryBean.setDatabaseConfig(databaseConfigBean());
+        databaseDataSourceConnectionFactoryBean.setDataSource(dataSource);
+        databaseDataSourceConnectionFactoryBean.setSchema("public");
+        return databaseDataSourceConnectionFactoryBean;
+    }
+}
diff --git a/dao/src/test/java/org/thingsboard/server/dao/sql/device/JpaDeviceCredentialsDaoTest.java b/dao/src/test/java/org/thingsboard/server/dao/sql/device/JpaDeviceCredentialsDaoTest.java
new file mode 100644
index 0000000..dce6113
--- /dev/null
+++ b/dao/src/test/java/org/thingsboard/server/dao/sql/device/JpaDeviceCredentialsDaoTest.java
@@ -0,0 +1,41 @@
+package org.thingsboard.server.dao.sql.device;
+
+import com.github.springtestdbunit.annotation.DatabaseSetup;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.thingsboard.server.common.data.security.DeviceCredentials;
+import org.thingsboard.server.dao.AbstractJpaDaoTest;
+import org.thingsboard.server.dao.device.DeviceCredentialsDao;
+
+import java.util.UUID;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * Created by Valerii Sosliuk on 5/6/2017.
+ */
+public class JpaDeviceCredentialsDaoTest extends AbstractJpaDaoTest {
+
+    @Autowired
+    DeviceCredentialsDao deviceCredentialsDao;
+
+    @Test
+    @DatabaseSetup("classpath:dbunit/device_credentials.xml")
+    public void testFindByDeviceId() {
+        UUID deviceId = UUID.fromString("958e3a30-3215-11e7-93ae-92361f002671");
+        DeviceCredentials deviceCredentials = deviceCredentialsDao.findByDeviceId(deviceId);
+        assertNotNull(deviceCredentials);
+        assertEquals("958e3314-3215-11e7-93ae-92361f002671", deviceCredentials.getId().getId().toString());
+        assertEquals("ID_1", deviceCredentials.getCredentialsId());
+    }
+
+    @Test
+    @DatabaseSetup("classpath:dbunit/device_credentials.xml")
+    public void findByCredentialsId() {
+        String credentialsId = "ID_2";
+        DeviceCredentials deviceCredentials = deviceCredentialsDao.findByCredentialsId(credentialsId);
+        assertNotNull(deviceCredentials);
+        assertEquals("958e3c74-3215-11e7-93ae-92361f002671", deviceCredentials.getId().getId().toString());
+    }
+}
diff --git a/dao/src/test/java/org/thingsboard/server/dao/sql/device/JpaDeviceDaoTest.java b/dao/src/test/java/org/thingsboard/server/dao/sql/device/JpaDeviceDaoTest.java
new file mode 100644
index 0000000..4f1b315
--- /dev/null
+++ b/dao/src/test/java/org/thingsboard/server/dao/sql/device/JpaDeviceDaoTest.java
@@ -0,0 +1,146 @@
+package org.thingsboard.server.dao.sql.device;
+
+import com.datastax.driver.core.utils.UUIDs;
+import com.github.springtestdbunit.annotation.DatabaseOperation;
+import com.github.springtestdbunit.annotation.DatabaseSetup;
+import com.github.springtestdbunit.annotation.DatabaseTearDown;
+import com.google.common.util.concurrent.*;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+import org.thingsboard.server.common.data.Device;
+import org.thingsboard.server.common.data.id.CustomerId;
+import org.thingsboard.server.common.data.id.DeviceId;
+import org.thingsboard.server.common.data.id.TenantId;
+import org.thingsboard.server.common.data.page.TextPageLink;
+import org.thingsboard.server.dao.AbstractJpaDaoTest;
+import org.thingsboard.server.dao.device.DeviceDao;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executors;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * Created by Valerii Sosliuk on 5/6/2017.
+ */
+@Transactional
+public class JpaDeviceDaoTest extends AbstractJpaDaoTest {
+
+    @Autowired
+    private DeviceDao deviceDao;
+
+    @Test
+    @DatabaseSetup(value = "classpath:dbunit/empty_dataset.xml",type = DatabaseOperation.DELETE_ALL)
+    @DatabaseTearDown(value = "classpath:dbunit/empty_dataset.xml",type = DatabaseOperation.DELETE_ALL)
+    public void testFindDevicesByTenantId() {
+        UUID tenantId1 = UUIDs.timeBased();
+        UUID tenantId2 = UUIDs.timeBased();
+        UUID customerId1 = UUIDs.timeBased();
+        UUID customerId2 = UUIDs.timeBased();
+        createDevices(tenantId1, tenantId2, customerId1, customerId2, 40);
+
+        TextPageLink pageLink1 = new TextPageLink(15, "SEARCH_TEXT");
+        List<Device> devices1 = deviceDao.findDevicesByTenantId(tenantId1, pageLink1);
+        assertEquals(15, devices1.size());
+
+        TextPageLink pageLink2 = new TextPageLink(15, "SEARCH_TEXT",  devices1.get(14).getId().getId(), null);
+        List<Device> devices2 = deviceDao.findDevicesByTenantId(tenantId1, pageLink2);
+        assertEquals(5, devices2.size());
+    }
+
+    @Test
+    @DatabaseSetup(value = "classpath:dbunit/empty_dataset.xml",type = DatabaseOperation.DELETE_ALL)
+    @DatabaseTearDown(value = "classpath:dbunit/empty_dataset.xml",type = DatabaseOperation.DELETE_ALL)
+    public void testFindAsync() throws ExecutionException, InterruptedException {
+        UUID tenantId = UUIDs.timeBased();
+        UUID customerId = UUIDs.timeBased();
+        Device device = getDevice(tenantId, customerId);
+        deviceDao.save(device);
+
+        UUID uuid = device.getId().getId();
+        Device entity = deviceDao.findById(uuid);
+        assertNotNull(entity);
+        assertEquals(uuid, entity.getId().getId());
+
+        ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
+        ListenableFuture<Device> future = service.submit(() -> deviceDao.findById(uuid));
+        Device asyncDevice = future.get();
+        assertNotNull("Async device expected to be not null", asyncDevice);
+    }
+
+    @Test
+    @DatabaseSetup(value = "classpath:dbunit/empty_dataset.xml",type = DatabaseOperation.DELETE_ALL)
+    @DatabaseTearDown(value = "classpath:dbunit/empty_dataset.xml",type = DatabaseOperation.DELETE_ALL)
+    public void testFindDevicesByTenantIdAndIdsAsync() throws ExecutionException, InterruptedException {
+        UUID tenantId1 = UUIDs.timeBased();
+        UUID customerId1 = UUIDs.timeBased();
+        UUID tenantId2 = UUIDs.timeBased();
+        UUID customerId2 = UUIDs.timeBased();
+
+        List<UUID> deviceIds = new ArrayList<>();
+
+        for(int i = 0; i < 5; i++) {
+            UUID deviceId1 = UUIDs.timeBased();
+            UUID deviceId2 = UUIDs.timeBased();
+            deviceDao.save(getDevice(tenantId1, customerId1, deviceId1));
+            deviceDao.save(getDevice(tenantId2, customerId2, deviceId2));
+            deviceIds.add(deviceId1);
+            deviceIds.add(deviceId2);
+        }
+
+        ListenableFuture<List<Device>> devicesFuture = deviceDao.findDevicesByTenantIdAndIdsAsync(tenantId1, deviceIds);
+        List<Device> devices = devicesFuture.get();
+        assertEquals(5, devices.size());
+    }
+
+    @Test
+    @DatabaseSetup(value = "classpath:dbunit/empty_dataset.xml",type = DatabaseOperation.DELETE_ALL)
+    @DatabaseTearDown(value = "classpath:dbunit/empty_dataset.xml",type = DatabaseOperation.DELETE_ALL)
+    public void testFindDevicesByTenantIdAndCustomerIdAndIdsAsync() throws ExecutionException, InterruptedException {
+        UUID tenantId1 = UUIDs.timeBased();
+        UUID customerId1 = UUIDs.timeBased();
+        UUID tenantId2 = UUIDs.timeBased();
+        UUID customerId2 = UUIDs.timeBased();
+
+        List<UUID> deviceIds = new ArrayList<>();
+
+        for(int i = 0; i < 20; i++) {
+            UUID deviceId1 = UUIDs.timeBased();
+            UUID deviceId2 = UUIDs.timeBased();
+            deviceDao.save(getDevice(tenantId1, customerId1, deviceId1));
+            deviceDao.save(getDevice(tenantId2, customerId2, deviceId2));
+            deviceIds.add(deviceId1);
+            deviceIds.add(deviceId2);
+        }
+
+        ListenableFuture<List<Device>> devicesFuture = deviceDao.findDevicesByTenantIdCustomerIdAndIdsAsync(tenantId1, customerId1, deviceIds);
+        List<Device> devices = devicesFuture.get();
+        assertEquals(20, devices.size());
+    }
+
+    private void createDevices(UUID tenantId1, UUID tenantId2, UUID customerId1, UUID customerId2, int count) {
+        for (int i = 0; i < count / 2; i++) {
+            deviceDao.save(getDevice(tenantId1, customerId1));
+            deviceDao.save(getDevice(tenantId2, customerId2));
+        }
+    }
+
+    private Device getDevice(UUID tenantId, UUID customerID) {
+        return getDevice(tenantId, customerID, UUIDs.timeBased());
+    }
+
+    private Device getDevice(UUID tenantId, UUID customerID, UUID deviceId) {
+        Device device = new Device();
+        device.setId(new DeviceId(deviceId));
+        device.setTenantId(new TenantId(tenantId));
+        device.setCustomerId(new CustomerId(customerID));
+        device.setName("SEARCH_TEXT");
+        return device;
+    }
+}
diff --git a/dao/src/test/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDaoTest.java b/dao/src/test/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDaoTest.java
index cdebadd..30667fa 100644
--- a/dao/src/test/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDaoTest.java
+++ b/dao/src/test/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDaoTest.java
@@ -1,6 +1,5 @@
 package org.thingsboard.server.dao.sql.event;
 
-import ch.qos.logback.core.net.SyslogOutputStream;
 import com.datastax.driver.core.utils.UUIDs;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
@@ -18,8 +17,6 @@ import org.thingsboard.server.dao.AbstractJpaDaoTest;
 import org.thingsboard.server.dao.event.EventDao;
 
 import java.io.IOException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
 import java.util.List;
 import java.util.Optional;
 import java.util.UUID;
diff --git a/dao/src/test/java/org/thingsboard/server/dao/sql/plugin/JpaBasePluginDaoTest.java b/dao/src/test/java/org/thingsboard/server/dao/sql/plugin/JpaBasePluginDaoTest.java
index f968b68..31a6c58 100644
--- a/dao/src/test/java/org/thingsboard/server/dao/sql/plugin/JpaBasePluginDaoTest.java
+++ b/dao/src/test/java/org/thingsboard/server/dao/sql/plugin/JpaBasePluginDaoTest.java
@@ -23,7 +23,6 @@ import org.thingsboard.server.common.data.id.PluginId;
 import org.thingsboard.server.common.data.id.TenantId;
 import org.thingsboard.server.common.data.page.TextPageLink;
 import org.thingsboard.server.common.data.plugin.PluginMetaData;
-import org.thingsboard.server.common.data.rule.RuleMetaData;
 import org.thingsboard.server.dao.AbstractJpaDaoTest;
 import org.thingsboard.server.dao.plugin.PluginDao;
 
diff --git a/dao/src/test/java/org/thingsboard/server/dao/sql/user/JpaUserDaoTest.java b/dao/src/test/java/org/thingsboard/server/dao/sql/user/JpaUserDaoTest.java
index fe540fa..9d719ba 100644
--- a/dao/src/test/java/org/thingsboard/server/dao/sql/user/JpaUserDaoTest.java
+++ b/dao/src/test/java/org/thingsboard/server/dao/sql/user/JpaUserDaoTest.java
@@ -71,7 +71,6 @@ public class JpaUserDaoTest extends AbstractJpaDaoTest {
         UUID tenantId = UUIDs.timeBased();
         UUID customerId = UUIDs.timeBased();
         create30Adminsand60Users(tenantId, customerId);
-        assertEquals(90, userDao.find().size());
         List<User> tenantAdmins1 = userDao.findTenantAdmins(tenantId, new TextPageLink(20));
         assertEquals(20, tenantAdmins1.size());
         List<User> tenantAdmins2 = userDao.findTenantAdmins(tenantId,
@@ -88,7 +87,6 @@ public class JpaUserDaoTest extends AbstractJpaDaoTest {
         UUID tenantId = UUIDs.timeBased();
         UUID customerId = UUIDs.timeBased();
         create30Adminsand60Users(tenantId, customerId);
-        assertEquals(90, userDao.find().size());
         List<User> customerUsers1 = userDao.findCustomerUsers(tenantId, customerId, new TextPageLink(40));
         assertEquals(40, customerUsers1.size());
         List<User> customerUsers2 = userDao.findCustomerUsers(tenantId, customerId,
diff --git a/dao/src/test/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDaoTest.java b/dao/src/test/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDaoTest.java
index eafcfd3..7c1df06 100644
--- a/dao/src/test/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDaoTest.java
+++ b/dao/src/test/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDaoTest.java
@@ -16,7 +16,9 @@
 package org.thingsboard.server.dao.sql.widget;
 
 import com.datastax.driver.core.utils.UUIDs;
+import com.github.springtestdbunit.annotation.DatabaseOperation;
 import com.github.springtestdbunit.annotation.DatabaseSetup;
+import com.github.springtestdbunit.annotation.DatabaseTearDown;
 import org.junit.Ignore;
 import org.junit.Test;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -41,13 +43,15 @@ public class JpaWidgetsBundleDaoTest extends AbstractJpaDaoTest {
     private WidgetsBundleDao widgetsBundleDao;
 
     @Test
-    @DatabaseSetup("classpath:dbunit/widgets_bundle.xml")
+    @DatabaseSetup(value = "classpath:dbunit/widgets_bundle.xml",type= DatabaseOperation.CLEAN_INSERT)
+    @DatabaseTearDown(value = "classpath:dbunit/widgets_bundle.xml", type= DatabaseOperation.DELETE_ALL)
     public void testFindAll() {
         assertEquals(7, widgetsBundleDao.find().size());
     }
 
     @Test
-    @DatabaseSetup("classpath:dbunit/widgets_bundle.xml")
+    @DatabaseSetup(value = "classpath:dbunit/widgets_bundle.xml",type= DatabaseOperation.CLEAN_INSERT)
+    @DatabaseTearDown(value = "classpath:dbunit/widgets_bundle.xml", type= DatabaseOperation.DELETE_ALL)
     public void testFindWidgetsBundleByTenantIdAndAlias() {
         WidgetsBundle widgetsBundle = widgetsBundleDao.findWidgetsBundleByTenantIdAndAlias(
                 UUID.fromString("250aca8e-2825-11e7-93ae-92361f002671"), "WB3");
@@ -55,7 +59,8 @@ public class JpaWidgetsBundleDaoTest extends AbstractJpaDaoTest {
     }
 
     @Test
-    @DatabaseSetup("classpath:dbunit/empty_dataset.xml")
+    @DatabaseSetup(value = "classpath:dbunit/widgets_bundle.xml", type= DatabaseOperation.DELETE_ALL)
+   // @DatabaseTearDown(value = "classpath:dbunit/empty_dataset.xml", type= DatabaseOperation.DELETE_ALL)
     public void testFindSystemWidgetsBundles() {
         createSystemWidgetBundles(30, "WB_");
         assertEquals(30, widgetsBundleDao.find().size());
@@ -70,7 +75,7 @@ public class JpaWidgetsBundleDaoTest extends AbstractJpaDaoTest {
     }
 
     @Test
-    @DatabaseSetup("classpath:dbunit/empty_dataset.xml")
+    @DatabaseSetup(value = "classpath:dbunit/widgets_bundle.xml", type= DatabaseOperation.DELETE_ALL)
     public void testFindWidgetsBundlesByTenantId() {
         UUID tenantId1 = UUIDs.timeBased();
         UUID tenantId2 = UUIDs.timeBased();
@@ -97,7 +102,7 @@ public class JpaWidgetsBundleDaoTest extends AbstractJpaDaoTest {
     }
 
     @Test
-    @DatabaseSetup("classpath:dbunit/empty_dataset.xml")
+    @DatabaseSetup(value = "classpath:dbunit/widgets_bundle.xml", type= DatabaseOperation.DELETE_ALL)
     public void testFindAllWidgetsBundlesByTenantId() {
         UUID tenantId1 = UUIDs.timeBased();
         UUID tenantId2 = UUIDs.timeBased();
@@ -129,9 +134,9 @@ public class JpaWidgetsBundleDaoTest extends AbstractJpaDaoTest {
         assertEquals(0, widgetsBundles4.size());
     }
 
-
     @Test
     @DatabaseSetup("classpath:dbunit/empty_dataset.xml")
+    @DatabaseTearDown(value = "classpath:dbunit/empty_dataset.xml", type= DatabaseOperation.DELETE_ALL)
     public void testNonSearchTextNotFound() {
         UUID tenantId = UUIDs.timeBased();
         createWidgetBundles(5, tenantId, "ABC_");
diff --git a/dao/src/test/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDaoTest.java b/dao/src/test/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDaoTest.java
index c38ccbd..87ce37a 100644
--- a/dao/src/test/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDaoTest.java
+++ b/dao/src/test/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDaoTest.java
@@ -15,7 +15,6 @@
  */
 package org.thingsboard.server.dao.sql.widget;
 
-import com.datastax.driver.core.utils.UUIDs;
 import com.github.springtestdbunit.annotation.DatabaseSetup;
 import org.junit.Test;
 import org.springframework.beans.factory.annotation.Autowired;
diff --git a/dao/src/test/resources/dbunit/device_credentials.xml b/dao/src/test/resources/dbunit/device_credentials.xml
new file mode 100644
index 0000000..aee6b1e
--- /dev/null
+++ b/dao/src/test/resources/dbunit/device_credentials.xml
@@ -0,0 +1,16 @@
+<dataset>
+    <device_credentials
+            id="958e3314-3215-11e7-93ae-92361f002671"
+            device_id="958e3a30-3215-11e7-93ae-92361f002671"
+            credentials_type="0"
+            credentials_id="ID_1"
+            credentials_value="ACCESS_TOKEN_1"
+    />
+    <device_credentials
+            id="958e3c74-3215-11e7-93ae-92361f002671"
+            device_id="958e3e5e-3215-11e7-93ae-92361f002671"
+            credentials_type="0"
+            credentials_id="ID_2"
+            credentials_value="ACCESS_TOKEN_2"
+    />
+</dataset>
\ No newline at end of file
diff --git a/dao/src/test/resources/dbunit/events.xml b/dao/src/test/resources/dbunit/events.xml
index 8f88758..2c02c19 100644
--- a/dao/src/test/resources/dbunit/events.xml
+++ b/dao/src/test/resources/dbunit/events.xml
@@ -1,16 +1,16 @@
 <dataset>
     <event
-        id="uuid'be41c7a2-31f5-11e7-9cfd-2786e6aa2046'"
-        tenant_id="uuid'be41c7a0-31f5-11e7-9cfd-2786e6aa2046'"
-        entity_id="uuid'be41c7a1-31f5-11e7-9cfd-2786e6aa2046'"
+        id="be41c7a2-31f5-11e7-9cfd-2786e6aa2046"
+        tenant_id="be41c7a0-31f5-11e7-9cfd-2786e6aa2046"
+        entity_id="be41c7a1-31f5-11e7-9cfd-2786e6aa2046"
         entity_type="1"
         event_type="STATS"
         event_uid="be41c7a3-31f5-11e7-9cfd-2786e6aa2046"
     />
     <event
-        id="uuid'be41c7a4-31f5-11e7-9cfd-2786e6aa2046'"
-        tenant_id="uuid'be41c7a0-31f5-11e7-9cfd-2786e6aa2046'"
-        entity_id="uuid'be41c7a1-31f5-11e7-9cfd-2786e6aa2046'"
+        id="be41c7a4-31f5-11e7-9cfd-2786e6aa2046"
+        tenant_id="be41c7a0-31f5-11e7-9cfd-2786e6aa2046"
+        entity_id="be41c7a1-31f5-11e7-9cfd-2786e6aa2046"
         entity_type="1"
         event_type="STATS"
         event_uid="be41c7a5-31f5-11e7-9cfd-2786e6aa2046"
diff --git a/dao/src/test/resources/dbunit/rule.xml b/dao/src/test/resources/dbunit/rule.xml
index dfe1054..5040ff6 100644
--- a/dao/src/test/resources/dbunit/rule.xml
+++ b/dao/src/test/resources/dbunit/rule.xml
@@ -1,31 +1,31 @@
 <dataset>
     <rule
-        id="uuid'8e834e11-2e0a-11e7-83ec-f7f6dbfb4833'"
-        tenant_id="uuid'8e834e10-2e0a-11e7-83ec-f7f6dbfb4833'"
+        id="8e834e11-2e0a-11e7-83ec-f7f6dbfb4833"
+        tenant_id="8e834e10-2e0a-11e7-83ec-f7f6dbfb4833"
         name="RULE_11"
         weight="1"
         search_text="rule_11"
         plugin_token="token_1"
     />
     <rule
-        id="uuid'8e834e12-2e0a-11e7-83ec-f7f6dbfb4833'"
-        tenant_id="uuid'8e834e10-2e0a-11e7-83ec-f7f6dbfb4833'"
+        id="8e834e12-2e0a-11e7-83ec-f7f6dbfb4833"
+        tenant_id="8e834e10-2e0a-11e7-83ec-f7f6dbfb4833"
         name="RULE_12"
         weight="1"
         search_text="rule_12"
         plugin_token="token_1"
     />
     <rule
-        id="uuid'8e834e13-2e0a-11e7-83ec-f7f6dbfb4833'"
-        tenant_id="uuid'8e834e10-2e0a-11e7-83ec-f7f6dbfb4833'"
+        id="8e834e13-2e0a-11e7-83ec-f7f6dbfb4833"
+        tenant_id="8e834e10-2e0a-11e7-83ec-f7f6dbfb4833"
         name="RULE_13"
         weight="1"
         search_text="rule_13"
         plugin_token="token_1"
     />
     <rule
-        id="uuid'8e834e14-2e0a-11e7-83ec-f7f6dbfb4833'"
-        tenant_id="uuid'8e834e10-2e0a-11e7-83ec-f7f6dbfb4833'"
+        id="8e834e14-2e0a-11e7-83ec-f7f6dbfb4833"
+        tenant_id="8e834e10-2e0a-11e7-83ec-f7f6dbfb4833"
         name="RULE_14"
         weight="2"
         search_text="rule_14"
diff --git a/dao/src/test/resources/dbunit/user_credentials.xml b/dao/src/test/resources/dbunit/user_credentials.xml
index c6607e9..76a2138 100644
--- a/dao/src/test/resources/dbunit/user_credentials.xml
+++ b/dao/src/test/resources/dbunit/user_credentials.xml
@@ -1,15 +1,15 @@
 <dataset>
     <user_credentials
-        id="uuid'3ed10af0-27d5-11e7-93ae-92361f002671'"
-        user_id="uuid'44ee8552-27d5-11e7-93ae-92361f002671'"
+        id="3ed10af0-27d5-11e7-93ae-92361f002671"
+        user_id="44ee8552-27d5-11e7-93ae-92361f002671"
         enabled="true"
         password="password"
         activate_token="ACTIVATE_TOKEN_1"
         reset_token="RESET_TOKEN_1"
     />
     <user_credentials
-        id="uuid'4b9e010c-27d5-11e7-93ae-92361f002671'"
-        user_id="uuid'787827e6-27d7-11e7-93ae-92361f002671'"
+        id="4b9e010c-27d5-11e7-93ae-92361f002671"
+        user_id="787827e6-27d7-11e7-93ae-92361f002671"
         enabled="true"
         password="password"
         activate_token="ACTIVATE_TOKEN_2"
diff --git a/dao/src/test/resources/dbunit/users.xml b/dao/src/test/resources/dbunit/users.xml
index b1e51dd..9576b5c 100644
--- a/dao/src/test/resources/dbunit/users.xml
+++ b/dao/src/test/resources/dbunit/users.xml
@@ -1,7 +1,7 @@
 <dataset>
-    <user id="uuid'9cb58ba0-27c1-11e7-93ae-92361f002671'"
-          tenant_id="uuid'c97ea14e-27c1-11e7-93ae-92361f002671'"
-          customer_id="uuid'cdf9c79e-27c1-11e7-93ae-92361f002671'"
+    <tb_user id="9cb58ba0-27c1-11e7-93ae-92361f002671"
+          tenant_id="c97ea14e-27c1-11e7-93ae-92361f002671"
+          customer_id="cdf9c79e-27c1-11e7-93ae-92361f002671"
           authority="0"
           email="sysadm@thingsboard.org"
           search_text="SYSADM SEARCH TEXT"
@@ -9,8 +9,8 @@
           last_name="Doe"
           additional_info="{&quot;key&quot;:&quot;value-0&quot;}"
     />
-    <user id="uuid'1312f328-27c7-11e7-93ae-92361f002671'"
-          tenant_id="uuid'1e1cd4c8-27c7-11e7-93ae-92361f002671'"
+    <tb_user id="1312f328-27c7-11e7-93ae-92361f002671"
+          tenant_id="1e1cd4c8-27c7-11e7-93ae-92361f002671"
           authority="1"
           email="tenantadm1@thingsboard.org"
           search_text="TENANTADM1 SEARCH TEXT"
@@ -18,8 +18,8 @@
           last_name="Serif"
           additional_info="{&quot;key&quot;:&quot;value-11&quot;}"
     />
-    <user id="uuid'2b090dde-27ca-11e7-93ae-92361f002671'"
-          tenant_id="uuid'1e1cd4c8-27c7-11e7-93ae-92361f002671'"
+    <tb_user id="2b090dde-27ca-11e7-93ae-92361f002671"
+          tenant_id="1e1cd4c8-27c7-11e7-93ae-92361f002671"
           authority="1"
           email="tenantadm2@thingsboard.org"
           search_text="TENANTADM2 SEARCH TEXT"
@@ -27,9 +27,9 @@
           last_name="Morgan"
           additional_info="{&quot;key&quot;:&quot;value-12&quot;}"
     />
-    <user id="uuid'cc8c1ca8-27c7-11e7-93ae-92361f002671'"
-          tenant_id="uuid'd2e27caa-27c7-11e7-93ae-92361f002671'"
-          customer_id="uuid'd89e128a-27c7-11e7-93ae-92361f002671'"
+    <tb_user id="cc8c1ca8-27c7-11e7-93ae-92361f002671"
+          tenant_id="d2e27caa-27c7-11e7-93ae-92361f002671"
+          customer_id="d89e128a-27c7-11e7-93ae-92361f002671"
           authority="2"
           email="customeruser@thingsboard.org"
           search_text="CUSTOMER USER SEARCH TEXT"
@@ -37,9 +37,9 @@
           last_name="Gordon"
           additional_info="{&quot;key&quot;:&quot;value-2&quot;}"
     />
-    <user id="uuid'edb2de58-27c7-11e7-93ae-92361f002671'"
-          tenant_id="uuid'f229675e-27c7-11e7-93ae-92361f002671'"
-          customer_id="uuid'f7a3d4e4-27c7-11e7-93ae-92361f002671'"
+    <tb_user id="edb2de58-27c7-11e7-93ae-92361f002671"
+          tenant_id="f229675e-27c7-11e7-93ae-92361f002671"
+          customer_id="f7a3d4e4-27c7-11e7-93ae-92361f002671"
           authority="3"
           email="refreshtoken@thingsboard.org"
           search_text="REFRESH TOKEN SEARCH TEXT"
diff --git a/dao/src/test/resources/dbunit/widget_type.xml b/dao/src/test/resources/dbunit/widget_type.xml
index 49664d3..ae99ce6 100644
--- a/dao/src/test/resources/dbunit/widget_type.xml
+++ b/dao/src/test/resources/dbunit/widget_type.xml
@@ -1,28 +1,28 @@
 <dataset>
     <widget_type
-        id="uuid'2b7e4c91-2dfe-11e7-94aa-f7f6dbfb4833'"
-        tenant_id="uuid'2b7e4c90-2dfe-11e7-94aa-f7f6dbfb4833'"
+        id="2b7e4c91-2dfe-11e7-94aa-f7f6dbfb4833"
+        tenant_id="2b7e4c90-2dfe-11e7-94aa-f7f6dbfb4833"
         bundle_alias="BUNDLE_ALIAS_1"
         alias="ALIAS1"
         name="ALIAS1"
     />
     <widget_type
-        id="uuid'2b7e4c92-2dfe-11e7-94aa-f7f6dbfb4833'"
-        tenant_id="uuid'2b7e4c90-2dfe-11e7-94aa-f7f6dbfb4833'"
+        id="2b7e4c92-2dfe-11e7-94aa-f7f6dbfb4833"
+        tenant_id="2b7e4c90-2dfe-11e7-94aa-f7f6dbfb4833"
         bundle_alias="BUNDLE_ALIAS_1"
         alias="ALIAS2"
         name="ALIAS2"
     />
     <widget_type
-        id="uuid'2b7e4c93-2dfe-11e7-94aa-f7f6dbfb4833'"
-        tenant_id="uuid'2b7e4c90-2dfe-11e7-94aa-f7f6dbfb4833'"
+        id="2b7e4c93-2dfe-11e7-94aa-f7f6dbfb4833"
+        tenant_id="2b7e4c90-2dfe-11e7-94aa-f7f6dbfb4833"
         bundle_alias="BUNDLE_ALIAS_1"
         alias="ALIAS3"
         name="ALIAS3"
     />
     <widget_type
-        id="uuid'2b7e4c94-2dfe-11e7-94aa-f7f6dbfb4833'"
-        tenant_id="uuid'2b7e4c90-2dfe-11e7-94aa-f7f6dbfb4833'"
+        id="2b7e4c94-2dfe-11e7-94aa-f7f6dbfb4833"
+        tenant_id="2b7e4c90-2dfe-11e7-94aa-f7f6dbfb4833"
         bundle_alias="BUNDLE_ALIAS_2"
         alias="ALIAS4"
         name="ALIAS4"
diff --git a/dao/src/test/resources/dbunit/widgets_bundle.xml b/dao/src/test/resources/dbunit/widgets_bundle.xml
index 10a8d22..ad6fbd7 100644
--- a/dao/src/test/resources/dbunit/widgets_bundle.xml
+++ b/dao/src/test/resources/dbunit/widgets_bundle.xml
@@ -1,56 +1,47 @@
 <dataset>
     <widgets_bundle
-        id="uuid'250ac7b4-2825-11e7-93ae-92361f002671'"
-        tenant_id="uuid'250aca8e-2825-11e7-93ae-92361f002671'"
+        id="250ac7b4-2825-11e7-93ae-92361f002671"
+        tenant_id="250aca8e-2825-11e7-93ae-92361f002671"
         alias="WB1"
         title="Widgets Bundle 1"
         search_text="WB SEARCH TEXT 1"
     />
     <widgets_bundle
-        id="uuid'3269c18a-2825-11e7-93ae-92361f002671'"
-        tenant_id="uuid'3269c18a-2825-11e7-93ae-92361f002671'"
+        id="3269c18a-2825-11e7-93ae-92361f002671"
+        tenant_id="3269c18a-2825-11e7-93ae-92361f002671"
         alias="WB2"
         title="Widgets Bundle 2"
         search_text="WB SEARCH TEXT 2"
     />
     <widgets_bundle
-        id="uuid'44e6af4e-2825-11e7-93ae-92361f002671'"
-        tenant_id="uuid'250aca8e-2825-11e7-93ae-92361f002671'"
+        id="44e6af4e-2825-11e7-93ae-92361f002671"
+        tenant_id="250aca8e-2825-11e7-93ae-92361f002671"
         alias="WB3"
         title="Widgets Bundle 3"
         search_text="WB SEARCH TEXT 3"
     />
     <widgets_bundle
-        id="uuid'696dc9b4-2830-11e7-93ae-92361f002671'"
+        id="696dc9b4-2830-11e7-93ae-92361f002671"
         alias="WB4"
         title="Widgets Bundle 4"
         search_text="SYSTEM BUNDLE 1"
     />
     <widgets_bundle
-        id="uuid'1a83fc50-2840-11e7-93ae-92361f002671'"
+        id="1a83fc50-2840-11e7-93ae-92361f002671"
         alias="WB5"
         title="Widgets Bundle 5"
         search_text="SYSTEM BUNDLE 2"
     />
     <widgets_bundle
-        id="uuid'6a593dde-2841-11e7-93ae-92361f002671'"
+        id="6a593dde-2841-11e7-93ae-92361f002671"
         alias="WB6"
         title="Widgets Bundle 6"
         search_text="SYSTEM BUNDLE 1"
     />
     <widgets_bundle
-        id="uuid'3beb4b1a-294d-11e7-93ae-92361f002671'"
+        id="3beb4b1a-294d-11e7-93ae-92361f002671"
         alias="WB6"
         title="Widgets Bundle 7"
         search_text="ABC DEF"
     />
-    <!--
-    <widgets_bundle
-        id=""
-        tenant_id=""
-        alias=""
-        title=""
-        search_text=""
-    />
-    -->
 </dataset>
\ No newline at end of file
diff --git a/dao/src/test/resources/jpa-test.properties b/dao/src/test/resources/jpa-test.properties
index 7fff922..f887e08 100644
--- a/dao/src/test/resources/jpa-test.properties
+++ b/dao/src/test/resources/jpa-test.properties
@@ -1,7 +1,17 @@
 cassandra.enabled=false
 
 sql.enabled=true
-sql.datasource.url=jdbc:h2:mem:thingsboard
-sql.datasource.username=sa
-sql.datasource.password=
+#sql.datasource.url=jdbc:h2:mem:thingsboard
+#sql.datasource.username=sa
+#sql.datasource.password=
+#spring.jpa.hibernate.ddl-auto=create-drop
 
+spring.jpa.show-sql=false
+spring.jpa.hibernate.ddl-auto=create-drop
+
+spring.database.driverClassName=org.postgresql.Driver
+spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
+spring.datasource.url=jdbc:postgresql://localhost:5432/thingsboard-test
+spring.datasource.username=thingsboard
+spring.datasource.password=thingsboard
+spring.jpa.generate-ddl=true

pom.xml 6(+6 -0)

diff --git a/pom.xml b/pom.xml
index 909936f..0d813f0 100755
--- a/pom.xml
+++ b/pom.xml
@@ -74,6 +74,7 @@
         <h2.version>1.4.194</h2.version>
         <dbunit.version>2.5.3</dbunit.version>
         <spring-test-dbunit.version>1.2.1</spring-test-dbunit.version>
+        <postgresql.driver.version>9.4.1211</postgresql.driver.version>
     </properties>
 
     <modules>
@@ -420,6 +421,11 @@
                 <version>${spring-boot.version}</version>
             </dependency>
             <dependency>
+                <groupId>org.postgresql</groupId>
+                <artifactId>postgresql</artifactId>
+                <version>${postgresql.driver.version}</version>
+            </dependency>
+            <dependency>
                 <groupId>org.springframework</groupId>
                 <artifactId>spring-context</artifactId>
                 <version>${spring.version}</version>