springCloud集成tdengine(原生和mapper方式) 其二 原生篇

mapper篇请看另一篇文章

一、引入pom文件

csharp 复制代码
   <!-- TDengine 连接器-->
        <dependency>
            <groupId>com.taosdata.jdbc</groupId>
            <artifactId>taos-jdbcdriver</artifactId>
            <version>3.5.3</version>
        </dependency>

二、在nacos中填写数据库各种value值

java 复制代码
tdengine: 
  datasource:
    location: yourLocation
    username: root
    password: yourPassword

三、编写TDengineUtil文件

下方util文件里面,包含创建database的方法,save方法以及getList方法,还有查询单个的方法。有需要的可以自行选择。这个包已经经过测试过了,有问题欢迎批评指正。在底部我会附上其他代码,是在其他地方copy的,具体使用方法没试过。大家自行选择。

java 复制代码
package com.apex.iot.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import java.lang.reflect.Method;
import java.sql.*;
import java.util.*;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * TDengine的util类
 * createDate: 2025.03.11
 * 使用方法:
 *       1 需要new TDengine,创建链接 connection
 *       2 如果有需要自己写的有关的sql,直接调用useOrInsertSql即可
 *       例如:
 *          TDengineUtil util1 = new TDengineUtil();
 *          util1.useOrInsertSql(str.toString());
 *        上述操作即可执行有关新增或修改的sql语句。
 *
 */
@Slf4j
public class TDengineUtil {

    private static Connection connection;
    private static Pattern humpPattern = Pattern.compile("[A-Z]");
    private static Statement statement;

    /**
     * new的时候创建好链接
     * @param jdbcUrl 要连接的数据库地址
     */
    public TDengineUtil(String jdbcUrl)  throws SQLException {
        if(this.connection == null){
            Properties properties = new Properties();
            properties.setProperty("charset", "UTF-8");
            properties.setProperty("locale", "en_US.UTF-8");
            properties.setProperty("timezone", "UTC-8");
            try {
                this.connection = DriverManager.getConnection(jdbcUrl, properties);
                this.statement = this.connection.createStatement();
                System.out.println("Connected to " + jdbcUrl + " successfully.");
            }catch (Exception e){
                e.printStackTrace();
                System.out.println("Connect to " + jdbcUrl + " failed.");
            }
        }
    }

    public static void closeConnection(){
        // 手动关闭资源
        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 创建database
     * @param databaseName 必填
     */
    public void createDatabase(String databaseName) throws SQLException {
        if(!StringUtils.isBlank(databaseName)){
            statement.executeUpdate("CREATE DATABASE IF NOT EXISTS " + databaseName);
            System.out.println("Database created successfully.");
        }
    }

    /**
     * 使用或insert或修改的烧起来语句
     * @param sql sql语句
     */
    public void useOrInsertSql(String sql) throws SQLException {
        if(!StringUtils.isBlank(sql)){
            log.info("TDengine执行sql语句:{}", sql);
            int a = statement.executeUpdate(sql);
            log.info("执行成功! 更改行数:{}", a);
        }
    }

    /**
     * 执行sql(无论是否返回结果),将结果注入到指定的类型实例中,且返回
     * 当查询到的数据大于一个时,取第一个
     * <p>
     * 对象遵从以下说明<br/>
     * 1.对象字段为String类型,数据库类型(通过jdbc读取到的)无论什么类型,都将调用Object.toString方法注入值<br/>
     * 2.对象字段为数据库类型(通过jdbc读取到的)一致的情况下,将会直接注入<br/>
     * 3.对象字段与数据库类型(通过jdbc读取到的)不一致的情况下,将尝试使用{@link Class#cast(Object)}方法转型,失败此值会是类型默认值(故实体推荐使用封装类型)<br/>
     * 4.对象字段为{@link Date}时,数据库类型为Date才可以注入,如果为long(例如TDengine)将会被当作毫秒的时间戳注入<br/>
     * @param sql   要执行的sql
     * @param clazz 要注入的实体类型
     * @param <T>   要注入的实体类型
     * @param databaseColumnHumpToLine 是否需要下划线转驼峰
     */
    public <T> T getOne(String sql, Class<T> clazz,boolean databaseColumnHumpToLine) throws IllegalAccessException, InstantiationException, SQLException {
        ArrayList<Method> methods = getSetterMethods(clazz);
        log.info("TDengine执行sql语句:{}", sql);
        ResultSet resultSet = statement.executeQuery(sql);
        log.info("执行成功,查询到的数据:",resultSet);
        //只有一个结果直接下一个就行
        resultSet.next();
        return resultSetToObject(resultSet, methods, clazz,databaseColumnHumpToLine);
    }

    /**
     * 执行sql(无论是否返回结果),将结果注入到指定的类型实例中,且返回
     * @param sql 要查询的sql语句
     * @param clazz 方法类
     * @param databaseColumnHumpToLine 是否启用驼峰转下划线
     * @param <T> 要注入的实体类型
     * @throws Exception
     */
    public <T> List<T> getList(String sql,Class<T> clazz,boolean databaseColumnHumpToLine) throws Exception{
        List<T> list = new ArrayList<>();
        log.info("TDengine执行sql语句:{}", sql);
        try(ResultSet resultSet = statement.executeQuery(sql);){
            log.info("执行成功,查询到的数据:",resultSet);
            // 获取所有的set方法,如果没有set方法,直接返回为空
            ArrayList<Method> setterMethods = getSetterMethods(clazz);
            while (resultSet.next()) {
                list.add(resultSetToObject(resultSet, setterMethods, clazz,databaseColumnHumpToLine));
            }
            return list;
        }catch (Exception e){
            throw e;
        }
    }


    /**
     * 通过setter method,获取到其对应的属性名
     *
     * @param method
     * @return
     */
    public static String getFieldNameBySetter(Method method)
    {
        return toLowerCaseFirstOne(method.getName().substring(3));
    }

    /**
     * 首字母转小写
     */
    public static String toLowerCaseFirstOne(String s)
    {
        if (Character.isLowerCase(s.charAt(0)))
        {
            return s;
        }
        else
        {
            return Character.toLowerCase(s.charAt(0)) + s.substring(1);
        }
    }

    /**
     *
     * @param databaseColumnHumpToLine 是否需要启动下划线转驼峰
     */
    public <T> T resultSetToObject(ResultSet resultSet, List<Method> setterMethods, Class<T> clazz,boolean databaseColumnHumpToLine) throws IllegalAccessException, InstantiationException {
        T result;
        try {
            result = clazz.newInstance();
        }catch (InstantiationException e) {
            System.out.println("请检查类" + clazz.getCanonicalName() + "是否有无参构造方法");
            throw e;
        }


        for (Method method : setterMethods) {
            try {
                String fieldName = getFieldNameBySetter(method);

                //因为标准的setter方法只会有一个参数,所以取一个就行了
                Class getParamClass = method.getParameterTypes()[0];

                //获得查询的结果
                Object resultObject;

                //是否启用驼峰转下划线规则获得数据库字段名
                resultObject = this.ResultSetGetObject(resultSet,databaseColumnHumpToLine,getParamClass,fieldName);
                //如果实体类的类型是String类型,那么无论x数据库类型是什么,都调用其toString方法获取值
                if (getParamClass.equals(String.class)) {
                    method.invoke(result, resultObject.toString());
                }else if (getParamClass.equals(Date.class) && resultObject.getClass().equals(Long.class)) {
                    method.invoke(result, new Date((Long) resultObject));
                } else {
                    try {
                        method.invoke(result, resultObject);
                    } catch (IllegalArgumentException e) {
                        //对象字段与数据库类型(通过jdbc读取到的)不一致的情况下,将尝试强制转型
                        method.invoke(result, getParamClass.cast(resultObject));
                    }
                }
            }
            catch (Exception ignored) {
                //所有的转型都失败了,则使用默认值
            }
        }

        return result;
    }

    public static Object ResultSetGetObject(ResultSet resultSet,Boolean humToLine,Class paramClass,String fieldName) throws SQLException {
        if(humToLine){
            fieldName = humpToLine(fieldName);
        }

        Object result = null;
        // 如果是String类型的,通过ResultSet.getObject根本获取不到数据,获取的会乱码,所以我们要根据ResultSet.getString进行获取
        if(paramClass.equals(String.class)){
            result = resultSet.getString(fieldName);
        }else{
            result = resultSet.getObject(fieldName);
        }
        return result;
    }



    /**
     * 获取指定类型方法的所有的setter方法
     */
    public static ArrayList<Method> getSetterMethods(Class clazz){
        Method[] methods = clazz.getMethods();

        ArrayList<Method> setterMothodsList = new ArrayList<>();

        for (Method m : methods) {
            if (m.getName().startsWith("set")) {
                setterMothodsList.add(m);
            }
        }

        if(setterMothodsList.size()>0){
            return setterMothodsList;
        }
        return null;
    }



    /**
     * 往表里添加一个对象
     * @param tableName 必填 table名称
     * @param obj 必填,要添加的对象
     */
    public void insert(String tableName,Object obj) throws SQLException {
        if(!StringUtils.isBlank(tableName) && null != obj){
            Map<String, Object> map = MapUtil.objectToMap(obj);
            StringBuilder builder = new StringBuilder();
            builder.append("INSERT INTO ").append(tableName);
            builder.append(mapToSQL(map));
            String sql =builder.toString();
            System.out.println(sql);
            statement.executeUpdate(sql);
        }
    }

    public static String mapToSQL(Map<String, Object> map)
    {
        StringBuilder builder = new StringBuilder();
        Set<Map.Entry<String, Object>> set = map.entrySet();

        StringBuilder keys = new StringBuilder(" ");
        StringBuilder value = new StringBuilder(" ");

        for (Map.Entry<String, Object> entry : set)
        {
            keys.append(humpToLine(entry.getKey())).append(",");
            try
            {
                if (entry.getValue().getClass().equals(Date.class))
                {
                    Date d = (Date) entry.getValue();
                    value.append(d.getTime()).append(",");
                }
                else
                {
                    value.append("'").append(entry.getValue()).append("'").append(",");
                }
            }
            catch (Exception ignored)
            {

            }
        }

        keys.deleteCharAt(keys.length() - 1);
        value.deleteCharAt(value.length() - 1);

        builder.append(" (").append(keys).append(") VALUES( ").append(value).append(")");
        return builder.toString();
    }

    /**
     * 驼峰转下划线,效率比上面高
     */
    public static String humpToLine(String str)
    {
        Matcher matcher = humpPattern.matcher(str);
        StringBuffer sb = new StringBuffer();
        while (matcher.find())
        {
            matcher.appendReplacement(sb, "_" + matcher.group(0).toLowerCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }


}

下面是TDengineUtil的其他方法,有需要的可以看以下

java 复制代码
package com.apex.iot.utils.utilModel;

import com.apex.iot.utils.MapUtil;
import com.taosdata.jdbc.TSDBDriver;

import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class TDengineUtilTest {

    private Connection connection;
    private boolean databaseColumnHumpToLine;

    /**
     * @param url                      url 例如 : "jdbc:TAOS://127.0.0.1:6020/netuo_iot"
     * @param username                 例如: "root"
     * @param password                 例如: "taosdata"
     * @param databaseColumnHumpToLine 是否需要数据库列名下划线转驼峰
     */
    public TDengineUtilTest(String url, String username, String password, boolean databaseColumnHumpToLine) throws ClassNotFoundException, SQLException
    {
        Class.forName("com.taosdata.jdbc.TSDBDriver");
        String jdbcUrl = url;
        Properties connProps = new Properties();
        connProps.setProperty(TSDBDriver.PROPERTY_KEY_USER, username);
        connProps.setProperty(TSDBDriver.PROPERTY_KEY_PASSWORD, password);
        connProps.setProperty(TSDBDriver.PROPERTY_KEY_CONFIG_DIR, "/etc/taos");
        connProps.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
        connProps.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
        connProps.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
        this.connection = DriverManager.getConnection(jdbcUrl, connProps);
        this.databaseColumnHumpToLine = databaseColumnHumpToLine;
    }

    /**
     * @param connection
     * @param databaseColumnHumpToLine
     */
    public TDengineUtilTest(Connection connection, boolean databaseColumnHumpToLine)
    {
        this.connection = connection;
        this.databaseColumnHumpToLine = databaseColumnHumpToLine;
    }


    /**
     * 执行sql(无论是否返回结果),将结果注入到指定的类型实例中,且返回
     * 当查询到的数据大于一个时,取第一个
     * <p>
     * 对象遵从以下说明<br/>
     * 1.对象字段为String类型,数据库类型(通过jdbc读取到的)无论什么类型,都将调用Object.toString方法注入值<br/>
     * 2.对象字段为数据库类型(通过jdbc读取到的)一致的情况下,将会直接注入<br/>
     * 3.对象字段与数据库类型(通过jdbc读取到的)不一致的情况下,将尝试使用{@link Class#cast(Object)}方法转型,失败此值会是类型默认值(故实体推荐使用封装类型)<br/>
     * 4.对象字段为{@link Date}时,数据库类型为Date才可以注入,如果为long(例如TDengine)将会被当作毫秒的时间戳注入<br/>
     *
     * @param sql   要执行的sql
     * @param clazz 要注入的实体类型
     * @param <T>   要注入的实体类型
     * @return
     * @throws IllegalAccessException
     * @throws InstantiationException
     * @throws SQLException
     */
    public <T> T getOne(String sql, Class<T> clazz) throws IllegalAccessException, InstantiationException, SQLException
    {
        Method[] setterMethods = getSetterMethods(clazz);
        ResultSet resultSet = connection.createStatement().executeQuery(sql);

        //只有一个结果直接下一个就行
        resultSet.next();

        return resultSetToObject(resultSet, setterMethods, clazz);
    }


    /**
     * 执行sql(无论是否返回结果),将结果注入到指定的类型实例中,且返回
     * 当查询到的结果没有时,返回一个大小为0的list;
     * <p>
     * 对象遵从以下说明<br/>
     * 1.对象字段为String类型,数据库类型(通过jdbc读取到的)无论什么类型,都将调用Object.toString方法注入值<br/>
     * 2.对象字段为数据库类型(通过jdbc读取到的)一致的情况下,将会直接注入<br/>
     * 3.对象字段与数据库类型(通过jdbc读取到的)不一致的情况下,将尝试使用{@link Class#cast(Object)}方法转型,失败此值会是类型默认值(故实体推荐使用封装类型)<br/>
     * 4.对象字段为{@link Date}时,数据库类型为Date才可以注入,如果为long(例如TDengine)将会被当作毫秒的时间戳注入<br/>
     *
     * @param sql   要执行的sql
     * @param clazz 要注入的实体类型
     * @param <T>   要注入的实体类型
     * @return
     * @throws IllegalAccessException
     * @throws InstantiationException
     * @throws SQLException
     */
    public <T> List<T> getList(String sql, Class<T> clazz) throws IllegalAccessException, InstantiationException, SQLException
    {
        List<T> list = new ArrayList<>();

        Method[] setterMethods = getSetterMethods(clazz);
        ResultSet resultSet = connection.createStatement().executeQuery(sql);

        while (resultSet.next())
        {
            list.add(resultSetToObject(resultSet, setterMethods, clazz));
        }
        return list;
    }

    /**
     * 插入对象到指定的表里面
     *
     * @param tableName
     * @param o
     * @return
     * @throws SQLException
     */
    @SuppressWarnings("all")
    public boolean insert(String tableName, Object o) throws SQLException
    {
        Map<String, Object> map = MapUtil.objectToMap(o);

        String sql = createInsertSql(tableName, map);
        return connection.createStatement().execute(sql);
    }


    public boolean insertWithStable(String tableName, String sTableName, Object o, String... tags) throws SQLException
    {

        Map<String, Object> map = MapUtil.objectToMap(o);

        String sql = createInsertStableSql(tableName,sTableName, map,tags);
        return connection.createStatement().execute(sql);

    }

    /**
     * 生成插入Stable的sql语句
     *
     * @param tableName
     * @param map
     * @return
     */
    public static String createInsertStableSql(String tableName, String sTbaleName, Map<String, Object> map, String... tags)
    {
        StringBuilder builder = new StringBuilder();
        builder.append("INSERT INTO ").append(tableName);
        builder.append(stableToSQL(sTbaleName, tags));
        builder.append(mapToSQL(map));

        return builder.toString();
    }

    private static String stableToSQL(String sTableName, String... tags)
    {
        StringBuilder builder = new StringBuilder();
        builder.append(" using ").append(sTableName).append(" TAGS ( ");
        for (String tag : tags)
        {
            builder.append("'").append(tag).append("',");
        }
        builder.deleteCharAt(builder.length() - 1).append(" ) ");

        return builder.toString();
    }

    /**
     * 生成插入sql语句
     *
     * @param tableName
     * @param map
     * @return
     */
    public static String createInsertSql(String tableName, Map<String, Object> map)
    {
        StringBuilder builder = new StringBuilder();
        builder.append("INSERT INTO ").append(tableName);
        builder.append(mapToSQL(map));

        return builder.toString();
    }

    public static String mapToSQL(Map<String, Object> map)
    {
        StringBuilder builder = new StringBuilder();
        Set<Map.Entry<String, Object>> set = map.entrySet();

        StringBuilder keys = new StringBuilder(" ");
        StringBuilder value = new StringBuilder(" ");

        for (Map.Entry<String, Object> entry : set)
        {
            keys.append(humpToLine(entry.getKey())).append(",");
            try
            {
                if (entry.getValue().getClass().equals(Date.class))
                {
                    Date d = (Date) entry.getValue();
                    value.append(d.getTime()).append(",");
                }
                else
                {
                    value.append("'").append(entry.getValue()).append("'").append(",");
                }
            }
            catch (Exception ignored)
            {

            }
        }

        keys.deleteCharAt(keys.length() - 1);
        value.deleteCharAt(value.length() - 1);

        builder.append(" (").append(keys).append(") VALUES( ").append(value).append(")");
        return builder.toString();
    }


    /**
     * 将resultSet注入到指定的类型实例中,且返回
     * 对象遵从以下说明<br/>
     * 1.对象字段为String类型,数据库类型(通过jdbc读取到的)无论什么类型,都将调用Object.toString方法注入值<br/>
     * 2.对象字段为数据库类型(通过jdbc读取到的)一致的情况下,将会直接注入<br/>
     * 3.对象字段与数据库类型(通过jdbc读取到的)不一致的情况下,将尝试使用{@link Class#cast(Object)}方法转型,失败此值会是类型默认值(故实体推荐使用封装类型)<br/>
     * 4.对象字段为{@link Date}时,数据库类型为Date才可以注入,如果为long(例如TDengine)将会被当作毫秒的时间戳注入<br/>
     * <p>
     * 注意,此方法只会注入一个结果,不会循环{@link ResultSet#next()}方法,请从外部调用。<br/>
     * 传入setterMethods的目的是为了方便外部循环使用此方法,这样方法内部不会重复调用,提高效率<br/>
     *
     * @param resultSet     查询结果,一定要是{@link ResultSet#next()}操作过的,不然没有数据
     * @param setterMethods clazz对应的所有setter方法,可以使用{@link this#getSetterMethods(Class)}获取
     * @param clazz         注入对象类型
     * @param <T>           注入对象类型
     * @return
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    public <T> T resultSetToObject(ResultSet resultSet, Method[] setterMethods, Class<T> clazz) throws IllegalAccessException, InstantiationException
    {
        T result;
        try
        {
            result = clazz.newInstance();
        }
        catch (InstantiationException e)
        {
            System.out.println("请检查类" + clazz.getCanonicalName() + "是否有无参构造方法");
            throw e;
        }


        for (Method method : setterMethods)
        {
            try
            {
                String fieldName = getFieldNameBySetter(method);

                //因为标准的setter方法只会有一个参数,所以取一个就行了
                Class getParamClass = method.getParameterTypes()[0];


                //获得查询的结果
                Object resultObject;

                //是否启用驼峰转下划线规则获得数据库字段名
                if (databaseColumnHumpToLine)
                {
                    resultObject = resultSet.getObject(humpToLine(fieldName));
                }
                else
                {
                    resultObject = resultSet.getObject(fieldName);
                }

                //如果实体类的类型是String类型,那么无论x数据库类型是什么,都调用其toString方法获取值
                if (getParamClass.equals(String.class))
                {
                    method.invoke(result, resultObject.toString());
                }
                else if (getParamClass.equals(Date.class) && resultObject.getClass().equals(Long.class))
                {
                    method.invoke(result, new Date((Long) resultObject));
                }
                else
                {
                    try
                    {
                        method.invoke(result, resultObject);
                    }
                    catch (IllegalArgumentException e)
                    {
                        //对象字段与数据库类型(通过jdbc读取到的)不一致的情况下,将尝试强制转型
                        method.invoke(result, getParamClass.cast(resultObject));
                    }
                }
            }
            catch (Exception ignored)
            {
                //所有的转型都失败了,则使用默认值
            }
        }

        return result;
    }

    /**
     * 通过setter method,获取到其对应的属性名
     *
     * @param method
     * @return
     */
    public static String getFieldNameBySetter(Method method)
    {
        return toLowerCaseFirstOne(method.getName().substring(3));
    }


    /**
     * 获取指定类型方法的所有的setter方法
     * 方法属性名为key,对应的方法为value
     *
     * @param clazz
     * @return
     */
    public static Map<String, Method> getSetterMethodsMap(Class clazz)
    {
        Method[] methods = clazz.getMethods();
        Map<String, Method> setterMethods = new HashMap<>(methods.length / 2);

        for (Method m : methods)
        {
            if (m.getName().startsWith("set"))
            {
                setterMethods.put(toLowerCaseFirstOne(m.getName().substring(3)), m);
            }
        }
        return setterMethods;
    }

    /**
     * 获取指定类型方法的所有的setter方法
     *
     * @param clazz
     * @return
     */
    public static Method[] getSetterMethods(Class clazz)
    {
        Method[] methods = clazz.getMethods();
        Method[] setterMethods = new Method[methods.length / 2];

        int i = 0;
        for (Method m : methods)
        {
            if (m.getName().startsWith("set"))
            {
                setterMethods[i] = m;
                i++;
            }
        }
        return setterMethods;
    }

    /**
     * 首字母转小写
     */
    public static String toLowerCaseFirstOne(String s)
    {
        if (Character.isLowerCase(s.charAt(0)))
        {
            return s;
        }
        else
        {
            return Character.toLowerCase(s.charAt(0)) + s.substring(1);
        }
    }


    /**
     * 首字母转大写
     */
    public static String toUpperCaseFirstOne(String s)
    {
        if (Character.isUpperCase(s.charAt(0)))
        {
            return s;
        }
        else
        {
            return Character.toUpperCase(s.charAt(0)) + s.substring(1);
        }
    }

    private static Pattern linePattern = Pattern.compile("_(\\w)");

    /**
     * 下划线转驼峰
     */
    public static String lineToHump(String str)
    {
        str = str.toLowerCase();
        Matcher matcher = linePattern.matcher(str);
        StringBuffer sb = new StringBuffer();
        while (matcher.find())
        {
            matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    private static Pattern humpPattern = Pattern.compile("[A-Z]");

    /**
     * 驼峰转下划线,效率比上面高
     */
    public static String humpToLine(String str)
    {
        Matcher matcher = humpPattern.matcher(str);
        StringBuffer sb = new StringBuffer();
        while (matcher.find())
        {
            matcher.appendReplacement(sb, "_" + matcher.group(0).toLowerCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }


}

四、然后可以创建实体类了

java 复制代码
package com.apex.iot.device.model;

import lombok.Data;

import java.io.Serializable;
import java.util.Date;

/**
 * 数据处理model
 * 数据在TDengine中
 * @CreateDate:2025-03-14
 */
@Data
public class DeviceModel implements Serializable {

    // 时间 == 必须
    private Date createTime;
    // 设备名字/设备id
    private String deviceId;
    // 标签值
    private String ip;
    // 值
    private Object value;
    // 类型
    private String valueType;
    //采集状态
    private int status;
    // 设备名称
    private String deviceName;
    // 设备parentName
    private String deviceParentName;
    // int类型的value值
    private Integer intValue;
    // 布尔类型的value值
    private Boolean booleanValue;
    // 小数类型的value值
    private Float floatValue;
    private Date ts;



}

五、创建service。这个service中的方法用的第一种util中的方法。

java 复制代码
@Service
@Slf4j
public class DeviceService {
	
	//TDengine中的superTable的名字
    private static final String superTable = "super_table";
    // database
    private static final String DATABASE = "database";
	
	// 连接地址、用户名、密码
    @Value("${tdengine.datasource.location}")
    private String host ;

    @Value("${tdengine.datasource.username}")
    private String username ;

    @Value("${tdengine.datasource.password}")
    private String password ;

	// 获取TDengine的utl方法
	public String getTDengineUrl(){
        return "jdbc:TAOS://" + host + ":6030/?user=" + username + "&password=" + password;
    }

	/**
     * 将数据存入TDengine中
     * 原生方法存储
     */
    public void saveToTDengine(List<DeviceModel> deviceList) throws Exception{
        TDengineUtil util1 = new TDengineUtil(this.getTDengineUrl());
        // 先连接database
        util1.useOrInsertSql("use " + DATABASE + ";");

        // 拼接sql字符串
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append("insert into ");
        for(DeviceModel deviceModel : deviceList){
            stringBuffer.append(deviceModel.getDeviceId());
            stringBuffer.append(" using ");
            stringBuffer.append(superTable);
            stringBuffer.append(" tags('");
            stringBuffer.append(deviceModel.getDeviceId());
            stringBuffer.append("',");
            if(StringUtils.isBlank(deviceModel.getDeviceName())){
                stringBuffer.append("null");
            }else{
                stringBuffer.append("'");
                stringBuffer.append(deviceModel.getDeviceName());
                stringBuffer.append("',");
            }
            if(StringUtils.isBlank(deviceModel.getDeviceParentName())){
                stringBuffer.append("null");
            }else{
                stringBuffer.append("'");
                stringBuffer.append(deviceModel.getDeviceParentName());
                stringBuffer.append("',");
            }
            if(StringUtils.isBlank(deviceModel.getIp())){
                stringBuffer.append("null");
            }else{
                stringBuffer.append("'");
                stringBuffer.append(deviceModel.getIp());
                stringBuffer.append("') values (");
            }
            stringBuffer.append(deviceModel.getCreateTime().getTime());
            stringBuffer.append(",");
            if(null == deviceModel.getIntValue()){
                stringBuffer.append("null,");
            }else{
                stringBuffer.append(deviceModel.getIntValue());
                stringBuffer.append(",");
            }
            if(null == deviceModel.getBooleanValue()){
                stringBuffer.append("null,");
            }else{
                stringBuffer.append(deviceModel.getBooleanValue());
                stringBuffer.append(",");
            }
            if(null == deviceModel.getFloatValue()){
                stringBuffer.append("null, ");
            }else {
                stringBuffer.append(deviceModel.getFloatValue());
                stringBuffer.append(", ");
            }
            stringBuffer.append(deviceModel.getStatus());
            stringBuffer.append(") ");
        }
        stringBuffer.append(";");
        System.out.println(stringBuffer.toString());
        // 执行sql语句,将数据存入数据库
        util1.useOrInsertSql(stringBuffer.toString());
        TDengineUtil.closeConnection();
    }

	 /**
     * 在TDengine中获取设备信息
     */
    public DeviceModel getDeviceMsgByTDengine(String deviceId) throws Exception {
        if(StringUtils.isBlank(deviceId)){
            return null;
        }
        TDengineUtil util = new TDengineUtil(this.getTDengineUrl());
        util.useOrInsertSql("use " + DATABASE + ";");
        String sql = "select ts,ip,device_parent_name,device_name,int_value,boolean_value,float_value,status from " + superTable + " where device_id = '"+deviceId+"' order by ts desc limit 1";
        log.info("打印的sql语句:{}", sql);
        DeviceModel device = util.getOne(sql,DeviceModel.class,true);
        TDengineUtil.closeConnection();
        if(null != device && null != device.getBooleanValue()){
            device.setValue(device.getBooleanValue());
            return device;
        }
        if(null != device && null != device.getFloatValue()){
            device.setValue(device.getFloatValue());
            return device;
        }
        if(null != device && null != device.getIntValue()){
            device.setValue(device.getIntValue());
            return device;
        }
        return device;
}

六、使用controller进行测试。这边就不编写了。

后来用了mapper方法,因为原生方法怕自己忘记close。

mapper方法在主页中《springCloud集成tdengine(原生和mapper方式) 其一》篇

相关推荐
TFHoney5 小时前
Java面试第十一山!《SpringCloud框架》
java·spring cloud·面试
小嘚7 小时前
springCloud的学习
学习·spring·spring cloud
创码小奇客13 小时前
深入理解 Java 泛型:从为啥用到咋高级用
java·后端·spring
杰瑞学AI15 小时前
Devops之Docker:Docker入门
运维·nginx·spring cloud·docker·云原生·容器·devops
neoooo16 小时前
打造一个 Spring Boot Starter:实现字符串工具库并探讨其价值
java·spring boot·spring
Stimd16 小时前
【重写SpringFramework】条件判定(chapter 4-4)
java·后端·spring
不修×蝙蝠19 小时前
SpringBoot 第二课(Ⅰ) 整合springmvc(详解)
java·spring boot·后端·spring·整合springmvc
都叫我大帅哥20 小时前
Spring框架中@Conditional注解全面解析
spring
withelios20 小时前
从Servlet 到SpringMVC
后端·spring