neo4j / neo4j-jdbc

Official Neo4j JDBC Driver
http://neo4j.github.io/neo4j-jdbc/
Apache License 2.0
135 stars 53 forks source link

Parsing decimal error #170

Closed crazyyanchao closed 6 years ago

crazyyanchao commented 6 years ago

I stored decimals in the neo4j database and reported an error while using Java jdbc access

java.sql.SQLException: An SQLException was provoked by the following failure: org.neo4j.driver.v1.exceptions.value.LossyCoercion: Cannot coerce FLOAT to Java float without losing precision
    at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:118)
    at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:77)
    at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:74)
code location: search.getString(i)
 while (search.next()) {
                columnNum = search.getMetaData().getColumnCount();
                for (int i = 1; i <= columnNum; i++) { 
                    stringList.add(search.getString(i));
                }

And then I try convert to JSON but fail search.getObject(i) demo data (how to convert to JSON):

{influenceScore=542.19896, eid=1541, dep_id=1, create_time=2018-07-31 23:59:59, end_time=2018-07-31 23:59:59, start_time=2018-06-01 00:00:00, user_id=299, name=week thing, influenceScorePercentage=0.999723, _id=20311, category=17, _labels=[Label1, Label2], status=1}
omarlarus commented 6 years ago

Hi @crazyyanchao , can you provide us the Cypher code used to create the data and the whole java code (sql query + resultStatement management), please? The JSON problem is not clear, we need some more details. If it isn't related to the "float" problem, it's worth to create another issue.

crazyyanchao commented 6 years ago

Hi @crazyyanchao , can you provide us the Cypher code used to create the data and the whole java code (sql query + resultStatement management), please? The JSON problem is not clear, we need some more details. If it isn't related to the "float" problem, it's worth to create another issue.

I query <MATCH (n:Label1) RETURN n LIMIT 10> // !!! 1.The attributes of the node have decimals. 2.search.getObject Cannot convert to JSON!

Attachments are the means of parsing the result set.

package casia.isiteam.knowledgegraph.common.model;
import casia.isiteam.knowledgegraph.services.visualinter.Neo4jDataUtils;
import casia.isiteam.knowledgegraph.utils.DbUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.apache.log4j.Logger;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class Test {

    private static Logger logger = Logger.getLogger(Test.class);

    public static JSONObject exetueCypherJDBC(String cypher) {
        logger.info(cypher);
        JSONObject jsonObject = null;
        Connection con = null;
        PreparedStatement pre = null;
        ResultSet result = null;
        try {
            long startTime = System.nanoTime();
            ComboPooledDataSource dataSourcePool = DbUtil.getConNeo4jPool();
            con = dataSourcePool.getConnection();
            pre = con.prepareStatement(cypher);
            result = pre.executeQuery();
            jsonObject = getNeo4jResult(result);
            long endTime = System.nanoTime();
            long consume = (endTime - startTime) / 1000000;
            logger.info("Cypher match " + consume + "ms");
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DbUtil.closeAll(result, pre, con);
        }
        return jsonObject;
    }

    public static JSONObject getNeo4jResult(ResultSet search) {
        // 遍历结果
        JSONObject results = new JSONObject(); //Final result
        JSONArray neoResults = new JSONArray();  //data array
        JSONObject result = new JSONObject(); //result
        JSONArray data = new JSONArray();  //data array
        JSONObject graph = new JSONObject(); //graph object
        JSONObject datas = new JSONObject(); //datas object

        JSONArray nodes = new JSONArray();
        JSONArray relationShips = new JSONArray();
        try {

            int columnNum;
            List<String> stringList = new ArrayList<String>();
            int stringListSize;
            String str;
            Object jsonData = null;

            while (search.next()) {
                columnNum = search.getMetaData().getColumnCount();
                for (int i = 1; i <= columnNum; i++) {  // (p1,p2,p3,p4,p5...n1,n2,n3,n4,n5...)

                    // search.getString error When I execute the node query <MATCH (n:Label1) RETURN 10 LIMIT 10>
                    // !!! The attributes of the node have decimals
                    stringList.add(search.getString(i));

                }
                stringListSize = stringList.size();
                for (int i = 0; i < stringListSize; i++) {
                    str = stringList.get(i);
                    if (str != null) {
                        //结果转换成array
                        try {
                            jsonData = JSON.parse(str);
                        } catch (Exception e) {
                            System.out.println("返回数据时错误的str:" + str);
                        }
                        //遍历结果
                        if (jsonData != null) {
                            JSONObject resultList = new JSONObject();
                            //判断结果为点还是线
                            // 返回路径
                            if (jsonData instanceof JSONArray) { //如果是 jsonArray 则为线
                                resultList = Neo4jDataUtils.getPathData(jsonData);
                                for (Object value : resultList.getJSONArray("nodes")) {
                                    if (!nodes.contains(value)) {
                                        nodes.add(value);
                                    }
                                }
                                for (Object value : resultList.getJSONArray("relationships")) {
                                    if (!relationShips.contains(value)) {
                                        relationShips.add(value);
                                    }
                                }
                            } else if (jsonData instanceof JSONObject) { //否则为点
                                // 返回节点
                                resultList = Neo4jDataUtils.getNodeData(jsonData);
                                if (!nodes.contains(resultList)) {
                                    nodes.add(resultList);
                                }
                            }
                        }
                    }
                }
                stringList.clear();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        datas.put("nodes", nodes);
        datas.put("relationships", relationShips);
        graph.put("graph", datas);
        data.add(graph);
        result.put("columns", "");
        result.put("data", data);
        neoResults.add(result);
        results.put("results", neoResults);
        return results;
    }
}
omarlarus commented 6 years ago

Hi @crazyyanchao , when you execute the Cypher statement "MATCH (n:Label1) RETURN 10 LIMIT 10" the database return to you the number "10" because there's no variables in the "RETURN" clause. However, even if you did a typo and the query is "MATCH (n:Label1) RETURN n LIMIT 10", when you call the column count you have 1 and it means the node (n), and it throws the exception you wrote. We're looking for the error in order to manage this situation better than now (in the 3.4 version).

Looking to your code you can fix it executing this Cypher statement "MATCH (n:Label1) RETURN n LIMIT 10" and use the getObject method that returns a Map<String,Object> when the output is a node.

crazyyanchao commented 6 years ago

Thanks @omarlarus I typed the wrong code ~.~. MATCH (n:Label1) RETURN n LIMIT 10 But, search.getObject convert to JSON ERROR! I need to transform relationships and nodes to JSON. NODE is {OBJECT}, RELATIONSHIP is []! How to use a method to solve? It soupport to convert n and p! I can not understand!

omarlarus commented 6 years ago

Hi @crazyyanchao , you can choose 2 ways:

If you need a quick preview I can send you a jar of the developer version of jdbc driver 3.4.

crazyyanchao commented 6 years ago

@omarlarus Please send it to my email address,Thanks! EMAIL: yanchaoma@foxmail.com

omarlarus commented 6 years ago

@crazyyanchao you can download a preview with the fix here

omarlarus commented 6 years ago

@crazyyanchao I sent you the 3.4 version of jdbc driver, that need the 1.6.1 version of neo4j-java-driver.

Try to change the dependency, please

        <dependency>
            <groupId>org.neo4j.driver</groupId>
            <artifactId>neo4j-java-driver</artifactId>
            <version>1.6.1</version>
        </dependency>

PS: you can check the dependencies looking at here in the README section.

crazyyanchao commented 6 years ago

@omarlarus OK, Thanks!

jexp commented 6 years ago

Merged the pull request, will be in the next release.