账号密码登录
微信安全登录
微信扫描二维码登录

登录后绑定QQ、微信即可实现信息互通

手机验证码登录
找回密码返回
邮箱找回 手机找回
注册账号返回
其他登录方式
分享
  • 收藏
    X
    在多线程下不能操作数据库么?
    • 2019-04-21 00:00
    • 10
    103
    0

    我这边有个项目,是使用客户端socekt 连接服务获取数据并保存到数据库,但是由于是一个客户端连接多个服务,目前只想到了多线程,但是在线程下一直无法保存数据会是什么原因导致的

    private JdbcTemplate jdbcTemplate = null;
        private InputStream in;
        private Socket socket = null;
        private String ip = null;
        private int port = 0;
        private ProductionDataRepository repository;
        private JSONObject json = null;
        private ProductionData SelectProdata = null;
        private int connect_Info_id = 0;
        private int a = 1;
        private int b = 2;
        public SaveDataThread(String ip,int port,ProductionDataRepository repository,ProductionData SelectProdata,int connect_Info_id,JdbcTemplate jdbcTemplate) throws UnknownHostException, IOException {
            this.port = port;
            this.ip = ip;
            this.repository = repository;
            this.SelectProdata = SelectProdata;
            this.connect_Info_id = connect_Info_id;
            this.jdbcTemplate = jdbcTemplate;
            socket = new Socket(ip, port);
        }
        @Transactional(rollbackOn=Exception.class)
        public synchronized void run() {
            
            System.out.println("线程-" + Thread.currentThread().getId());
            System.out.println(ip);
            System.out.println(port);
            
            ProductionData Prodata = null;
            boolean connectStatus = true;
            while(connectStatus) {
                try {
                    if(socket.getInputStream() == null) {
                        continue;
                    }
                    in = socket.getInputStream();
                } catch (IOException e2) {
                    // TODO Auto-generated catch block
                    e2.printStackTrace();
                }
                try {
                    socket.sendUrgentData(0xFF);
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                    socket = null;
                    connectStatus = false;
                }
                byte[] data=new byte[1024];
                int len = 0;
                try {
                    len = in.read(data);
                } catch (IOException e) {
                    System.out.println("ProductionDataServices的save方法中的in.read(data)调用异常,异常原因:"+e.getMessage());
                    e.printStackTrace();
                }
                System.out.println(new String(data,0,len));
                json = JSONObject.fromObject(new String(data,0,len));
                /*json = getPorductionData(as.get("ip").toString(),Integer.parseInt(as.get("port").toString()));*/
                if(json == null) {
                    System.out.println("json对象为 null,未获取到数据!");
                    continue;
                }
                //查询生产数据id 等于 production_data_id的数据
                //获取
    
                //如果当天存在数据则对数据进行修改
                String state = null;
                if(SelectProdata != null) {
                     // 0 暂停 1 运行 2 未连接
                    if(json.getInt("State") == 0) {
                        state = "暂停";
                    } else if(json.getInt("State") == 1) {
                        state = "运行";
                    }
                    //判断是否为空,防止未连接时存在对象但是开始时间为空
                    if(SelectProdata.getStartTime() == null) {
                        repository.updateStart_time(new Timestamp(System.currentTimeMillis()),SelectProdata.getId());
                    }
                    
                    
                        System.out.println();
                        int OK = SelectProdata.getOk()+json.getInt("OK");
                        System.out.println("对象ng:    "+SelectProdata.getOk());
                        System.out.println("json对象NG:    "+json.getInt("OK"));
                        System.out.println(""+SelectProdata.getOk()+"+"+json.getInt("OK")+"="+(SelectProdata.getOk()+json.getInt("OK")));
                        System.out.println("int总和ng:    "+OK);
                        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
                        String sql = "update ss_production_data pd set "
                                + "pd.ok = "+(SelectProdata.getOk()+json.getInt("OK"))+","
                                + "pd.ng = "+(SelectProdata.getNg()+json.getInt("NG"))+","
                                + "pd.total = "+(SelectProdata.getOk()+json.getInt("OK")+SelectProdata.getNg()+json.getInt("NG"))+","
                                + "pd.state = '"+state+"',"
                                + "pd.owe_hole = "+(SelectProdata.getOweHole()+json.getInt("Hole"))+","
                                + "pd.long_hair = "+(SelectProdata.getLongHair()+json.getInt("LongHair"))+","
                                + "pd.Long_short_hair="+(SelectProdata.getLongShortHair()+json.getInt("UnevenHair"))+","
                                + "pd.loose_wool="+(SelectProdata.getLooseWool()+json.getInt("LooseHair"))+","
                                + "pd.implantation_error ="+(SelectProdata.getImplantationError()+json.getInt("WrongHair"))+","
                                + "pd.difference_hair = "+(SelectProdata.getDifferenceHair()+json.getInt("CrushHair"))+","
                                + "pd.dirty= "+(SelectProdata.getDirty()+json.getInt("Dirt"))+","
                                + "pd.end_time = '"+df.format(new Date())+"'"
                                + "where pd.id = "+SelectProdata.getId()+"";
                        
                        
                        save(sql);
                        
                        
                                
                    
                    continue;
                }
                
                
                    Prodata = new  ProductionData();
                    //否则因为不存在id修改将变成添加
                    Prodata.setName(connect_Info_id+"号机器");//机器名称
                    Prodata.setConnectInfoId(connect_Info_id);//绑定连接信息id
                    Prodata.setOk(json.getInt("OK"));//合格
                    Prodata.setNg(json.getInt("NG"));//不合格
                    Prodata.setTotal((json.getInt("OK")+json.getInt("NG")));//总数
                    // 0 暂停 1 运行 2 未连接
                    if(json.getInt("State") == 0) {
                        Prodata.setState("暂停");
                    } else if(json.getInt("State") == 1) {
                        Prodata.setState("运行");
                    }
                    Prodata.setOweHole(json.getInt("Hole"));//欠孔
                    Prodata.setLongHair(json.getInt("LongHair"));//长毛
                    Prodata.setLongShortHair(json.getInt("UnevenHair"));//长短毛
                    Prodata.setLooseWool(json.getInt("LooseHair"));//散毛
                    Prodata.setImplantationError(json.getInt("WrongHair"));//植错毛
                    Prodata.setDifferenceHair(json.getInt("CrushHair"));//差毛
                    Prodata.setDirty(json.getInt("Dirt"));//脏毛
                    Prodata.setStartTime(new Timestamp(System.currentTimeMillis()));
                    Prodata.setStartTime(new Timestamp(System.currentTimeMillis()));
                    Prodata.setCreateTime(new Timestamp(System.currentTimeMillis()));
                    repository.save(Prodata);
                
            }
        }
        public void save(String sql) {
            String driver = "com.mysql.cj.jdbc.Driver";
            String url = "jdbc:mysql://127.0.0.1:3306/hair_planting_machine?serverTimezone=GMT%2B8&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true";
            String username = "root";
            String password = "123456";
            Connection conn = null;
            try {
                Class.forName(driver); //classLoader,加载对应驱动
                conn = (Connection) DriverManager.getConnection(url, username, password);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            int i = 0;
            PreparedStatement pstmt;
            try {
                pstmt = (PreparedStatement) conn.prepareStatement(sql);
                i = pstmt.executeUpdate();
                System.out.println("resutl: " + i);
                pstmt.close();
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    2
    打赏
    收藏
    点击回答
    您的回答被采纳后将获得:提问者悬赏的 10 元积分
        全部回答
    • 0
    • 时光划破青春 普通会员 1楼

      在多线程环境下,通常情况下是无法直接操作数据库的,因为数据库通常是由多个不同的线程或进程共享的。这些线程或进程共享同一套数据库系统,它们需要访问数据库的资源,如表、索引、存储过程、触发器等,这些资源是互斥的,也就是说,一个线程不能同时访问同一个数据库表中的所有数据,而另一个线程也不能同时访问同一数据库表中的任何一条数据。

      然而,可以使用数据库的数据库访问接口(如SQL API)在多线程环境下操作数据库。以下是一些使用数据库API操作数据库的基本步骤:

      1. 获取数据库连接:在多线程环境中,你需要使用数据库的API来获取数据库连接,这通常涉及到在主程序中创建一个数据库连接对象,然后在其他线程中使用这个连接对象来执行数据库查询。

      java Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydatabase", "username", "password");

      1. 执行SQL查询:在获取数据库连接后,你可以使用SQL API执行查询。例如,你可以使用Statement对象来执行SQL查询,PreparedStatement对象来执行预编译的SQL查询,以及ResultSet对象来获取查询结果。

      java Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM mytable");

      1. 获取结果集中的数据:使用ResultSet对象获取查询结果,然后遍历这个结果集,获取每条数据并对其进行处理,如插入、更新或删除等。

      java while (rs.next()) { int id = rs.getInt("id"); String name = rs.getString("name"); // 处理数据... } rs.close(); stmt.close(); conn.close();

      1. 提交更改:如果查询结果中存在需要修改的记录,你可能需要提交更改,这通常涉及到使用PreparedStatement对象执行一个更新操作。例如,你可以使用以下代码向表中添加一条新的记录:

      java PreparedStatement pstmt = conn.prepareStatement("INSERT INTO mytable (id, name) VALUES (?, ?)"); pstmt.setInt(1, 100); pstmt.setString(2, "John Doe"); pstmt.executeUpdate();

      1. 处理错误:在执行任何操作时,都可能会出现错误。你需要在每次执行操作后捕获并处理可能的错误,如SQLExceptionConnectionExceptionPreparedStatementException等,以避免程序崩溃。

      java try { // 执行操作... } catch (SQLException e) { e.printStackTrace(); } catch (ConnectionException e) { e.printStackTrace(); } catch (PreparedStatementException e) { e.printStackTrace(); }

      需要注意的是,虽然在多线程环境下可以使用数据库API操作数据库,但直接修改数据库表中的数据可能会导致数据不一致,因此在进行大规模数据操作时,通常会采取分表、缓存、事务等方式来保证数据的一致性和完整性。

    更多回答
    扫一扫访问手机版
    • 回到顶部
    • 回到顶部