ResultSet can not re-read row data for column 1.

SQLServer JDBC驱动异常解析
本文探讨了在使用SQLServer数据库及微软JDBC驱动时出现的特定异常原因,并提供了通过调整字段读取顺序或更换为jtds驱动的解决方案。

org.springframework.jdbc.UncategorizedSQLException: Hibernate operation: could not initialize a collection:


java.sql.SQLException: [Microsoft][SQLServer 2000 Driver for JDBC]ResultSet can not re-read row data for column 1.
 at com.microsoft.jdbc.base.BaseExceptions.createException(Unknown Source)
 at com.microsoft.jdbc.base.BaseExceptions.getException(Unknown Source)
 at com.microsoft.jdbc.base.BaseResultSet.validateColumnIndex(Unknown Source)
 at com.microsoft.jdbc.base.BaseResultSet.getInt(Unknown Source)
 at com.microsoft.jdbc.base.BaseResultSet.getInt(Unknown Source)
 at org.apache.commons.dbcp.DelegatingResultSet.getInt(DelegatingResultSet.java:236)
  . . . . . .省略掉的这一部分是堆栈信息

 

使用SQLServer 数据库时,可能发生此异常,原因是微软自己的jdbc驱动不支持同一个记录的字段的重复读取,因为微软加入了text,image这种类型的支持,就限制了字段的回读功能.

 

(我在使用hibernate级联查询的时候出现了这种异常lazy=false的级联查询)

 

解决方法:按照顺序(从左到右的顺序)读取字段,例如(getString(1),getString(2),getString(3)....);当然这个是微软jdbc驱动的一个bug,我们也可以不用他的驱动,自己到网上下载jtds.jar驱动,使用这种驱动就不会出现上面的异常了.

 

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/ruanxiaping/archive/2008/09/28/2993161.aspx

2025-09-23 14:14:58.177 [reactor-http-nio-2] DEBUG reactor.netty.http.server.HttpServerOperations - [812192b7, L:/192.168.10.122:9000 - R:/192.168.10.122:12766] New http connection, requesting read 2025-09-23 14:14:58.177 [reactor-http-nio-2] DEBUG reactor.netty.transport.TransportConfig - [812192b7, L:/192.168.10.122:9000 - R:/192.168.10.122:12766] Initialized pipeline DefaultChannelPipeline{(reactor.left.httpCodec = io.netty.handler.codec.http.HttpServerCodec), (reactor.left.httpTrafficHandler = reactor.netty.http.server.HttpTrafficHandler), (reactor.right.reactiveBridge = reactor.netty.channel.ChannelOperationsHandler)} 2025-09-23 14:14:58.240 [reactor-http-nio-2] DEBUG reactor.netty.http.server.HttpServerOperations - [812192b7, L:/192.168.10.122:9000 - R:/192.168.10.122:12766] Increasing pending responses, now 1 2025-09-23 14:14:58.280 [reactor-http-nio-2] DEBUG reactor.netty.http.server.HttpServer - [812192b7-1, L:/192.168.10.122:9000 - R:/192.168.10.122:12766] Handler is being applied: org.springframework.http.server.reactive.ReactorHttpHandlerAdapter@516cf1d9 2025-09-23 14:14:58.385 [reactor-http-nio-2] DEBUG o.s.web.server.adapter.HttpWebHandlerAdapter - [812192b7-1] HTTP POST "/master/shipperPart/listPartsWithStatus?supplierId=28&shipperId=3" 2025-09-23 14:14:58.440 [reactor-http-nio-2] DEBUG o.s.w.r.r.m.a.RequestMappingHandlerMapping - [812192b7-1] Mapped to com.hvlink.controller.ShipperPartController#listPartsWithStatus(Integer, Integer) 2025-09-23 14:14:58.558 [reactor-http-nio-2] DEBUG org.mybatis.spring.SqlSessionUtils - Creating a new SqlSession 2025-09-23 14:14:58.621 [reactor-http-nio-2] DEBUG org.mybatis.spring.SqlSessionUtils - SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@76b115c] was not registered for synchronization because synchronization is not active 2025-09-23 14:14:58.663 [reactor-http-nio-2] DEBUG o.springframework.jdbc.datasource.DataSourceUtils - Fetching JDBC Connection from DataSource 2025-09-23 14:14:58.664 [reactor-http-nio-2] DEBUG o.m.spring.transaction.SpringManagedTransaction - JDBC Connection [ConnectionID:1 ClientConnectionId: bd2cbe9a-b87f-4c42-9c85-577ad4546ee0] will not be managed by Spring 2025-09-23 14:14:58.678 [reactor-http-nio-2] DEBUG c.h.m.master.PartMapper.selectPartsWithBindStatus - ==> Preparing: SELECT p.id, p.part_code, p.part_desc, p.supplier_code, CASE WHEN sp.part_id IS NOT NULL THEN 1 ELSE 0 END AS assigned FROM tm_part p LEFT JOIN tm_shipper_part sp ON p.part_code = sp.part_id AND sp.shipper_id = ? WHERE p.supplier_code = ( SELECT supplier_code FROM tm_part WHERE id = ? ) ORDER BY p.part_code 2025-09-23 14:14:58.900 [reactor-http-nio-2] DEBUG c.h.m.master.PartMapper.selectPartsWithBindStatus - ==> Parameters: 3(Integer), 28(Integer) 2025-09-23 14:14:59.167 [reactor-http-nio-2] DEBUG org.mybatis.spring.SqlSessionUtils - Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@76b115c] 2025-09-23 14:14:59.248 [reactor-http-nio-2] DEBUG o.s.beans.factory.xml.XmlBeanDefinitionReader - Loaded 11 bean definitions from class path resource [org/springframework/jdbc/support/sql-error-codes.xml] 2025-09-23 14:14:59.248 [reactor-http-nio-2] DEBUG o.s.b.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'DB2' 2025-09-23 14:14:59.255 [reactor-http-nio-2] DEBUG o.s.b.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'Derby' 2025-09-23 14:14:59.257 [reactor-http-nio-2] DEBUG o.s.b.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'H2' 2025-09-23 14:14:59.257 [reactor-http-nio-2] DEBUG o.s.b.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'HDB' 2025-09-23 14:14:59.259 [reactor-http-nio-2] DEBUG o.s.b.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'HSQL' 2025-09-23 14:14:59.259 [reactor-http-nio-2] DEBUG o.s.b.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'Informix' 2025-09-23 14:14:59.260 [reactor-http-nio-2] DEBUG o.s.b.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'MS-SQL' 2025-09-23 14:14:59.260 [reactor-http-nio-2] DEBUG o.s.b.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'MySQL' 2025-09-23 14:14:59.260 [reactor-http-nio-2] DEBUG o.s.b.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'Oracle' 2025-09-23 14:14:59.260 [reactor-http-nio-2] DEBUG o.s.b.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'PostgreSQL' 2025-09-23 14:14:59.260 [reactor-http-nio-2] DEBUG o.s.b.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'Sybase' 2025-09-23 14:14:59.261 [reactor-http-nio-2] DEBUG o.s.jdbc.support.SQLErrorCodesFactory - Looking up default SQLErrorCodes for DataSource [com.hvlink.config.DataSourceConfig$1@eed890d] 2025-09-23 14:14:59.267 [reactor-http-nio-2] DEBUG o.springframework.jdbc.datasource.DataSourceUtils - Fetching JDBC Connection from DataSource 2025-09-23 14:14:59.270 [reactor-http-nio-2] DEBUG o.s.jdbc.support.SQLErrorCodesFactory - SQL error codes for 'Microsoft SQL Server' found 2025-09-23 14:14:59.270 [reactor-http-nio-2] DEBUG o.s.jdbc.support.SQLErrorCodesFactory - Caching SQL error codes for DataSource [com.hvlink.config.DataSourceConfig$1@eed890d]: database product name is 'Microsoft SQL Server' 2025-09-23 14:14:59.272 [reactor-http-nio-2] DEBUG o.s.j.support.SQLErrorCodeSQLExceptionTranslator - Unable to translate SQLException with Error code '245', will now try the fallback translator 2025-09-23 14:14:59.273 [reactor-http-nio-2] DEBUG o.s.jdbc.support.SQLStateSQLExceptionTranslator - Extracted SQL state class 'S0' from value 'S0001' 2025-09-23 14:14:59.307 [reactor-http-nio-2] ERROR com.hvlink.controller.ShipperPartController - 查询零件列表失败 supplierId:28, shipperId:3 org.springframework.jdbc.UncategorizedSQLException: ### Error querying database. Cause: com.microsoft.sqlserver.jdbc.SQLServerException: 当前命令期间出错(完成状态 0)。在将 varchar 值 'P00118936101' 转换成数据类型 int 时失败。 ### The error may exist in file [D:\SHProjects\hv-link-backend\dao\target\classes\mapper\master\PartMapper.xml] ### The error may involve com.hvlink.mapper.master.PartMapper.selectPartsWithBindStatus ### The error occurred while handling results ### SQL: SELECT p.id, p.part_code, p.part_desc, p.supplier_code, CASE WHEN sp.part_id IS NOT NULL THEN 1 ELSE 0 END AS assigned FROM tm_part p LEFT JOIN tm_shipper_part sp ON p.part_code = sp.part_id AND sp.shipper_id = ? WHERE p.supplier_code = ( SELECT supplier_code FROM tm_part WHERE id = ? ) ORDER BY p.part_code ### Cause: com.microsoft.sqlserver.jdbc.SQLServerException: 当前命令期间出错(完成状态 0)。在将 varchar 值 'P00118936101' 转换成数据类型 int 时失败。 ; uncategorized SQLException; SQL state [S0001]; error code [245]; 当前命令期间出错(完成状态 0)。在将 varchar 值 'P00118936101' 转换成数据类型 int 时失败。; nested exception is com.microsoft.sqlserver.jdbc.SQLServerException: 当前命令期间出错(完成状态 0)。在将 varchar 值 'P00118936101' 转换成数据类型 int 时失败。 at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:92) at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:441) at com.sun.proxy.$Proxy115.selectList(Unknown Source) at org.mybatis.spring.SqlSessionTemplate.selectList(SqlSessionTemplate.java:224) at com.baomidou.mybatisplus.core.override.MybatisMapperMethod.executeForMany(MybatisMapperMethod.java:166) at com.baomidou.mybatisplus.core.override.MybatisMapperMethod.execute(MybatisMapperMethod.java:77) at com.baomidou.mybatisplus.core.override.MybatisMapperProxy$PlainMethodInvoker.invoke(MybatisMapperProxy.java:148) at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.invoke(MybatisMapperProxy.java:89) at com.sun.proxy.$Proxy127.selectPartsWithBindStatus(Unknown Source) at com.hvlink.service.impl.ShipperPartServiceImpl.listPartsWithStatus(ShipperPartServiceImpl.java:37) at com.hvlink.service.impl.ShipperPartServiceImpl$$FastClassBySpringCGLIB$$80781e7d.invoke(<generated>) at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) at org.springframework.aop.framework.CglibAopProxy.invokeMethod(CglibAopProxy.java:386) at org.springframework.aop.framework.CglibAopProxy.access$000(CglibAopProxy.java:85) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:703) at com.hvlink.service.impl.ShipperPartServiceImpl$$EnhancerBySpringCGLIB$$eadee9b3.listPartsWithStatus(<generated>) at com.hvlink.controller.ShipperPartController.listPartsWithStatus(ShipperPartController.java:33) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.web.reactive.result.method.InvocableHandlerMethod.lambda$invoke$0(InvocableHandlerMethod.java:145) at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:125) at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onNext(FluxOnAssembly.java:539) at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1839) at reactor.core.publisher.MonoZip$ZipCoordinator.signal(MonoZip.java:258) at reactor.core.publisher.MonoZip$ZipInner.onNext(MonoZip.java:347) at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onNext(FluxOnAssembly.java:539) at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.onNext(MonoPeekTerminal.java:180) at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onNext(FluxOnAssembly.java:539) at reactor.core.publisher.FluxDefaultIfEmpty$DefaultIfEmptySubscriber.onNext(FluxDefaultIfEmpty.java:101) at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onNext(FluxOnAssembly.java:539) at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onNext(FluxSwitchIfEmpty.java:74) at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onNext(FluxOnAssembly.java:539) at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2400) at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.request(FluxOnAssembly.java:649) at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.set(Operators.java:2196) at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onSubscribe(Operators.java:2070) at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onSubscribe(FluxOnAssembly.java:633) at reactor.core.publisher.FluxFlatMap.trySubscribeScalarMap(FluxFlatMap.java:192) at reactor.core.publisher.MonoFlatMap.subscribeOrReturn(MonoFlatMap.java:53) at reactor.core.publisher.Mono.subscribe(Mono.java:4475) at reactor.core.publisher.MonoZip.subscribe(MonoZip.java:129) at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64) at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:53) at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64) at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.subscribeNext(MonoIgnoreThen.java:240) at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onComplete(MonoIgnoreThen.java:203) at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onComplete(FluxOnAssembly.java:549) at reactor.core.publisher.MonoFlatMap$FlatMapMain.onComplete(MonoFlatMap.java:181) at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onComplete(FluxOnAssembly.java:549) at reactor.core.publisher.Operators.complete(Operators.java:137) at reactor.core.publisher.MonoZip.subscribe(MonoZip.java:121) at reactor.core.publisher.Mono.subscribe(Mono.java:4490) at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.subscribeNext(MonoIgnoreThen.java:263) at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:51) at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64) at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:157) at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onNext(FluxOnAssembly.java:539) at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onNext(FluxSwitchIfEmpty.java:74) at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onNext(FluxOnAssembly.java:539) at reactor.core.publisher.MonoNext$NextSubscriber.onNext(MonoNext.java:82) at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onNext(FluxOnAssembly.java:539) at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.innerNext(FluxConcatMap.java:282) at reactor.core.publisher.FluxConcatMap$ConcatMapInner.onNext(FluxConcatMap.java:863) at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onNext(FluxOnAssembly.java:539) at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:129) at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onNext(FluxOnAssembly.java:539) at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.onNext(MonoPeekTerminal.java:180) at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onNext(FluxOnAssembly.java:539) at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2400) at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.request(FluxOnAssembly.java:649) at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.request(MonoPeekTerminal.java:139) at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.request(FluxOnAssembly.java:649) at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.request(FluxMapFuseable.java:171) at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.request(FluxOnAssembly.java:649) at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.set(Operators.java:2196) at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onSubscribe(Operators.java:2070) at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onSubscribe(FluxOnAssembly.java:633) at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onSubscribe(FluxMapFuseable.java:96) at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onSubscribe(FluxOnAssembly.java:633) at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.onSubscribe(MonoPeekTerminal.java:152) at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onSubscribe(FluxOnAssembly.java:633) at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:55) at reactor.core.publisher.Mono.subscribe(Mono.java:4490) at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.drain(FluxConcatMap.java:451) at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.onSubscribe(FluxConcatMap.java:219) at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onSubscribe(FluxOnAssembly.java:633) at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:201) at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:83) at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64) at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:53) at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64) at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:53) at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64) at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:53) at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64) at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:53) at reactor.core.publisher.Mono.subscribe(Mono.java:4490) at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.subscribeNext(MonoIgnoreThen.java:263) at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:51) at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64) at reactor.core.publisher.MonoDeferContextual.subscribe(MonoDeferContextual.java:55) at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64) at reactor.netty.http.server.HttpServer$HttpServerHandle.onStateChange(HttpServer.java:1112) at reactor.netty.ReactorNetty$CompositeConnectionObserver.onStateChange(ReactorNetty.java:707) at reactor.netty.transport.ServerTransport$ChildObserver.onStateChange(ServerTransport.java:481) at reactor.netty.http.server.HttpServerOperations.onInboundNext(HttpServerOperations.java:626) at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:114) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) at reactor.netty.http.server.HttpTrafficHandler.channelRead(HttpTrafficHandler.java:230) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436) at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:346) at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:318) at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788) at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724) at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562) at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997) at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) at java.lang.Thread.run(Thread.java:750) Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: 当前命令期间出错(完成状态 0)。在将 varchar 值 'P00118936101' 转换成数据类型 int 时失败。 at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:259) at com.microsoft.sqlserver.jdbc.SQLServerResultSet$FetchBuffer$FetchBufferTokenHandler.onDone(SQLServerResultSet.java:5456) at com.microsoft.sqlserver.jdbc.TDSParser.parse(tdsparser.java:103) at com.microsoft.sqlserver.jdbc.TDSParser.parse(tdsparser.java:42) at com.microsoft.sqlserver.jdbc.SQLServerResultSet$FetchBuffer.nextRow(SQLServerResultSet.java:5559) at com.microsoft.sqlserver.jdbc.SQLServerResultSet.fetchBufferNext(SQLServerResultSet.java:1821) at com.microsoft.sqlserver.jdbc.SQLServerResultSet.next(SQLServerResultSet.java:1079) at com.alibaba.druid.pool.DruidPooledResultSet.next(DruidPooledResultSet.java:56) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.apache.ibatis.logging.jdbc.ResultSetLogger.invoke(ResultSetLogger.java:69) at com.sun.proxy.$Proxy229.next(Unknown Source) at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleRowValuesForSimpleResultMap(DefaultResultSetHandler.java:359) at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleRowValues(DefaultResultSetHandler.java:335) at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleResultSet(DefaultResultSetHandler.java:308) at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleResultSets(DefaultResultSetHandler.java:201) at org.apache.ibatis.executor.statement.PreparedStatementHandler.query(PreparedStatementHandler.java:65) at org.apache.ibatis.executor.statement.RoutingStatementHandler.query(RoutingStatementHandler.java:79) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:64) at com.sun.proxy.$Proxy226.query(Unknown Source) at org.apache.ibatis.executor.SimpleExecutor.doQuery(SimpleExecutor.java:63) at org.apache.ibatis.executor.BaseExecutor.queryFromDatabase(BaseExecutor.java:325) at org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:156) at com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor.intercept(MybatisPlusInterceptor.java:81) at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:62) at com.sun.proxy.$Proxy225.query(Unknown Source) at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:151) at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:145) at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:140) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:427) ... 134 common frames omitted 2025-09-23 14:14:59.322 [reactor-http-nio-2] DEBUG o.s.w.r.r.m.annotation.ResponseBodyResultHandler - [812192b7-1] Using 'application/json' given [*/*] and supported [application/json, application/*+json, application/x-ndjson, text/event-stream] 2025-09-23 14:14:59.322 [reactor-http-nio-2] DEBUG o.s.w.r.r.m.annotation.ResponseBodyResultHandler - [812192b7-1] 0..1 [com.hvlink.common.Result<java.util.List<com.hvlink.entity.vo.master.PartVO>>] 2025-09-23 14:14:59.377 [reactor-http-nio-2] DEBUG o.s.http.codec.json.Jackson2JsonEncoder - [812192b7-1] Encoding [Result(status=500, msg=查询失败, data=null, timestamp=1758608099315)] 2025-09-23 14:14:59.458 [reactor-http-nio-2] DEBUG reactor.netty.http.server.HttpServerOperations - [812192b7-1, L:/192.168.10.122:9000 - R:/192.168.10.122:12766] Decreasing pending responses, now 0 2025-09-23 14:14:59.459 [reactor-http-nio-2] DEBUG reactor.netty.http.server.HttpServerOperations - [812192b7-1, L:/192.168.10.122:9000 - R:/192.168.10.122:12766] Last HTTP packet was sent, terminating the channel 2025-09-23 14:14:59.459 [reactor-http-nio-2] DEBUG reactor.netty.channel.ChannelOperations - [812192b7-1, L:/192.168.10.122:9000 - R:/192.168.10.122:12766] [HttpServer] Channel inbound receiver cancelled (operation cancelled). 2025-09-23 14:14:59.481 [reactor-http-nio-2] DEBUG o.s.web.server.adapter.HttpWebHandlerAdapter - [812192b7-1] Completed 200 OK 2025-09-23 14:14:59.487 [reactor-http-nio-2] DEBUG reactor.netty.http.server.HttpServerOperations - [812192b7-1, L:/192.168.10.122:9000 - R:/192.168.10.122:12766] Last HTTP response frame
最新发布
09-24
org.jkiss.dbeaver.model.sql.DBSQLException: SQL 错误 [1242] [21000]: Subquery returns more than 1 row at org.jkiss.dbeaver.model.impl.jdbc.exec.JDBCPreparedStatementImpl.executeStatement(JDBCPreparedStatementImpl.java:208) at org.jkiss.dbeaver.ui.editors.sql.execute.SQLQueryJob.executeStatement(SQLQueryJob.java:614) at org.jkiss.dbeaver.ui.editors.sql.execute.SQLQueryJob.lambda$2(SQLQueryJob.java:505) at org.jkiss.dbeaver.model.exec.DBExecUtils.tryExecuteRecover(DBExecUtils.java:194) at org.jkiss.dbeaver.ui.editors.sql.execute.SQLQueryJob.executeSingleQuery(SQLQueryJob.java:524) at org.jkiss.dbeaver.ui.editors.sql.execute.SQLQueryJob.extractData(SQLQueryJob.java:976) at org.jkiss.dbeaver.ui.editors.sql.SQLEditor$QueryResultsContainer.readData(SQLEditor.java:4155) at org.jkiss.dbeaver.ui.controls.resultset.ResultSetJobDataRead.lambda$0(ResultSetJobDataRead.java:123) at org.jkiss.dbeaver.model.exec.DBExecUtils.tryExecuteRecover(DBExecUtils.java:194) at org.jkiss.dbeaver.ui.controls.resultset.ResultSetJobDataRead.run(ResultSetJobDataRead.java:121) at org.jkiss.dbeaver.ui.controls.resultset.ResultSetViewer$ResultSetDataPumpJob.run(ResultSetViewer.java:5152) at org.jkiss.dbeaver.model.runtime.AbstractJob.run(AbstractJob.java:115) at org.eclipse.core.internal.jobs.Worker.run(Worker.java:63) Caused by: java.sql.SQLException: Subquery returns more than 1 row at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:130) at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122) at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:912) at com.mysql.cj.jdbc.ClientPreparedStatement.execute(ClientPreparedStatement.java:354) at org.jkiss.dbeaver.model.impl.jdbc.exec.JDBCPreparedStatementImpl.execute(JDBCPreparedStatementImpl.java:261) at org.jkiss.dbeaver.model.impl.jdbc.exec.JDBCPreparedStatementImpl.executeStatement(JDBCPreparedStatementImpl.java:205)这是我的错误信息
08-19
package org.example; import javax.swing.*; import javax.swing.table.DefaultTableModel; import java.awt.*; import java.awt.event.*; import java.math.BigDecimal; import java.sql.*; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; // 数据库工具类 class MySQL { private static final String URL = "jdbc:mysql://localhost:3306/cangchu"; private static final String USER = "root"; private static final String PASSWORD = "123456"; static { try { Class.forName("com.mysql.cj.jdbc.Driver"); } catch (ClassNotFoundException e) { showError("数据库驱动加载失败", e); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USER, PASSWORD); } // 用户验证 public static boolean validateUser(String username, String password) { String sql = "SELECT * FROM `管理员` WHERE `用户名`=? AND `密码`=?"; try (Connection conn = getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, username); pstmt.setString(2, password); return pstmt.executeQuery().next(); } catch (SQLException e) { showError("用户验证错误", e); return false; } } // 更新密码 public static boolean updatePassword(String username, String newPassword) { String sql = "UPDATE 管理员 SET 密码 = ? WHERE 用户名 = ?"; try (Connection conn = getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, newPassword); pstmt.setString(2, username); return pstmt.executeUpdate() > 0; } catch (SQLException e) { showError("密码更新错误", e); return false; } } // 读取表数据 public static List<Map<String, Object>> readTable(String tableName) { List<Map<String, Object>> result = new ArrayList<>(); String sql = "SELECT * FROM " + tableName; try (Connection conn = getConnection(); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql)) { ResultSetMetaData metaData = rs.getMetaData(); int columnCount = metaData.getColumnCount(); while (rs.next()) { Map<String, Object> row = new LinkedHashMap<>(); for (int i = 1; i <= columnCount; i++) { row.put(metaData.getColumnName(i), rs.getObject(i)); } result.add(row); } } catch (SQLException e) { showError("数据库查询错误", e); } return result; } // 执行更新操作 public static int executeUpdate(String sql, Object... params) { try (Connection conn = getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { for (int i = 0; i < params.length; i++) { pstmt.setObject(i + 1, params[i]); } return pstmt.executeUpdate(); } catch (SQLException e) { showError("数据库操作错误: " + sql, e); return -1; } } // 检查外键是否存在 public static boolean checkForeignKeyExists(String table, String column, String value) { String sql = "SELECT COUNT(*) FROM " + table + " WHERE " + column + " = ?"; try (Connection conn = getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, value); try (ResultSet rs = pstmt.executeQuery()) { return rs.next() && rs.getInt(1) > 0; } } catch (SQLException e) { showError("外键检查错误", e); return false; } } // 更新仓库容量 public static void updateWarehouseCapacity(String warehouseId, int amount, boolean isInbound) { String sql = "UPDATE 仓库 SET 剩余容量 = 剩余容量 + ? WHERE 仓库编号 = ?"; executeUpdate(sql, isInbound ? -amount : amount, warehouseId); } // 更新商品库存 public static void updateProductStock(String productId, int amount, boolean isInbound) { String sql = "UPDATE 商品 SET 库存 = 库存 + ? WHERE 商品编号 = ?"; executeUpdate(sql, isInbound ? amount : -amount, productId); } // 显示错误信息 static void showError(String message, Exception e) { String errorMsg = message + ": " + e.getMessage(); if (e instanceof SQLException) { SQLException sqlEx = (SQLException) e; errorMsg += "\nSQL状态: " + sqlEx.getSQLState(); errorMsg += "\n错误码: " + sqlEx.getErrorCode(); } JOptionPane.showMessageDialog(null, errorMsg, "数据库错误", JOptionPane.ERROR_MESSAGE); e.printStackTrace(); } } // 登录界面 class LoginScreen { private JFrame frame; private JTextField usernameField; private JPasswordField passwordField; public void show() { frame = new JFrame("用户登录"); frame.setSize(400, 250); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLocationRelativeTo(null); JPanel panel = new JPanel(new GridLayout(3, 2, 10, 10)); panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); panel.add(new JLabel("账号:")); usernameField = new JTextField(); panel.add(usernameField); panel.add(new JLabel("密码:")); passwordField = new JPasswordField(); panel.add(passwordField); JButton loginButton = new JButton("登录"); loginButton.addActionListener(e -> login()); JButton resetButton = new JButton("重置"); resetButton.addActionListener(e -> reset()); JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 10)); buttonPanel.add(loginButton); buttonPanel.add(resetButton); frame.add(panel, BorderLayout.CENTER); frame.add(buttonPanel, BorderLayout.SOUTH); frame.setVisible(true); } private void login() { String username = usernameField.getText().trim(); String password = new String(passwordField.getPassword()); if (username.isEmpty() || password.isEmpty()) { JOptionPane.showMessageDialog(frame, "账号和密码不能为空!"); return; } if (MySQL.validateUser(username, password)) { JOptionPane.showMessageDialog(frame, "登录成功!"); frame.dispose(); new MainMenu(username).setVisible(true); } else { JOptionPane.showMessageDialog(frame, "账号或密码错误!"); passwordField.setText(""); passwordField.requestFocus(); } } private void reset() { usernameField.setText(""); passwordField.setText(""); } public static void main(String[] args) { SwingUtilities.invokeLater(() -> new LoginScreen().show()); } } // 主菜单界面 class MainMenu extends JFrame { private String currentUser; public MainMenu(String username) { super("仓库管理系统 - 当前用户: " + username); this.currentUser = username; setSize(900, 600); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLocationRelativeTo(null); JTabbedPane tabPane = new JTabbedPane(); tabPane.addTab("仓库管理", new WarehouseManager().createPanel()); tabPane.addTab("商品管理", new ProductManager().createPanel()); tabPane.addTab("供应商管理", new SupplierManager().createPanel()); tabPane.addTab("出入库管理", new InventoryManager().createPanel()); tabPane.addTab("管理员管理", new AdminManager(currentUser).createPanel()); add(tabPane); } } // 仓库管理 class WarehouseManager { private JTable table; private DefaultTableModel model; public JPanel createPanel() { JPanel panel = new JPanel(new BorderLayout()); // 工具栏 JToolBar toolbar = new JToolBar(); JButton refreshBtn = new JButton("刷新"); JButton addBtn = new JButton("添加"); JButton editBtn = new JButton("修改"); JButton deleteBtn = new JButton("删除"); JButton searchBtn = new JButton("搜索"); refreshBtn.addActionListener(e -> refreshData()); addBtn.addActionListener(e -> addWarehouse()); editBtn.addActionListener(e -> editWarehouse()); deleteBtn.addActionListener(e -> deleteWarehouse()); toolbar.add(refreshBtn); toolbar.add(addBtn); toolbar.add(editBtn); toolbar.add(deleteBtn); // 搜索面板 JPanel searchPanel = new JPanel(); JTextField searchField = new JTextField(15); searchBtn.addActionListener(e -> searchWarehouse(searchField.getText())); searchPanel.add(new JLabel("仓库名称:")); searchPanel.add(searchField); searchPanel.add(searchBtn); // 表格 model = new DefaultTableModel() { @Override public boolean isCellEditable(int row, int column) { return false; } }; table = new JTable(model); table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); // 设置列名 model.setColumnIdentifiers(new String[]{"仓库编号", "仓库名", "总容量", "剩余容量"}); refreshData(); // 布局 JPanel topPanel = new JPanel(new BorderLayout()); topPanel.add(toolbar, BorderLayout.NORTH); topPanel.add(searchPanel, BorderLayout.CENTER); panel.add(topPanel, BorderLayout.NORTH); panel.add(new JScrollPane(table), BorderLayout.CENTER); return panel; } private void refreshData() { List<Map<String, Object>> data = MySQL.readTable("仓库"); model.setRowCount(0); for (Map<String, Object> row : data) { model.addRow(new Object[]{ row.get("仓库编号"), row.get("仓库名"), row.get("总容量"), row.get("剩余容量") }); } } private void searchWarehouse(String keyword) { List<Map<String, Object>> data = new ArrayList<>(); String sql = "SELECT * FROM 仓库 WHERE 仓库名 LIKE ?"; try (Connection conn = MySQL.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, "%" + keyword + "%"); ResultSet rs = pstmt.executeQuery(); while (rs.next()) { Map<String, Object> row = new LinkedHashMap<>(); row.put("仓库编号", rs.getString("仓库编号")); row.put("仓库名", rs.getString("仓库名")); row.put("总容量", rs.getInt("总容量")); row.put("剩余容量", rs.getInt("剩余容量")); data.add(row); } } catch (SQLException e) { MySQL.showError("搜索错误", e); } model.setRowCount(0); for (Map<String, Object> row : data) { model.addRow(new Object[]{ row.get("仓库编号"), row.get("仓库名"), row.get("总容量"), row.get("剩余容量") }); } } private void addWarehouse() { JDialog dialog = new JDialog((Frame) null, "添加仓库", true); dialog.setSize(400, 300); dialog.setLayout(new GridLayout(5, 2, 10, 10)); dialog.setLocationRelativeTo(null); JTextField idField = new JTextField(); JTextField nameField = new JTextField(); JTextField capacityField = new JTextField(); JTextField remainingField = new JTextField(); JButton submitBtn = new JButton("提交"); submitBtn.addActionListener(e -> { try { String id = idField.getText().trim(); String name = nameField.getText().trim(); int capacity = Integer.parseInt(capacityField.getText().trim()); int remaining = Integer.parseInt(remainingField.getText().trim()); // 验证输入 if (id.isEmpty() || name.isEmpty()) { JOptionPane.showMessageDialog(dialog, "仓库编号和名称不能为空!"); return; } if (capacity <= 0 || remaining < 0) { JOptionPane.showMessageDialog(dialog, "容量必须为正数!"); return; } if (remaining > capacity) { JOptionPane.showMessageDialog(dialog, "剩余容量必须等于总容量!"); return; } if (remaining <capacity) { JOptionPane.showMessageDialog(dialog, "剩余容量必须等于总容量!"); return; } // 执行SQL if (MySQL.executeUpdate( "INSERT INTO 仓库 (仓库编号, 仓库名, 总容量, 剩余容量) VALUES (?, ?, ?, ?)", id, name, capacity, remaining) > 0) { JOptionPane.showMessageDialog(dialog, "仓库添加成功!"); dialog.dispose(); refreshData(); } else { JOptionPane.showMessageDialog(dialog, "仓库添加失败!"); } } catch (NumberFormatException ex) { JOptionPane.showMessageDialog(dialog, "请输入有效的数字!"); } }); JButton cancelBtn = new JButton("取消"); cancelBtn.addActionListener(e -> dialog.dispose()); // 添加组件 dialog.add(new JLabel("仓库编号:")); dialog.add(idField); dialog.add(new JLabel("仓库名称:")); dialog.add(nameField); dialog.add(new JLabel("总容量:")); dialog.add(capacityField); dialog.add(new JLabel("剩余容量:")); dialog.add(remainingField); dialog.add(submitBtn); dialog.add(cancelBtn); dialog.setVisible(true); } private void editWarehouse() { int row = table.getSelectedRow(); if (row == -1) { JOptionPane.showMessageDialog(null, "请选择要修改的仓库"); return; } String id = (String) table.getValueAt(row, 0); String name = (String) table.getValueAt(row, 1); int capacity = (int) table.getValueAt(row, 2); int remaining = (int) table.getValueAt(row, 3); JDialog dialog = new JDialog((Frame) null, "修改仓库", true); dialog.setSize(400, 300); dialog.setLayout(new GridLayout(5, 2, 10, 10)); dialog.setLocationRelativeTo(null); JTextField idField = new JTextField(id); idField.setEditable(false); JTextField nameField = new JTextField(name); JTextField capacityField = new JTextField(String.valueOf(capacity)); JTextField remainingField = new JTextField(String.valueOf(remaining)); JButton submitBtn = new JButton("提交"); submitBtn.addActionListener(e -> { try { String newName = nameField.getText().trim(); int newCapacity = Integer.parseInt(capacityField.getText().trim()); int newRemaining = Integer.parseInt(remainingField.getText().trim()); // 验证输入 if (newName.isEmpty()) { JOptionPane.showMessageDialog(dialog, "仓库名称不能为空!"); return; } if (newCapacity <= 0 || newRemaining < 0) { JOptionPane.showMessageDialog(dialog, "容量必须为正数!"); return; } if (newRemaining > newCapacity) { JOptionPane.showMessageDialog(dialog, "剩余容量不能大于总容量!"); return; } // 执行SQL if (MySQL.executeUpdate( "UPDATE 仓库 SET 仓库名=?, 总容量=?, 剩余容量=? WHERE 仓库编号=?", newName, newCapacity, newRemaining, id) > 0) { JOptionPane.showMessageDialog(dialog, "仓库信息更新成功!"); dialog.dispose(); refreshData(); } else { JOptionPane.showMessageDialog(dialog, "仓库信息更新失败!"); } } catch (NumberFormatException ex) { JOptionPane.showMessageDialog(dialog, "请输入有效的数字!"); } }); JButton cancelBtn = new JButton("取消"); cancelBtn.addActionListener(e -> dialog.dispose()); // 添加组件 dialog.add(new JLabel("仓库编号:")); dialog.add(idField); dialog.add(new JLabel("仓库名称:")); dialog.add(nameField); dialog.add(new JLabel("总容量:")); dialog.add(capacityField); dialog.add(new JLabel("剩余容量:")); dialog.add(remainingField); dialog.add(submitBtn); dialog.add(cancelBtn); dialog.setVisible(true); } private void deleteWarehouse() { int row = table.getSelectedRow(); if (row == -1) { JOptionPane.showMessageDialog(null, "请选择要删除的仓库"); return; } String id = (String) table.getValueAt(row, 0); String name = (String) table.getValueAt(row, 1); int confirm = JOptionPane.showConfirmDialog( null, "确定要删除仓库: " + name + " (ID: " + id + ")?", "确认删除", JOptionPane.YES_NO_OPTION ); if (confirm == JOptionPane.YES_OPTION) { if (hasInventoryRecords(id)) { JOptionPane.showMessageDialog(null, "该仓库有出入库记录,无法删除!"); return; } if (MySQL.executeUpdate("DELETE FROM 仓库 WHERE 仓库编号=?", id) > 0) { JOptionPane.showMessageDialog(null, "仓库删除成功!"); refreshData(); } else { JOptionPane.showMessageDialog(null, "仓库删除失败!"); } } } private boolean hasInventoryRecords(String warehouseId) { String sql = "SELECT COUNT(*) FROM 出入库 WHERE 仓库ID = ?"; try (Connection conn = MySQL.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, warehouseId); try (ResultSet rs = pstmt.executeQuery()) { return rs.next() && rs.getInt(1) > 0; } } catch (SQLException e) { MySQL.showError("记录检查错误", e); return true; } } } // 商品管理 class ProductManager { private JTable table; private DefaultTableModel model; public JPanel createPanel() { JPanel panel = new JPanel(new BorderLayout()); // 工具栏 JToolBar toolbar = new JToolBar(); JButton refreshBtn = new JButton("刷新"); JButton addBtn = new JButton("添加"); JButton editBtn = new JButton("修改"); JButton deleteBtn = new JButton("删除"); refreshBtn.addActionListener(e -> refreshData()); addBtn.addActionListener(e -> addProduct()); editBtn.addActionListener(e -> editProduct()); deleteBtn.addActionListener(e -> deleteProduct()); toolbar.add(refreshBtn); toolbar.add(addBtn); toolbar.add(editBtn); toolbar.add(deleteBtn); // 搜索面板 JPanel searchPanel = new JPanel(); JTextField nameField = new JTextField(10); JTextField categoryField = new JTextField(10); JButton searchBtn = new JButton("搜索"); searchBtn.addActionListener(e -> searchProducts( nameField.getText().trim(), categoryField.getText().trim() )); searchPanel.add(new JLabel("商品名称:")); searchPanel.add(nameField); searchPanel.add(new JLabel("商品类别:")); searchPanel.add(categoryField); searchPanel.add(searchBtn); // 表格 model = new DefaultTableModel() { @Override public boolean isCellEditable(int row, int column) { return false; } }; table = new JTable(model); table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); // 设置列名 model.setColumnIdentifiers(new String[]{ "商品编号", "商品名", "供应商ID", "产地", "类别", "价格", "库存" }); refreshData(); // 布局 JPanel topPanel = new JPanel(new BorderLayout()); topPanel.add(toolbar, BorderLayout.NORTH); topPanel.add(searchPanel, BorderLayout.CENTER); panel.add(topPanel, BorderLayout.NORTH); panel.add(new JScrollPane(table), BorderLayout.CENTER); return panel; } private void refreshData() { List<Map<String, Object>> data = MySQL.readTable("商品"); model.setRowCount(0); for (Map<String, Object> row : data) { model.addRow(new Object[]{ row.get("商品编号"), row.get("商品名"), row.get("供应商ID"), row.get("产地"), row.get("类别"), row.get("价格"), row.get("库存") }); } } private void searchProducts(String name, String category) { List<Map<String, Object>> data = new ArrayList<>(); String sql = "SELECT * FROM 商品 WHERE 商品名 LIKE ? AND 类别 LIKE ?"; try (Connection conn = MySQL.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, "%" + name + "%"); pstmt.setString(2, "%" + category + "%"); ResultSet rs = pstmt.executeQuery(); while (rs.next()) { Map<String, Object> row = new LinkedHashMap<>(); row.put("商品编号", rs.getString("商品编号")); row.put("商品名", rs.getString("商品名")); row.put("供应商ID", rs.getString("供应商ID")); row.put("产地", rs.getString("产地")); row.put("类别", rs.getString("类别")); row.put("价格", rs.getBigDecimal("价格")); row.put("库存", rs.getInt("库存")); data.add(row); } } catch (SQLException e) { MySQL.showError("搜索错误", e); } model.setRowCount(0); for (Map<String, Object> row : data) { model.addRow(new Object[]{ row.get("商品编号"), row.get("商品名"), row.get("供应商ID"), row.get("产地"), row.get("类别"), row.get("价格"), row.get("库存") }); } } private void addProduct() { JDialog dialog = new JDialog((Frame) null, "添加商品", true); dialog.setSize(500, 400); dialog.setLayout(new GridLayout(7, 2, 10, 10)); dialog.setLocationRelativeTo(null); JTextField idField = new JTextField(); JTextField nameField = new JTextField(); JTextField supplierIdField = new JTextField(); JTextField originField = new JTextField(); JTextField categoryField = new JTextField(); JTextField priceField = new JTextField(); JTextField stockField = new JTextField("0"); // 默认库存为0 JButton submitBtn = new JButton("提交"); submitBtn.addActionListener(e -> { try { String id = idField.getText().trim(); String name = nameField.getText().trim(); String supplierId = supplierIdField.getText().trim(); String origin = originField.getText().trim(); String category = categoryField.getText().trim(); double price = Double.parseDouble(priceField.getText().trim()); int stock = Integer.parseInt(stockField.getText().trim()); // 验证输入 if (id.isEmpty() || name.isEmpty()) { JOptionPane.showMessageDialog(dialog, "商品编号和名称不能为空!"); return; } if (!MySQL.checkForeignKeyExists("供应商", "供应商编号", supplierId)) { JOptionPane.showMessageDialog(dialog, "供应商ID不存在!"); return; } if (price <= 0) { JOptionPane.showMessageDialog(dialog, "价格必须大于0!"); return; } if (stock < 0) { JOptionPane.showMessageDialog(dialog, "库存不能为负数!"); return; } // 执行SQL if (MySQL.executeUpdate( "INSERT INTO 商品 (商品编号, 商品名, 供应商ID, 产地, 类别, 价格, 库存) VALUES (?, ?, ?, ?, ?, ?, ?)", id, name, supplierId, origin, category, price, stock) > 0) { JOptionPane.showMessageDialog(dialog, "商品添加成功!"); dialog.dispose(); refreshData(); } else { JOptionPane.showMessageDialog(dialog, "商品添加失败!"); } } catch (NumberFormatException ex) { JOptionPane.showMessageDialog(dialog, "请输入有效的数字!"); } }); JButton cancelBtn = new JButton("取消"); cancelBtn.addActionListener(e -> dialog.dispose()); // 添加组件 dialog.add(new JLabel("商品编号:")); dialog.add(idField); dialog.add(new JLabel("商品名称:")); dialog.add(nameField); dialog.add(new JLabel("供应商ID:")); dialog.add(supplierIdField); dialog.add(new JLabel("产地:")); dialog.add(originField); dialog.add(new JLabel("类别:")); dialog.add(categoryField); dialog.add(new JLabel("价格:")); dialog.add(priceField); dialog.add(new JLabel("库存:")); dialog.add(stockField); dialog.add(submitBtn); dialog.add(cancelBtn); dialog.setVisible(true); } private void editProduct() { int row = table.getSelectedRow(); if (row == -1) { JOptionPane.showMessageDialog(null, "请选择要修改的商品"); return; } String id = (String) table.getValueAt(row, 0); String name = (String) table.getValueAt(row, 1); String supplierId = (String) table.getValueAt(row, 2); String origin = (String) table.getValueAt(row, 3); String category = (String) table.getValueAt(row, 4); BigDecimal price = (BigDecimal) table.getValueAt(row, 5); int stock = (int) table.getValueAt(row, 6); JDialog dialog = new JDialog((Frame) null, "修改商品", true); dialog.setSize(500, 400); dialog.setLayout(new GridLayout(7, 2, 10, 10)); dialog.setLocationRelativeTo(null); JTextField idField = new JTextField(id); idField.setEditable(false); JTextField nameField = new JTextField(name); JTextField supplierIdField = new JTextField(supplierId); JTextField originField = new JTextField(origin); JTextField categoryField = new JTextField(category); JTextField priceField = new JTextField(price.toString()); JTextField stockField = new JTextField(String.valueOf(stock)); JButton submitBtn = new JButton("提交"); submitBtn.addActionListener(e -> { try { String newName = nameField.getText().trim(); String newSupplierId = supplierIdField.getText().trim(); String newOrigin = originField.getText().trim(); String newCategory = categoryField.getText().trim(); double newPrice = Double.parseDouble(priceField.getText().trim()); int newStock = Integer.parseInt(stockField.getText().trim()); // 验证输入 if (newName.isEmpty()) { JOptionPane.showMessageDialog(dialog, "商品名称不能为空!"); return; } if (!MySQL.checkForeignKeyExists("供应商", "供应商编号", newSupplierId)) { JOptionPane.showMessageDialog(dialog, "供应商ID不存在!"); return; } if (newPrice <= 0) { JOptionPane.showMessageDialog(dialog, "价格必须大于0!"); return; } if (newStock < 0) { JOptionPane.showMessageDialog(dialog, "库存不能为负数!"); return; } // 执行SQL if (MySQL.executeUpdate( "UPDATE 商品 SET 商品名=?, 供应商ID=?, 产地=?, 类别=?, 价格=?, 库存=? WHERE 商品编号=?", newName, newSupplierId, newOrigin, newCategory, newPrice, newStock, id) > 0) { JOptionPane.showMessageDialog(dialog, "商品信息更新成功!"); dialog.dispose(); refreshData(); } else { JOptionPane.showMessageDialog(dialog, "商品信息更新失败!"); } } catch (NumberFormatException ex) { JOptionPane.showMessageDialog(dialog, "请输入有效的数字!"); } }); JButton cancelBtn = new JButton("取消"); cancelBtn.addActionListener(e -> dialog.dispose()); // 添加组件 dialog.add(new JLabel("商品编号:")); dialog.add(idField); dialog.add(new JLabel("商品名称:")); dialog.add(nameField); dialog.add(new JLabel("供应商ID:")); dialog.add(supplierIdField); dialog.add(new JLabel("产地:")); dialog.add(originField); dialog.add(new JLabel("类别:")); dialog.add(categoryField); dialog.add(new JLabel("价格:")); dialog.add(priceField); dialog.add(new JLabel("库存:")); dialog.add(stockField); dialog.add(submitBtn); dialog.add(cancelBtn); dialog.setVisible(true); } private void deleteProduct() { int row = table.getSelectedRow(); if (row == -1) { JOptionPane.showMessageDialog(null, "请选择要删除的商品"); return; } String id = (String) table.getValueAt(row, 0); String name = (String) table.getValueAt(row, 1); int confirm = JOptionPane.showConfirmDialog( null, "确定要删除商品: " + name + " (ID: " + id + ")?", "确认删除", JOptionPane.YES_NO_OPTION ); if (confirm == JOptionPane.YES_OPTION) { if (hasInventoryRecords(id)) { JOptionPane.showMessageDialog(null, "该商品有出入库记录,无法删除!"); return; } if (MySQL.executeUpdate("DELETE FROM 商品 WHERE 商品编号=?", id) > 0) { JOptionPane.showMessageDialog(null, "商品删除成功!"); refreshData(); } else { JOptionPane.showMessageDialog(null, "商品删除失败!"); } } } private boolean hasInventoryRecords(String productId) { String sql = "SELECT COUNT(*) FROM 出入库 WHERE 商品ID = ?"; try (Connection conn = MySQL.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, productId); try (ResultSet rs = pstmt.executeQuery()) { return rs.next() && rs.getInt(1) > 0; } } catch (SQLException e) { MySQL.showError("记录检查错误", e); return true; } } } // 供应商管理 class SupplierManager { private JTable table; private DefaultTableModel model; public JPanel createPanel() { JPanel panel = new JPanel(new BorderLayout()); // 工具栏 JToolBar toolbar = new JToolBar(); JButton refreshBtn = new JButton("刷新"); JButton addBtn = new JButton("添加"); JButton editBtn = new JButton("修改"); JButton deleteBtn = new JButton("删除"); refreshBtn.addActionListener(e -> refreshData()); addBtn.addActionListener(e -> addSupplier()); editBtn.addActionListener(e -> editSupplier()); deleteBtn.addActionListener(e -> deleteSupplier()); toolbar.add(refreshBtn); toolbar.add(addBtn); toolbar.add(editBtn); toolbar.add(deleteBtn); // 搜索面板 JPanel searchPanel = new JPanel(); JTextField nameField = new JTextField(10); JTextField regionField = new JTextField(10); JButton searchBtn = new JButton("搜索"); searchBtn.addActionListener(e -> searchSuppliers( nameField.getText().trim(), regionField.getText().trim() )); searchPanel.add(new JLabel("供应商名称:")); searchPanel.add(nameField); searchPanel.add(new JLabel("所在地区:")); searchPanel.add(regionField); searchPanel.add(searchBtn); // 表格 model = new DefaultTableModel() { @Override public boolean isCellEditable(int row, int column) { return false; } }; table = new JTable(model); table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); // 设置列名 model.setColumnIdentifiers(new String[]{ "供应商编号", "供应商名", "供应商地址", "供应商电话" }); refreshData(); // 布局 JPanel topPanel = new JPanel(new BorderLayout()); topPanel.add(toolbar, BorderLayout.NORTH); topPanel.add(searchPanel, BorderLayout.CENTER); panel.add(topPanel, BorderLayout.NORTH); panel.add(new JScrollPane(table), BorderLayout.CENTER); return panel; } private void refreshData() { List<Map<String, Object>> data = MySQL.readTable("供应商"); model.setRowCount(0); for (Map<String, Object> row : data) { model.addRow(new Object[]{ row.get("供应商编号"), row.get("供应商名"), row.get("供应商地址"), row.get("供应商电话") }); } } private void searchSuppliers(String name, String region) { List<Map<String, Object>> data = new ArrayList<>(); String sql = "SELECT * FROM 供应商 WHERE 供应商名 LIKE ? AND 供应商地址 LIKE ?"; try (Connection conn = MySQL.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, "%" + name + "%"); pstmt.setString(2, "%" + region + "%"); ResultSet rs = pstmt.executeQuery(); while (rs.next()) { Map<String, Object> row = new LinkedHashMap<>(); row.put("供应商编号", rs.getString("供应商编号")); row.put("供应商名", rs.getString("供应商名")); row.put("供应商地址", rs.getString("供应商地址")); row.put("供应商电话", rs.getString("供应商电话")); data.add(row); } } catch (SQLException e) { MySQL.showError("搜索错误", e); } model.setRowCount(0); for (Map<String, Object> row : data) { model.addRow(new Object[]{ row.get("供应商编号"), row.get("供应商名"), row.get("供应商地址"), row.get("供应商电话") }); } } private void addSupplier() { JDialog dialog = new JDialog((Frame) null, "添加供应商", true); dialog.setSize(500, 300); dialog.setLayout(new GridLayout(5, 2, 10, 10)); dialog.setLocationRelativeTo(null); JTextField idField = new JTextField(); JTextField nameField = new JTextField(); JTextField addressField = new JTextField(); JTextField phoneField = new JTextField(); JButton submitBtn = new JButton("提交"); submitBtn.addActionListener(e -> { String id = idField.getText().trim(); String name = nameField.getText().trim(); String address = addressField.getText().trim(); String phone = phoneField.getText().trim(); // 验证输入 if (id.isEmpty() || name.isEmpty()) { JOptionPane.showMessageDialog(dialog, "供应商编号和名称不能为空!"); return; } // 执行SQL if (MySQL.executeUpdate( "INSERT INTO 供应商 (供应商编号, 供应商名, 供应商地址, 供应商电话) VALUES (?, ?, ?, ?)", id, name, address, phone) > 0) { JOptionPane.showMessageDialog(dialog, "供应商添加成功!"); dialog.dispose(); refreshData(); } else { JOptionPane.showMessageDialog(dialog, "供应商添加失败!"); } }); JButton cancelBtn = new JButton("取消"); cancelBtn.addActionListener(e -> dialog.dispose()); // 添加组件 dialog.add(new JLabel("供应商编号:")); dialog.add(idField); dialog.add(new JLabel("供应商名称:")); dialog.add(nameField); dialog.add(new JLabel("供应商地址:")); dialog.add(addressField); dialog.add(new JLabel("供应商电话:")); dialog.add(phoneField); dialog.add(submitBtn); dialog.add(cancelBtn); dialog.setVisible(true); } private void editSupplier() { int row = table.getSelectedRow(); if (row == -1) { JOptionPane.showMessageDialog(null, "请选择要修改的供应商"); return; } String id = (String) table.getValueAt(row, 0); String name = (String) table.getValueAt(row, 1); String address = (String) table.getValueAt(row, 2); String phone = (String) table.getValueAt(row, 3); JDialog dialog = new JDialog((Frame) null, "修改供应商", true); dialog.setSize(500, 300); dialog.setLayout(new GridLayout(5, 2, 10, 10)); dialog.setLocationRelativeTo(null); JTextField idField = new JTextField(id); idField.setEditable(false); JTextField nameField = new JTextField(name); JTextField addressField = new JTextField(address); JTextField phoneField = new JTextField(phone); JButton submitBtn = new JButton("提交"); submitBtn.addActionListener(e -> { String newName = nameField.getText().trim(); String newAddress = addressField.getText().trim(); String newPhone = phoneField.getText().trim(); // 验证输入 if (newName.isEmpty()) { JOptionPane.showMessageDialog(dialog, "供应商名称不能为空!"); return; } // 执行SQL if (MySQL.executeUpdate( "UPDATE 供应商 SET 供应商名=?, 供应商地址=?, 供应商电话=? WHERE 供应商编号=?", newName, newAddress, newPhone, id) > 0) { JOptionPane.showMessageDialog(dialog, "供应商信息更新成功!"); dialog.dispose(); refreshData(); } else { JOptionPane.showMessageDialog(dialog, "供应商信息更新失败!"); } }); JButton cancelBtn = new JButton("取消"); cancelBtn.addActionListener(e -> dialog.dispose()); // 添加组件 dialog.add(new JLabel("供应商编号:")); dialog.add(idField); dialog.add(new JLabel("供应商名称:")); dialog.add(nameField); dialog.add(new JLabel("供应商地址:")); dialog.add(addressField); dialog.add(new JLabel("供应商电话:")); dialog.add(phoneField); dialog.add(submitBtn); dialog.add(cancelBtn); dialog.setVisible(true); } private void deleteSupplier() { int row = table.getSelectedRow(); if (row == -1) { JOptionPane.showMessageDialog(null, "请选择要删除的供应商"); return; } String id = (String) table.getValueAt(row, 0); String name = (String) table.getValueAt(row, 1); int confirm = JOptionPane.showConfirmDialog( null, "确定要删除供应商: " + name + " (ID: " + id + ")?", "确认删除", JOptionPane.YES_NO_OPTION ); if (confirm == JOptionPane.YES_OPTION) { if (hasRelatedProducts(id)) { JOptionPane.showMessageDialog(null, "该供应商有商品记录,无法删除!"); return; } if (MySQL.executeUpdate("DELETE FROM 供应商 WHERE 供应商编号=?", id) > 0) { JOptionPane.showMessageDialog(null, "供应商删除成功!"); refreshData(); } else { JOptionPane.showMessageDialog(null, "供应商删除失败!"); } } } private boolean hasRelatedProducts(String supplierId) { String sql = "SELECT COUNT(*) FROM 商品 WHERE 供应商ID = ?"; try (Connection conn = MySQL.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, supplierId); try (ResultSet rs = pstmt.executeQuery()) { return rs.next() && rs.getInt(1) > 0; } } catch (SQLException e) { MySQL.showError("记录检查错误", e); return true; } } } // 出入库管理 class InventoryManager { private JTabbedPane tabbedPane = new JTabbedPane(); private Map<String, DefaultTableModel> models = new LinkedHashMap<>(); private Map<String, JTable> tables = new LinkedHashMap<>(); public JPanel createPanel() { JPanel panel = new JPanel(new BorderLayout()); tabbedPane.addTab("入库管理", createInventoryPanel("入库")); tabbedPane.addTab("出库管理", createInventoryPanel("出库")); panel.add(tabbedPane, BorderLayout.CENTER); return panel; } private JPanel createInventoryPanel(String type) { JPanel panel = new JPanel(new BorderLayout()); // 工具栏 JToolBar toolbar = new JToolBar(); JButton addBtn = new JButton("添加"); JButton editBtn = new JButton("修改"); JButton deleteBtn = new JButton("删除"); JButton refreshBtn = new JButton("刷新"); JButton capacityBtn = new JButton("仓库容量"); JButton stockBtn = new JButton("商品库存"); addBtn.addActionListener(e -> addRecord(type)); editBtn.addActionListener(e -> editRecord(type)); deleteBtn.addActionListener(e -> deleteRecord(type)); refreshBtn.addActionListener(e -> refreshData(type)); capacityBtn.addActionListener(e -> showWarehouseCapacity()); stockBtn.addActionListener(e -> showProductStock()); toolbar.add(addBtn); toolbar.add(editBtn); toolbar.add(deleteBtn); toolbar.add(refreshBtn); toolbar.add(capacityBtn); toolbar.add(stockBtn); // 搜索面板 JPanel searchPanel = new JPanel(); JTextField warehouseField = new JTextField(8); JTextField productField = new JTextField(8); JTextField dateField = new JTextField(8); JButton searchBtn = new JButton("搜索"); searchBtn.addActionListener(e -> searchRecords( type, warehouseField.getText().trim(), productField.getText().trim(), dateField.getText().trim() )); searchPanel.add(new JLabel("仓库ID:")); searchPanel.add(warehouseField); searchPanel.add(new JLabel("商品ID:")); searchPanel.add(productField); searchPanel.add(new JLabel("日期:")); searchPanel.add(dateField); searchPanel.add(searchBtn); // 表格 DefaultTableModel model = new DefaultTableModel() { @Override public boolean isCellEditable(int row, int column) { return false; } }; model.setColumnIdentifiers(new String[]{"编号", "仓库ID", "商品ID", "商品数量", "日期", "类型"}); models.put(type, model); JTable table = new JTable(model); table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); tables.put(type, table); refreshData(type); // 布局 JPanel topPanel = new JPanel(new BorderLayout()); topPanel.add(toolbar, BorderLayout.NORTH); topPanel.add(searchPanel, BorderLayout.CENTER); panel.add(topPanel, BorderLayout.NORTH); panel.add(new JScrollPane(table), BorderLayout.CENTER); return panel; } private void refreshData(String type) { List<Map<String, Object>> data = MySQL.readTable("出入库"); DefaultTableModel model = models.get(type); model.setRowCount(0); for (Map<String, Object> row : data) { if (type.equals(row.get("类型"))) { model.addRow(new Object[]{ row.get("编号"), row.get("仓库ID"), row.get("商品ID"), row.get("商品数量"), row.get("日期"), row.get("类型") }); } } } private void searchRecords(String type, String warehouseId, String productId, String date) { DefaultTableModel model = models.get(type); model.setRowCount(0); StringBuilder sql = new StringBuilder("SELECT * FROM 出入库 WHERE 类型=?"); List<Object> params = new ArrayList<>(); params.add(type); if (!warehouseId.isEmpty()) { sql.append(" AND 仓库ID LIKE ?"); params.add("%" + warehouseId + "%"); } if (!productId.isEmpty()) { sql.append(" AND 商品ID LIKE ?"); params.add("%" + productId + "%"); } if (!date.isEmpty()) { sql.append(" AND 日期 LIKE ?"); params.add("%" + date + "%"); } try (Connection conn = MySQL.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql.toString())) { for (int i = 0; i < params.size(); i++) { pstmt.setObject(i + 1, params.get(i)); } ResultSet rs = pstmt.executeQuery(); while (rs.next()) { model.addRow(new Object[]{ rs.getString("编号"), rs.getString("仓库ID"), rs.getString("商品ID"), rs.getInt("商品数量"), rs.getString("日期"), rs.getString("类型") }); } } catch (SQLException e) { MySQL.showError("搜索错误", e); } } private void addRecord(String type) { JDialog dialog = new JDialog((Frame) null, type + "记录", true); dialog.setSize(500, 300); dialog.setLayout(new GridLayout(5, 2, 10, 10)); dialog.setLocationRelativeTo(null); JTextField warehouseField = new JTextField(); JTextField productField = new JTextField(); JTextField quantityField = new JTextField(); JTextField dateField = new JTextField(); JButton submitBtn = new JButton("提交"); submitBtn.addActionListener(e -> { try { String warehouseId = warehouseField.getText().trim(); String productId = productField.getText().trim(); int quantity = Integer.parseInt(quantityField.getText().trim()); String date = dateField.getText().trim(); // 验证输入 if (warehouseId.isEmpty() || productId.isEmpty() || date.isEmpty()) { JOptionPane.showMessageDialog(dialog, "所有字段都必须填写!"); return; } if (!MySQL.checkForeignKeyExists("仓库", "仓库编号", warehouseId)) { JOptionPane.showMessageDialog(dialog, "仓库ID不存在!"); return; } if (!MySQL.checkForeignKeyExists("商品", "商品编号", productId)) { JOptionPane.showMessageDialog(dialog, "商品ID不存在!"); return; } if (quantity <= 0) { JOptionPane.showMessageDialog(dialog, "商品数量必须大于0!"); return; } boolean isInbound = "入库".equals(type); // 检查容量/库存 if (isInbound && !checkWarehouseCapacity(warehouseId, quantity)) { JOptionPane.showMessageDialog(dialog, "仓库剩余容量不足!"); return; } if (!isInbound && !checkProductStock(productId, quantity)) { JOptionPane.showMessageDialog(dialog, "商品库存不足!"); return; } // 执行SQL if (MySQL.executeUpdate( "INSERT INTO 出入库 (仓库ID, 商品ID, 商品数量, 日期, 类型) VALUES (?, ?, ?, ?, ?)", warehouseId, productId, quantity, date, type) > 0) { // 更新仓库容量和商品库存 MySQL.updateWarehouseCapacity(warehouseId, quantity, isInbound); MySQL.updateProductStock(productId, quantity, isInbound); JOptionPane.showMessageDialog(dialog, type + "记录添加成功!"); dialog.dispose(); refreshData(type); } else { JOptionPane.showMessageDialog(dialog, type + "记录添加失败!"); } } catch (NumberFormatException ex) { JOptionPane.showMessageDialog(dialog, "请输入有效的数字!"); } }); JButton cancelBtn = new JButton("取消"); cancelBtn.addActionListener(e -> dialog.dispose()); // 添加组件 dialog.add(new JLabel("仓库ID:")); dialog.add(warehouseField); dialog.add(new JLabel("商品ID:")); dialog.add(productField); dialog.add(new JLabel("商品数量:")); dialog.add(quantityField); dialog.add(new JLabel("日期(YYYY-MM-DD):")); dialog.add(dateField); dialog.add(submitBtn); dialog.add(cancelBtn); dialog.setVisible(true); } private boolean checkWarehouseCapacity(String warehouseId, int quantity) { String sql = "SELECT 剩余容量 FROM 仓库 WHERE 仓库编号 = ?"; try (Connection conn = MySQL.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, warehouseId); try (ResultSet rs = pstmt.executeQuery()) { return rs.next() && rs.getInt("剩余容量") >= quantity; } } catch (SQLException e) { MySQL.showError("容量检查错误", e); return false; } } private boolean checkProductStock(String productId, int quantity) { String sql = "SELECT 库存 FROM 商品 WHERE 商品编号 = ?"; try (Connection conn = MySQL.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, productId); try (ResultSet rs = pstmt.executeQuery()) { return rs.next() && rs.getInt("库存") >= quantity; } } catch (SQLException e) { MySQL.showError("库存检查错误", e); return false; } } private void showWarehouseCapacity() { String warehouseId = JOptionPane.showInputDialog("请输入仓库编号:"); if (warehouseId != null && !warehouseId.isEmpty()) { String sql = "SELECT 剩余容量 FROM 仓库 WHERE 仓库编号 = ?"; try (Connection conn = MySQL.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, warehouseId); try (ResultSet rs = pstmt.executeQuery()) { if (rs.next()) { JOptionPane.showMessageDialog(null, "仓库 " + warehouseId + " 的剩余容量: " + rs.getInt("剩余容量")); } else { JOptionPane.showMessageDialog(null, "未找到仓库!"); } } } catch (SQLException e) { MySQL.showError("查询错误", e); } } } private void showProductStock() { String productId = JOptionPane.showInputDialog("请输入商品编号:"); if (productId != null && !productId.isEmpty()) { String sql = "SELECT 库存 FROM 商品 WHERE 商品编号 = ?"; try (Connection conn = MySQL.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, productId); try (ResultSet rs = pstmt.executeQuery()) { if (rs.next()) { JOptionPane.showMessageDialog(null, "商品 " + productId + " 的库存: " + rs.getInt("库存")); } else { JOptionPane.showMessageDialog(null, "未找到商品!"); } } } catch (SQLException e) { MySQL.showError("查询错误", e); } } } private void editRecord(String type) { JTable table = tables.get(type); int row = table.getSelectedRow(); if (row == -1) { JOptionPane.showMessageDialog(null, "请选择要修改的记录"); return; } String id = (String) table.getValueAt(row, 0); String warehouseId = (String) table.getValueAt(row, 1); String productId = (String) table.getValueAt(row, 2); int quantity = (int) table.getValueAt(row, 3); String date = (String) table.getValueAt(row, 4); JDialog dialog = new JDialog((Frame) null, "修改记录", true); dialog.setSize(500, 300); dialog.setLayout(new GridLayout(5, 2, 10, 10)); dialog.setLocationRelativeTo(null); JTextField warehouseField = new JTextField(warehouseId); JTextField productField = new JTextField(productId); JTextField quantityField = new JTextField(String.valueOf(quantity)); JTextField dateField = new JTextField(date); JButton submitBtn = new JButton("提交"); submitBtn.addActionListener(e -> { try { String newWarehouseId = warehouseField.getText().trim(); String newProductId = productField.getText().trim(); int newQuantity = Integer.parseInt(quantityField.getText().trim()); String newDate = dateField.getText().trim(); // 验证输入 if (newWarehouseId.isEmpty() || newProductId.isEmpty() || newDate.isEmpty()) { JOptionPane.showMessageDialog(dialog, "所有字段都必须填写!"); return; } if (!MySQL.checkForeignKeyExists("仓库", "仓库编号", newWarehouseId)) { JOptionPane.showMessageDialog(dialog, "仓库ID不存在!"); return; } if (!MySQL.checkForeignKeyExists("商品", "商品编号", newProductId)) { JOptionPane.showMessageDialog(dialog, "商品ID不存在!"); return; } if (newQuantity <= 0) { JOptionPane.showMessageDialog(dialog, "商品数量必须大于0!"); return; } boolean isInbound = "入库".equals(type); // 检查容量/库存 if (isInbound && !checkWarehouseCapacity(newWarehouseId, newQuantity)) { JOptionPane.showMessageDialog(dialog, "仓库剩余容量不足!"); return; } if (!isInbound && !checkProductStock(newProductId, newQuantity)) { JOptionPane.showMessageDialog(dialog, "商品库存不足!"); return; } // 执行SQL if (MySQL.executeUpdate( "UPDATE 出入库 SET 仓库ID=?, 商品ID=?, 商品数量=?, 日期=? WHERE 编号=?", newWarehouseId, newProductId, newQuantity, newDate, id) > 0) { // 撤销原操作的影响 MySQL.updateWarehouseCapacity(warehouseId, quantity, !isInbound); MySQL.updateProductStock(productId, quantity, !isInbound); // 应用新操作的影响 MySQL.updateWarehouseCapacity(newWarehouseId, newQuantity, isInbound); MySQL.updateProductStock(newProductId, newQuantity, isInbound); JOptionPane.showMessageDialog(dialog, "记录更新成功!"); dialog.dispose(); refreshData(type); } else { JOptionPane.showMessageDialog(dialog, "记录更新失败!"); } } catch (NumberFormatException ex) { JOptionPane.showMessageDialog(dialog, "请输入有效的数字!"); } }); JButton cancelBtn = new JButton("取消"); cancelBtn.addActionListener(e -> dialog.dispose()); // 添加组件 dialog.add(new JLabel("仓库ID:")); dialog.add(warehouseField); dialog.add(new JLabel("商品ID:")); dialog.add(productField); dialog.add(new JLabel("商品数量:")); dialog.add(quantityField); dialog.add(new JLabel("日期(YYYY-MM-DD):")); dialog.add(dateField); dialog.add(submitBtn); dialog.add(cancelBtn); dialog.setVisible(true); } private void deleteRecord(String type) { JTable table = tables.get(type); int row = table.getSelectedRow(); if (row == -1) { JOptionPane.showMessageDialog(null, "请选择要删除的记录"); return; } String id = (String) table.getValueAt(row, 0); String warehouseId = (String) table.getValueAt(row, 1); String productId = (String) table.getValueAt(row, 2); int quantity = (int) table.getValueAt(row, 3); int confirm = JOptionPane.showConfirmDialog( null, "确定要删除这条记录吗?", "确认删除", JOptionPane.YES_NO_OPTION ); if (confirm == JOptionPane.YES_OPTION) { if (MySQL.executeUpdate("DELETE FROM 出入库 WHERE 编号=?", id) > 0) { boolean isInbound = "入库".equals(type); // 撤销操作的影响 MySQL.updateWarehouseCapacity(warehouseId, quantity, !isInbound); MySQL.updateProductStock(productId, quantity, !isInbound); JOptionPane.showMessageDialog(null, "记录删除成功!"); refreshData(type); } else { JOptionPane.showMessageDialog(null, "记录删除失败!"); } } } } // 管理员管理 class AdminManager { private String currentUser; public AdminManager(String currentUser) { this.currentUser = currentUser; } public JPanel createPanel() { JPanel panel = new JPanel(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.insets = new Insets(20, 20, 20, 20); gbc.gridx = 0; gbc.gridy = 0; JLabel titleLabel = new JLabel("用户管理"); titleLabel.setFont(new Font("宋体", Font.BOLD, 24)); panel.add(titleLabel, gbc); gbc.gridy++; JButton changePwdBtn = new JButton("修改密码"); changePwdBtn.setPreferredSize(new Dimension(200, 40)); changePwdBtn.addActionListener(e -> changePassword()); panel.add(changePwdBtn, gbc); return panel; } private void changePassword() { JDialog dialog = new JDialog((Frame) null, "修改密码", true); dialog.setSize(400, 250); dialog.setLayout(new GridLayout(4, 2, 10, 10)); dialog.setLocationRelativeTo(null); JPasswordField oldPwdField = new JPasswordField(); JPasswordField newPwdField = new JPasswordField(); JPasswordField confirmPwdField = new JPasswordField(); JButton submitBtn = new JButton("提交"); submitBtn.addActionListener(e -> { String oldPwd = new String(oldPwdField.getPassword()); String newPwd = new String(newPwdField.getPassword()); String confirmPwd = new String(confirmPwdField.getPassword()); if (oldPwd.isEmpty() || newPwd.isEmpty() || confirmPwd.isEmpty()) { JOptionPane.showMessageDialog(dialog, "所有字段都必须填写!"); return; } if (!MySQL.validateUser(currentUser, oldPwd)) { JOptionPane.showMessageDialog(dialog, "旧密码不正确!"); return; } if (!newPwd.equals(confirmPwd)) { JOptionPane.showMessageDialog(dialog, "两次输入的新密码不一致!"); return; } if (MySQL.updatePassword(currentUser, newPwd)) { JOptionPane.showMessageDialog(dialog, "密码修改成功!"); dialog.dispose(); } else { JOptionPane.showMessageDialog(dialog, "密码更新失败,请联系管理员"); } }); JButton cancelBtn = new JButton("取消"); cancelBtn.addActionListener(e -> dialog.dispose()); dialog.add(new JLabel("旧密码:")); dialog.add(oldPwdField); dialog.add(new JLabel("新密码:")); dialog.add(newPwdField); dialog.add(new JLabel("确认新密码:")); dialog.add(confirmPwdField); dialog.add(submitBtn); dialog.add(cancelBtn); dialog.setVisible(true); } }详细解释解释每一行
06-25
package data; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class BaseDao { public Connection conn=null; public Statement st=null; public PreparedStatement ps=null; public ResultSet rs=null; public static String driver="com.mysql.jdbc.Driver"; public static String url="jdbc:mysql://localhost:3306/my?characterEncoding=UTF-8"; public static String dbName="root"; public static String dbPass="root"; public Connection getConn(){ try { Class.forName(driver); conn= DriverManager.getConnection(url,dbName,dbPass); System.out.println("数据库已连接!"); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block //e.printStackTrace(); System.out.println("驱动类未找到:"+e); } catch (SQLException e) { // TODO Auto-generated catch block //e.printStackTrace(); System.out.println("连接数据库失败:"+e); } return conn; } public void closeAll(){ if(rs!=null){ try{ rs.close(); }catch(SQLException e){ e.printStackTrace(); } } if(ps!=null){ try{ ps.close(); }catch(SQLException e){ e.printStackTrace(); } } if(conn!=null){ try{ conn.close(); }catch(SQLException e){ e.printStackTrace(); } } } public int executeSQL(String sql,String[] param){ Connection conn=null; PreparedStatement ps=null; int num=0; try{ conn=getConn(); ps=conn.prepareStatement(sql); if(param!=null){ for(int i=0;i<param.length;i++){ ps.setString(i+1,param[i]); } } num=ps.executeUpdate(); }catch(SQLException e){ e.printStackTrace(); }finally{ closeAll(); } return num; } } package util; import java.sql.ResultSet; import java.sql.SQLException; public class Test { public static void main(String[] args) { UserDao user = new UserDaoImpl(); user.userLogin("bb", "22"); ResultSet rs = user.findAllUsers(); try{ while (rs.next()){ System.out.println("会员名:"+rs.getString(1)); System.out.println("密码:"+rs.getString(2)); } }catch (SQLException e){ e.printStackTrace(); } user.insertNewUser("dd", "44", "男", "18833332222", "江苏盐城", "big.png", "他是一个上进有远大理想的大学生", "同意"); user.updateUserPassword("12345", "aa"); user.updateUser("8888", "女", "18833331112", "江苏苏州", "big.png", "孝顺", "同意", "苏州托普"); user.deleteUser("cc"); } } package util; import java.sql.ResultSet; public interface UserDao { public abstract int deleteUser(String name); public abstract int insertNewUser(String name,String password,String sex,String tel,String add,String photo,String intro,String read); public abstract int updateUserPassword(String password,String name); public abstract int updateUser(String password,String sex,String tel,String add,String photo,String intro,String read, String name); public abstract ResultSet userLogin(String name,String password); public abstract ResultSet findAllUsers(); public abstract ResultSet findAllName(String name); } package util; import java.sql.ResultSet; import data.BaseDao; public class UserDaoImpl extends BaseDao implements UserDao { public int deleteUser(String name) { String sql ="delete from user where name=?"; String param[]={name}; int i=0; try { i = this.executeSQL(sql, param); if(i>0){ System.out.println("删除用户成功!"); } else{ System.out.println("删除用户失败!"); } }catch(Exception e) { e.printStackTrace(); } return i; } public ResultSet findAllName(String name) { // TODO Auto-generated method stub String sql ="select * from user where name=?"; try { conn = this.getConn(); ps = conn.prepareStatement(sql); ps.setString(1, name); rs = ps.executeQuery(); }catch(Exception e) { e.printStackTrace(); } return rs; } public ResultSet findAllUsers() { // TODO Auto-generated method stub String sql ="select * from user "; try { conn = this.getConn(); ps = conn.prepareStatement(sql); rs = ps.executeQuery(); }catch(Exception e) { e.printStackTrace(); } return rs; } public int insertNewUser(String name, String password, String sex, String tel, String add, String photo, String intro, String read) { // TODO Auto-generated method stub String sql = "insert into user values(?,?,?,?,?,?,?,?)"; String param[] = {name,password,sex,tel,add,photo,intro,read}; int i = 0; try { i = this.executeSQL(sql, param); if(i>0){ System.out.println("添加用户成功!"); } else{ System.out.println("添加用户失败!"); } }catch(Exception e) { e.printStackTrace(); } return i; } public int updateUser(String password, String sex, String tel,String add,String photo,String intro,String read,String name) { // TODO Auto-generated method stub String sql ="update user set password=?, sex=?, tel=?, add=?, photo=?, intro=?, read=? where name=?"; String param[] = {password,sex,tel,add,photo,intro,read,name}; int i = 0; try { i = this.executeSQL(sql, param); if(i>0){ System.out.println("修改用户信息成功!"); } else{ System.out.println("修改用户信息失败!"); } }catch(Exception e) { e.printStackTrace(); } return i; } public int updateUserPassword(String password, String name) { // TODO Auto-generated method stub String sql ="update user set password=? and name=?"; String param[] = {password,name}; int i = 0; try { i = this.executeSQL(sql, param); if(i>0){ System.out.println("修改用户密码成功!"); } else{ System.out.println("修改用户密码失败!"); } }catch(Exception e) { e.printStackTrace(); } return i; } public ResultSet userLogin(String name, String password) { // TODO Auto-generated method stub String sql ="select * from user where name=? and password=?"; try { conn = this.getConn(); ps = conn.prepareStatement(sql); ps.setString(1, name); ps.setString(2, password); rs = ps.executeQuery(); }catch(Exception e) { e.printStackTrace(); } return rs; } } 数据库已连接! 数据库已连接! 用户名:aa 密码:11 用户名:bb 密码:22 用户名:cc 密码:33 用户名:苏州托普 密码:0 数据库已连接! java.sql.SQLException: Column count doesn't match value count at row 1 at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1055) at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956) at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3515) at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3447) at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1951) at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2101) at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2554) at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1761) at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2046) at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1964) at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1949) at data.BaseDao.executeSQL(BaseDao.java:71) at util.UserDaoImpl.insertNewUser(UserDaoImpl.java:68) at util.Test.main(Test.java:18) 添加用户失败! 数据库已连接! 修改用户密码成功! 数据库已连接! com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'aihao' in 'field list' at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) at java.lang.reflect.Constructor.newInstance(Constructor.java:513) at com.mysql.jdbc.Util.handleNewInstance(Util.java:406) at com.mysql.jdbc.Util.getInstance(Util.java:381) at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1030) at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956) at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3515) at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3447) at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1951) at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2101) at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2554) at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1761) at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2046) at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1964) at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1949) at data.BaseDao.executeSQL(BaseDao.java:71) at util.UserDaoImpl.updateUser(UserDaoImpl.java:90) at util.Test.main(Test.java:20) 修改用户信息失败! 数据库已连接! 删除用户成功! 结合上诉代码与错误分析给你解决方案
06-24
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值