You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Spring Boot引用完整性约束违反问题排查求助

Troubleshooting Referential Integrity Violation in JPA OneToMany Setup

Hey there, let's dig into that referential integrity constraint violation you're hitting when starting your tests. I've looked over your setup, and here's what's going wrong and how to fix it.

The Root Cause

The core issue is the order of your insert statements in data.sql. You're adding records to the ARTICLE table first, but those articles reference a user with ID=1 that doesn't exist yet—you insert the USER records after the articles. Relational databases enforce foreign key constraints strictly: the referenced parent record (in this case, the user) must exist before any child records (articles) that link to it can be created.

Your Entity Setup (for reference)

Article Entity

@Entity 
@Table(name = "ARTICLE") 
@Getter 
@Setter 
public class Article extends BaseEntity { 
    private String title; 
    private String name; 
    private String iconName; 
    @ManyToOne 
    @JoinColumn(name = "AUTHOR_ID") 
    private UserItem author; 
    private Long editorId; 
    @Lob 
    private String article; 
}

UserItem Entity

@Entity 
@Table(name = "USER") 
@Getter 
@Setter 
@EqualsAndHashCode(callSuper = false, of = { "username", "company" }) 
public class UserItem extends BaseEntity { 
    private String username; 
    private String name; 
    private String lastName; 
    private String phone; 
    private String password; 
    private String company; 
    private String reasonsForAccess; 
    private Integer failLogins = 0; 
    private boolean enabled = true; 
    private boolean accountNonExpired; 
    private boolean accountNonLocked; 
    private boolean passwordNonExpired; 
    private boolean credentialsNonExpired; 
    @ManyToMany(fetch = FetchType.LAZY) 
    @JoinTable( 
        name = "USER_TO_ROLE", 
        joinColumns = @JoinColumn(name = "USER_ID"), 
        inverseJoinColumns = @JoinColumn(name = "ROLE_ID")) 
    private Set<RoleItem> roles; 
    @ManyToMany(cascade = { CascadeType.PERSIST }, fetch = FetchType.LAZY) 
    @JoinTable( 
        name = "USER_ANSWER", 
        joinColumns = { @JoinColumn(name = "USER_ID") }, 
        inverseJoinColumns = { @JoinColumn(name = "QUESTION_ANSWER_ID") } ) 
    Set<QuestionAnswerItem> answers = new HashSet<>(); 
    @OneToMany(mappedBy = "author") 
    private Set<Article> articles; 
}

The Fixes

Here's how to resolve the issue:

  1. Reorder your data.sql inserts
    Move the INSERT INTO PUBLIC.USER block before the INSERT INTO PUBLIC.ARTICLE block. This ensures the user with ID=1 exists when you insert articles that reference it. Your corrected script should look like this:

    -- Insert users first to satisfy foreign key constraints
    INSERT INTO PUBLIC.USER(ID, VERSION, CREDENTIALS_NON_EXPIRED, ACCOUNT_NON_EXPIRED, ACCOUNT_NON_LOCKED, COMPANY, ENABLED, FAIL_LOGINS, LAST_NAME, NAME, PASSWORD, PASSWORD_NON_EXPIRED, PHONE, REASONS_FOR_ACCESS, USERNAME) 
    VALUES 
    (1, 7, TRUE, TRUE, TRUE, 'lingaro', TRUE, 0, 'admin', 'admin', '$2a$11$TiefIbi6p15IAlGZsTIxquCNDrRCCjmzt9lTN0/D.toRFDVG3ECYO', TRUE, NULL, 'good', 'admin@mail.com'), 
    (2, 0, TRUE, TRUE, TRUE, 'lingaro', TRUE, 0, 'user', 'user', '$2a$10$GS4IiuO9ygrHOr2e.lFx4euYACa6ZENz52KmGx8l.WCEqH03.HPsO', TRUE, NULL, 'good', 'user@mail.com'), 
    (33, 4, TRUE, TRUE, TRUE, 'lingaroaaaaaaaa', TRUE, 0, 'admin', 'admin', '$2a$10$AJMuV2lAeg1XQoPIYQklju9t6aWyVrPMreXVOCaRgJhoxsp831Yhe', TRUE, NULL, 'good good', 'admin1'), 
    (97, 0, TRUE, TRUE, TRUE, 'PG', TRUE, 0, 'hu_ta', 'hu_ta', '$2a$10$3opTpBQkdbvt8AA1aEOaM.YyCHh98ODxsPBlQ6IrX23o9HxUDyALq', TRUE, NULL, 'Ping Federation', 'hu_ta'), 
    (161, 0, TRUE, TRUE, TRUE, 'PG', TRUE, 0, 'tatar.ht', 'tatar.ht', '$2a$10$iDfgmuKJI1YHRK4DKsm4mOZ/CdnE.5GoWYijEzdsdU/SnulJCHRYS', TRUE, NULL, 'Ping Federation', 'tatar.ht');
    
    -- Now insert articles that reference existing users
    INSERT INTO PUBLIC.ARTICLE(ID, VERSION, ARTICLE, AUTHOR_ID, ICON_NAME, NAME, TITLE, EDITOR_ID) 
    VALUES 
    (4, 0, 'clobclobyolo', 1, 'book', 'Introduction to 1, Consumer Place', 'one', null), 
    (5, 0, 'clobclobyolo', 1, 'mail', 'Email Solution (Digital Marketing Center)', 'one', null), 
    (6, 0, 'clobclobyolo', 1, 'glob', 'Global Registration System (GRS)', 'one', null), 
    (7, 0, 'clobclobyolo', 1, 'ticket', 'Ticketing Tool to drive CRM work (Service Now)', 'one', null), 
    (8, 0, 'clobclobyolo', 1, 'pie-chart', '1.Consumer Place Reporting', 'one', null), 
    (9, 0, 'clobclobyolo', 1, 'sms', 'SMS Solution', 'one', null), 
    (10, 0, 'clobclobyolo', 1, 'list', 'Driving trial through Brand Propensity Model', 'one', null), 
    (11, 0, 'clobclobyolo', 1, 'line-chart', 'Data Integration Capabilities', 'one', null), 
    (12, 0, 'clobclobyolo', 1, 'application', 'What is DMP, CRM and DMP better together', 'one', null), 
    (13, 0, 'clobclobyolo', 1, 'bar-chart', 'Data Source performance Tracking', 'one', null), 
    (14, 0, 'clobclobyolo', 1, 'facebook', 'Facebook Leads Campaigns', 'one', null), 
    (15, 0, 'clobclobyolo', 1, 'cloud-glob', 'Learn more about Data Enrichments', 'one', null);
    
  2. Optional: Split scripts for better maintainability
    If your data setup grows more complex, split inserts into separate files (e.g., user-data.sql and article-data.sql). Then use Spring's @Sql annotation in your test class to enforce execution order:

    @Sql(scripts = {"classpath:user-data.sql", "classpath:article-data.sql"})
    @SpringBootTest
    public class YourTestClass {
        // Test methods go here
    }
    
  3. Verify foreign key constraints (if needed)
    Double-check that the ARTICLE.AUTHOR_ID column has a foreign key constraint pointing to USER.ID. Your JPA annotations should handle this when Hibernate generates the schema, but if you're using a pre-existing schema, confirm the constraint exists in your database.

The Error You Encountered (for reference)

java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:125)
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:108)
at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:190)
at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInst...

内容的提问来源于stack exchange,提问作者Jack_Russell

火山引擎 最新活动