在我的java bat文件中,我收到一个错误:
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cann
ot add or update a child row: a foreign key constraint fails (`ellinel`.`invento
ryitems`, CONSTRAINT `FK_inventoryitems_2` FOREIGN KEY (`accountid`) REFERENCES
`accounts` (`id`) ON DELETE CASCADE)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Sou
rce)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:408)
at com.mysql.jdbc.Util.getInstance(Util.java:383)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1049)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4226)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4158)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2615)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2776)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2840)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.ja
va:2082)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java
:2334)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java
:2262)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java
:2246)
at client.inventory.ItemFactory.saveItems(ItemFactory.java:249)
at server.MapleStorage.saveToDB(MapleStorage.java:137)
at client.MapleCharacter.saveToDB(MapleCharacter.java:5188)
at net.server.channel.handlers.ChangeChannelHandler.handlePacket(ChangeC
hannelHandler.java:97)
at net.MapleServerHandler.messageReceived(MapleServerHandler.java:128)
at org.apache.mina.core.filterchain.DefaultIoFilterChain$TailFilter.mess
ageReceived(DefaultIoFilterChain.java:690)
at org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextMessage
Received(DefaultIoFilterChain.java:417)
at org.apache.mina.core.filterchain.DefaultIoFilterChain.access$1200(Def
aultIoFilterChain.java:47)
at org.apache.mina.core.filterchain.DefaultIoFilterChain$EntryImpl$1.mes
sageReceived(DefaultIoFilterChain.java:765)
at org.apache.mina.filter.codec.ProtocolCodecFilter$ProtocolDecoderOutpu
tImpl.flush(ProtocolCodecFilter.java:407)
at org.apache.mina.filter.codec.ProtocolCodecFilter.messageReceived(Prot
ocolCodecFilter.java:236)
at org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextMessage
Received(DefaultIoFilterChain.java:417)
at org.apache.mina.core.filterchain.DefaultIoFilterChain.access$1200(Def
aultIoFilterChain.java:47)
at org.apache.mina.core.filterchain.DefaultIoFilterChain$EntryImpl$1.mes
sageReceived(DefaultIoFilterChain.java:765)
at org.apache.mina.core.filterchain.IoFilterAdapter.messageReceived(IoFi
lterAdapter.java:109)
at org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextMessage
Received(DefaultIoFilterChain.java:417)
at org.apache.mina.core.filterchain.DefaultIoFilterChain.fireMessageRece
ived(DefaultIoFilterChain.java:410)
at org.apache.mina.core.polling.AbstractPollingIoProcessor.read(Abstract
PollingIoProcessor.java:710)
at org.apache.mina.core.polling.AbstractPollingIoProcessor.process(Abstr
actPollingIoProcessor.java:664)
at org.apache.mina.core.polling.AbstractPollingIoProcessor.process(Abstr
actPollingIoProcessor.java:653)
at org.apache.mina.core.polling.AbstractPollingIoProcessor.access$600(Ab
stractPollingIoProcessor.java:67)
at org.apache.mina.core.polling.AbstractPollingIoProcessor$Processor.run
(AbstractPollingIoProcessor.java:1124)
at org.apache.mina.util.NamePreservingRunnable.run(NamePreservingRunnabl
e.java:64)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
它是代码执行的部分:
public synchronized void saveItems(List<Pair<Item, MapleInventoryType>> items, int id) throws SQLException {
PreparedStatement ps = null;
PreparedStatement pse = null;
try {
StringBuilder query = new StringBuilder();
query.append("DELETE FROM `inventoryitems` WHERE `type` = ? AND `");
query.append(account ? "accountid" : "characterid").append("` = ?");
Connection con = DatabaseConnection.getConnection();
ps = con.prepareStatement(query.toString());
ps.setInt(1, value);
ps.setInt(2, id);
ps.executeUpdate();
ps.close();
ps = con.prepareStatement("INSERT INTO `inventoryitems` VALUES (DEFAULT, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", Statement.RETURN_GENERATED_KEYS);
pse = con.prepareStatement("INSERT INTO `inventoryequipment` VALUES (DEFAULT, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
for (Pair<Item, MapleInventoryType> pair : items) {
Item item = pair.getLeft();
MapleInventoryType mit = pair.getRight();
ps.setInt(1, value);
ps.setString(2, account ? null : String.valueOf(id));
ps.setString(3, account ? String.valueOf(id) : null);
ps.setInt(4, item.getItemId());
ps.setInt(5, mit.getType());
ps.setInt(6, item.getPosition());
ps.setInt(7, item.getQuantity());
ps.setString(8, item.getOwner());
ps.setInt(9, item.getPetId());
ps.setInt(10, item.getFlag());
ps.setLong(11, item.getExpiration());
ps.setString(12, item.getGiftFrom());
ps.setString(13, item.getRewards());
ps.executeUpdate();//line 249
if (mit.equals(MapleInventoryType.EQUIP) || mit.equals(MapleInventoryType.EQUIPPED)) {
try (ResultSet rs = ps.getGeneratedKeys()) {
if (!rs.next()) {
throw new RuntimeException("Inserting item failed.");
}
pse.setInt(1, rs.getInt(1));
}
Equip equip = (Equip) item;
pse.setInt(2, equip.getUpgradeSlots());
pse.setInt(3, equip.getLevel());
pse.setInt(4, equip.getStr());
pse.setInt(5, equip.getDex());
pse.setInt(6, equip.getInt());
pse.setInt(7, equip.getLuk());
pse.setInt(8, equip.getHp());
pse.setInt(9, equip.getMp());
pse.setInt(10, equip.getWatk());
pse.setInt(11, equip.getMatk());
pse.setInt(12, equip.getWdef());
pse.setInt(13, equip.getMdef());
pse.setInt(14, equip.getAcc());
pse.setInt(15, equip.getAvoid());
pse.setInt(16, equip.getHands());
pse.setInt(17, equip.getSpeed());
pse.setInt(18, equip.getJump());
pse.setInt(19, 0);
pse.setInt(20, equip.getVicious());
pse.setInt(21, equip.getItemLevel());
pse.setInt(22, equip.getItemExp());
pse.setInt(23, equip.getRingId());
pse.executeUpdate();
}
}
pse.close();
ps.close();
} finally {
if (ps != null) {
ps.close();
}
if (pse != null) {
pse.close();
}
}
}
不幸的是,我不知道如何使用外键。有人可以解释一下我的问题是什么,解决问题的方法是什么?
SQL代码:
DROP TABLE IF EXISTS `ellinel`.`inventoryitems`;
CREATE TABLE `ellinel`.`inventoryitems` (
`inventoryitemid` int(10) unsigned NOT NULL AUTO_INCREMENT,
`type` tinyint(3) unsigned NOT NULL,
`characterid` int(11) DEFAULT NULL,
`accountid` int(11) DEFAULT NULL,
`itemid` int(11) NOT NULL DEFAULT '0',
`inventorytype` int(11) NOT NULL DEFAULT '0',
`position` int(11) NOT NULL DEFAULT '0',
`quantity` int(11) NOT NULL DEFAULT '0',
`owner` tinytext NOT NULL,
`petid` int(11) NOT NULL DEFAULT '-1',
`flag` int(11) NOT NULL,
`expiration` bigint(20) NOT NULL DEFAULT '-1',
`giftFrom` varchar(26) NOT NULL,
`rewards` text NOT NULL,
PRIMARY KEY (`inventoryitemid`),
KEY `FK_inventoryitems_1` (`characterid`),
KEY `FK_inventoryitems_2` (`accountid`) USING BTREE,
CONSTRAINT `FK_inventoryitems_1` FOREIGN KEY (`characterid`) REFERENCES `characters` (`id`) ON DELETE CASCADE,
CONSTRAINT `FK_inventoryitems_2` FOREIGN KEY (`accountid`) REFERENCES `accounts` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=113340972 DEFAULT CHARSET=latin1;
答案 0 :(得分:0)
您无法删除具有与之关联的外键的表。外键的问题在于,在创建外键后,链接必须始终存在。这使得删除和复制痛苦。您需要做的是首先使用临时名称创建新表,并在其中创建所有新的主键和外键。您需要为与inventoryitems
和accounts
相关联的所有内容制作临时表格,然后从下往上删除原始表格,这样您就不会违反任何关键约束条件。最后,使用旧表名重命名新表。
基本上,首先按照您想要的方式创建临时结构。然后删除旧结构并重命名新结构以匹配。
答案 1 :(得分:0)
在您的表格中,accountid
列引用了id
表的accounts
列中的值。
accountid
是外键,这意味着它只能保存accounts.id
中可以找到的值。
因此,当一个新值插入accountid
或更新现有值时,您必须确保accounts
中有一个条目,以便满足约束条件。
简单地说,外键是一个引用另一个表中的条目的值。
答案 2 :(得分:0)
一个表中的外键(FK)指向另一个表中的主键(PK)。您可以阅读更多信息,并在w3schools
上查看一些示例您的错误说明:
Cannot add or update a child row: a foreign key constraint fails
(`ellinel`.`inventoryitems`, CONSTRAINT `FK_inventoryitems_2` FOREIGN KEY (`accountid`) REFERENCES`accounts` (`id`) ON DELETE CASCADE)
在这里,我们看到了约束&#39; FK_inventoryitems_2&#39;是一个错误的原因。我们在Create table语句中找到它:
CONSTRAINT `FK_inventoryitems_2` FOREIGN KEY (`accountid`) REFERENCES `accounts` (`id`) ON DELETE CASCADE
在这里,您可以看到约束FK_inventoryitems_2
代表表accounts
的FK。
这基本上意味着您要在表accountid
中插入的inventoryitems
在表accounts
中不存在。我相信这是为accountid字段增加价值的部分:
ps.setString(3, account ? String.valueOf(id) : null);
一句话,在您向表格accountid
中的inventoryitems
字段添加一些值之前,您需要在表id
中添加accounts
。