我的数据库中有两个表:
employee_details_table:
employee_attendance:
以下是将数据插入employee_attendance的java代码:
class Attendance
{
java.util.Date utilDate;
java.sql.Date sqlDate;
String attDate;
int empid;
String pa;
Connection con=null;
PreparedStatement statement=null;
ResultSet rs=null;
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt)
{
try
{
empid=Integer.parseInt(jTextField1.getText());
sqlDate=new java.sql.Date(utilDate.getTime());
pa=jComboBox1.getSelectedItem().toString();
}
catch(Exception e)
{
JOptionPane.showMessageDialog(null,e.getMessage());
}
String query = "Insert into employee_attendance (employee_id,attendance_for,present_or_absent) values (?,?,?)";
try
{
Class.forName("com.mysql.jdbc.Driver");
con=DriverManager.getConnection("jdbc:mysql:///hrmps?zeroDateTimeBehavior=convertToNull","root","root");
statement=con.prepareStatement(query);
statement.setInt(1,empid);
//sqlDate=new java.sql.Date(utilDate.getTime());
statement.setDate(2,sqlDate);
statement.setString(3, pa);
statement.executeUpdate();
}
catch(Exception e)
{
JOptionPane.showMessageDialog(null,e.getMessage());
}
}
}
每当我尝试将数据插入employee_attendance时,我都会得到以下异常:
“无法添加或更新子行:外键约束失败”
答案 0 :(得分:0)
正如评论者已经说过,错误告诉你问题。 “外键约束”违规意味着您尝试使用不存在的父行的外键值将行插入子表。
因此,您需要检查父表(Employee)中的数据以及您尝试插入子表(Attendance)的值。你有不匹配。
下面是一个完整的工作示例,创建一个数据库&插入行,所有行都塞进一个类中。虽然这是不生产有价值的代码,但它是正确插入子行(三次)和不正确地插入子行(一次,demo
方法的最后一行)的工作演示。
演示的重点是insertAttendance
方法中对demo
的四次调用。我们获得employee_
行,标识符为1,2和3.因此,为这三个值中的任何一个插入attendance_
行都会成功。
this.insertAttendance ( conn , 2 …
this.insertAttendance ( conn , 1 …
this.insertAttendance ( conn , 3 …
当我们尝试无效号码时,我们没有employee_
,例如4
,那么我们就会失败。我们收到SQLException,指出违反了foreign key constraint。数据库正在执行referential integrity。如果我们没有被阻止,我们会创建一个“孤儿”行,attendance_
行,但没有匹配的employee_
行。
this.insertAttendance ( conn , 4 … // Throws SQLException for violation of the foreign key constraint.
此示例使用纯Java数据库H2 Database。您必须添加为依赖项才能运行此代码。易于通过Maven等添加
跑步时。
Tables established and populated.
Table dump: employee_
Employee id_: 1 | name_: Alfred
Employee id_: 2 | name_: Barbara
Employee id_: 3 | name_: Charlie
Table dump: attendance_
Attendance id_: 1 | fkey_employee_id_: 2 | when_expected_: 2016-01-23T10:00:00Z | status_: present
Attendance id_: 2 | fkey_employee_id_: 1 | when_expected_: 2016-01-23T10:00:00Z | status_: present
Attendance id_: 3 | fkey_employee_id_: 3 | when_expected_: 2016-01-23T10:00:00Z | status_: absent
SQLException: Referential integrity constraint violation: "CONSTRAINT_32: PUBLIC.ATTENDANCE_ FOREIGN KEY(FKEY_EMPLOYEE_ID_) REFERENCES PUBLIC.EMPLOYEE_(ID_) (4)"; SQL statement:
INSERT INTO attendance_ ( fkey_employee_id_ , when_expected_ , status_ ) VALUES ( ? , ? , ? ); [23506-191]
示例代码。
package com.example.h2example;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.time.Instant;
/**
* Demonstrates how to both properly and improperly insert rows into a child
* table.
*
* Caveat: Not production-worthy code. For demonstration purposes only. Use at
* your own risk.
*
* @author Basil Bourque
*/
public class App {
public static void main ( String[] args ) {
App app = new App ();
app.demo ();
}
private void demo () {
Connection conn = this.fetchConnection ();
this.insertAttendance ( conn , 2 , Instant.parse ( "2016-01-23T10:00:00Z" ) , "present" );
this.insertAttendance ( conn , 1 , Instant.parse ( "2016-01-23T10:00:00Z" ) , "present" );
this.insertAttendance ( conn , 3 , Instant.parse ( "2016-01-23T10:00:00Z" ) , "absent" );
this.dumpTable_Employee ( conn );
this.dumpTable_Attendance ( conn );
// Insert invalid value (BAD).
this.insertAttendance ( conn , 4 , Instant.parse ( "2016-01-23T10:00:00Z" ) , "absent" );
}
private Connection fetchConnection () {
Connection conn = null;
try {
Class.forName ( "org.h2.Driver" );
} catch ( ClassNotFoundException e ) {
// TODO: Handle exception.
System.out.println ( "Database failure: " + e );
return null;
}
// Specify a database named 'EmployeeAttendanceBogus.mv.db' in the Unix user’s home folder.
String dbFolderPath = "~/";
String dbName = "EmployeeAttendanceBogus";
String dbUrl = "jdbc:h2:" + dbFolderPath + dbName;
String dbUserName = "h2";
String dbPassword = "pw";
try {
// If database does not yet exist, it is automatically created.
conn = DriverManager.getConnection ( dbUrl , dbUserName , dbPassword );
} catch ( SQLException ex ) {
System.out.println ( "SQLException on DriverManager.getConnection: " + ex.getMessage () );
// TODO: Handle exception when no Connection is made.
}
if ( null == conn ) {
System.out.println ( "Database error. No Connection." );
// TODO: Handle exception when no Connection is made.
} else {
// ELSE got database connection. Normal.
this.recreateTables ( conn );
// this.dumpTable_Employee ( conn );
// this.dumpTable_Attendance ( conn );
}
return conn;
}
private void recreateTables ( Connection conn ) {
// Update database structure if needed.
StringBuilder sql = new StringBuilder ();
// Delete any existing tables.
sql.append ( "DROP TABLE IF EXISTS attendance_ ; " + " \n" ); // Drop child table first, because of referential integrity.
sql.append ( "DROP TABLE IF EXISTS employee_ ; " + " \n" );
// Define tables.
sql.append ( "CREATE TABLE employee_ " + " \n" );
sql.append ( "(" + " \n" );
sql.append ( "id_ IDENTITY PRIMARY KEY , " + " \n" ); // Primary key, Long type.
sql.append ( "name_ VARCHAR_IGNORECASE NOT NULL " + " \n" );
sql.append ( ")" + " \n" );
sql.append ( ";" + " \n" );
sql.append ( "" );
sql.append ( "CREATE TABLE attendance_ " + " \n" );
sql.append ( "(" + " \n" );
sql.append ( "id_ IDENTITY PRIMARY KEY , " + " \n" ); // Primary key, Long type.
sql.append ( "fkey_employee_id_ BIGINT , " + " \n" );
sql.append ( "when_expected_ TIMESTAMP NOT NULL , " + " \n" );
sql.append ( "status_ VARCHAR_IGNORECASE NOT NULL " + " \n" ); // Domain: "present" | "absent" .
sql.append ( ")" + " \n" );
sql.append ( ";" + " \n" );
sql.append ( "" );
sql.append ( "ALTER TABLE attendance_ ADD FOREIGN KEY ( fkey_employee_id_ ) REFERENCES employee_( id_ ) ;" );
sql.append ( "" );
sql.append ( "INSERT INTO employee_ ( name_ ) VALUES ( 'Alfred' ) ;" );
sql.append ( "INSERT INTO employee_ ( name_ ) VALUES ( 'Barbara' ) ;" );
sql.append ( "INSERT INTO employee_ ( name_ ) VALUES ( 'Charlie' ) ;" );
System.out.println ( "Tables established and populated.\n" );
try ( Statement stmt = conn.createStatement () ) {
stmt.executeUpdate ( sql.toString () );
} catch ( SQLException ex ) {
System.err.println ( "SQLException: " + ex.getMessage () );
// TODO: Handle exception.
}
}
private void dumpTable_Employee ( Connection conn ) {
StringBuilder sql = new StringBuilder ();
sql.append ( "SELECT * FROM employee_ ;" );
try ( PreparedStatement pstmt = conn.prepareStatement ( sql.toString () ) ) {
try ( ResultSet rs = pstmt.executeQuery (); ) {
System.out.println ( "Table dump: employee_" );
while ( rs.next () ) {
long id = rs.getLong ( "id_" );
String name = rs.getString ( "name_" );
System.out.println ( "Employee id_: " + id + " | name_: " + name );
}
System.out.println ( "" );
}
} catch ( SQLException ex ) {
System.err.println ( "SQLException: " + ex.getMessage () );
// TODO: Handle exception.
}
}
private void dumpTable_Attendance ( Connection conn ) {
StringBuilder sql = new StringBuilder ();
sql.append ( "SELECT * FROM attendance_ ;" );
try ( PreparedStatement pstmt = conn.prepareStatement ( sql.toString () ) ) {
try ( ResultSet rs = pstmt.executeQuery (); ) {
System.out.println ( "Table dump: attendance_" );
while ( rs.next () ) {
long id = rs.getLong ( "id_" );
long fkey = rs.getLong ( "fkey_employee_id_" );
java.sql.Timestamp whenExpectedTs = rs.getTimestamp ( "when_expected_" );
Instant whenExpected = whenExpectedTs.toInstant (); // Convert as soon as possible from java.sql.Timestamp to java.time.
String status = rs.getString ( "status_" );
System.out.println ( "Attendance id_: " + id + " | fkey_employee_id_: " + fkey + " | when_expected_: " + whenExpected + " | status_: " + status );
}
System.out.println ( "" );
}
} catch ( SQLException ex ) {
System.err.println ( "SQLException: " + ex.getMessage () );
// TODO: Handle exception.
}
}
private void insertAttendance ( Connection conn , long employeeId , Instant whenExpected , String status ) {
StringBuilder sql = new StringBuilder ();
sql.append ( "INSERT INTO attendance_ ( fkey_employee_id_ , when_expected_ , status_ ) VALUES ( ? , ? , ? );" );
try ( PreparedStatement pstmt = conn.prepareStatement ( sql.toString () ) ) {
pstmt.setLong ( 1 , employeeId );
pstmt.setTimestamp ( 2 , java.sql.Timestamp.from ( whenExpected ) );
pstmt.setString ( 3 , status );
int rowsAffected = pstmt.executeUpdate ();
} catch ( SQLException ex ) {
System.err.println ( "SQLException: " + ex.getMessage () );
// TODO: Handle exception.
}
}
}
顺便说一句......
您的代码显示您可能对java.util.Date
和java.sql.Date
感到困惑。第一个是日期和时间,而第二个假装只是一个日期没有时间。
避免使用旧的java.util.Date类(和.Calendar),因为它设计糟糕,令人困惑且麻烦。使用java.time,内置于Java 8及更高版本。
java.sql类型同样糟糕。但是我们必须继续使用它们,直到我们的JDBC驱动程序更新为直接使用java.time类型。在此之前,尽可能简单地使用java.sql类型将数据移入/移出数据库。收到值后立即从java.sql转换为java.time。