分销商的主键采用了单独的表来完成,因为多个用户同时生成主键,那么就存在访问共享资源的情况,必须保持线程同步。
两种解决方案:
1)java中使用关键字synchronized关键字对方法同步
2)可以使用数据库的悲观锁,例如:select value from t_table_id where table_name=? for update;
左侧的再输入悲观锁语句,就不能查询出数据来了。
悲观锁:
整个数据处理的过程,数据对外界的修改持保守态度。整个数据处理过程中,处于锁定的状态。本次事务提交之前,外界无法修改该记录。体现了数据库的独占性。
乐观锁:
基于版本标识来实现的。读数据时候,将版本号读出,修改之后,对其版本号加1。提交的时候,将提交数据的版本数据和数据库中的版本号对比,大于数据库中的版本,予以提交。
所以源代码的语句:
/** * */ package com.bjpowernode.drp.util; import java.awt.image.ConvolveOp; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; /** * @ClassName:IdGenerator * @Description:ID生成器 * @author wm * @date 2016年1月15日下午6:41:06 */ public class IdGenerator { /** * 根据表名生成该表的序列 * @param tableName * @return 返回生成的序列 * 使用synchronized实现线程同步问题 */ //锁住线程1 //public static synchronized int generate(String tableName){ public int generate(String tableName){ //TODO:id 生成器 //锁住线程2 /*synchronized (this) { }*/ //数据库的悲观锁 String sql="select value from t_table_id where table_name=? for update"; Connection conn =null; PreparedStatement pstmt=null; ResultSet rs=null; int value=0; try { conn=DbUtil.getConnection(); pstmt=conn.prepareStatement(sql); pstmt.setString(1, tableName); rs=pstmt.executeQuery(); if(!rs.next()){ throw new RuntimeException(); } value =rs.getInt("value"); value++; modifyValueField(conn,tableName,value); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(); }finally{ DbUtil.close(rs); DbUtil.close(pstmt); DbUtil.close(conn); } return value; } /** * 根据表名更新序列字段的值 * @param conn * @param tableName * @param value * @throws SQLException */ private static void modifyValueField(Connection conn,String tableName,int value) throws SQLException{ String sql="update t_table_id set value=? where table_name=?"; PreparedStatement pstmt=null; try { pstmt=conn.prepareStatement(sql); pstmt.setInt(1, value); pstmt.setString(2, tableName); pstmt.executeUpdate(); } finally{ DbUtil.close(pstmt); } } public static void main(String[] args){ //完成测试 int retValue=IdGenerator.generate("t_client"); System.out.println(retValue); } }