【问题标题】:Hibernate 4 Annotation - MySQL Configuration Error: java.sql.SQLException: Cannot add foreign key constraintHibernate 4 注释 - MySQL 配置错误:java.sql.SQLException:无法添加外键约束
【发布时间】:2017-03-25 03:09:15
【问题描述】:

当我尝试使用 Hibernate 4 - MySQL 配置加载我的 Spring Boot 应用程序时,出现配置堆栈跟踪错误。我不知道是什么导致了这个外键约束问题。 非常感谢您的帮助!

**Caused by: java.sql.SQLException: Cannot add foreign key constraint
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:963)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3966)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3902)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2526)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2673)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2545)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2503)
at com.mysql.jdbc.StatementImpl.executeInternal(StatementImpl.java:839)
at com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:739)
at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:49)
...**

这是我的三个数据库表:

主要实体

@Entity
public class Principal implements {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long principal_id;

@Column(name = "username", unique = true, nullable = false)
private String name;

@Column(unique = true, nullable = false)
private String email;

@Column(nullable = false)
private String password;

@Column(nullable = false)
private Boolean locked;

@ManyToMany( fetch = FetchType.EAGER)
@JoinTable(joinColumns = { @JoinColumn(name = "PRINCIPAL_ID", referencedColumnName = "PRINCIPAL_ID") }, inverseJoinColumns = { @JoinColumn(name = "ROLE_ID", referencedColumnName = "ROLE_ID") })
private Set<Role> roles;


public Principal() {
    super();

    locked = false;
}

public Principal(final String nameToSet, final String passwordToSet, final Set<Role> rolesToSet) {
    super();

    name = nameToSet;
    password = passwordToSet;
    roles = rolesToSet;
}

public Principal(final UserDto userDto) {
    super();

    name = userDto.getName();
    password = userDto.getPassword();
    roles = userDto.getRoles();
}

@Override
public Long getId() {
    return principal_id;
}

@Override
public void setId(final Long idToSet) {
    principal_id = idToSet;
}

@Override
public String getName() {
    return name;
}

public void setName(final String nameToSet) {
    name = nameToSet;
}

public String getEmail() {
    return email;
}

public void setEmail(final String emailToSet) {
    email = emailToSet;
}

public String getPassword() {
    return password;
}

public void setPassword(final String passwordToSet) {
    password = passwordToSet;
}

public Set<Role> getRoles() {
    return roles;
}

public void setRoles(final Set<Role> rolesToSet) {
    roles = rolesToSet;
}

public Boolean getLocked() {
    return locked;
}

public void setLocked(final Boolean lockedToSet) {
    locked = lockedToSet;
}

}

角色实体

@Entity
public class Role implements INameableEntity, INameableDto {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long role_id;

@Column(unique = true, nullable = false)
@Size(min = 2, max = 30)
@NotNull
private String name;

public Role() {
    super();
}

public Role(final String nameToSet) {
    super();
    name = nameToSet;
}

// API

@Override
public Long getId() {
    return role_id;
}

@Override
public void setId(final Long idToSet) {
    role_id = idToSet;
}

@Override
public String getName() {
    return name;
}

public void setName(final String nameToSet) {
    name = nameToSet;
}

persistence-mysql.properties

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/qlc?&useSSL=false
jdbc.username=root
jdbc.password=password


hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
hibernate.show_sql=true
hibernate.hbm2ddl.auto=update

jpa.generateDdl=true

UmPersistenceJpaConfig.java

@Configuration
@EnableTransactionManagement
@ComponentScan({ "org.qlc.um.persistence" })
@PropertySource({ "persistence-mysql.properties" })
@EnableJpaRepositories(basePackages = "org.qlc.um.persistence.dao")
public class UmPersistenceJpaConfig {

@Autowired
private Environment env;

public UmPersistenceJpaConfig() {
    super();
}

// beans

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
    final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
    em.setDataSource(dataSource());
    em.setPackagesToScan(new String[] { "org.qlc.um" });
    final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
    em.setJpaVendorAdapter(vendorAdapter);
    em.setJpaProperties(additionalProperties());
    return em;
}

@Bean
public DataSource dataSource() {
    final DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
    dataSource.setUrl(env.getProperty("jdbc.url"));
    dataSource.setUsername(env.getProperty("jdbc.username"));
    dataSource.setPassword(env.getProperty("jdbc.password"));
    return dataSource;
}

@Bean
public JpaTransactionManager transactionManager() {
    final JpaTransactionManager transactionManager = new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
    return transactionManager;
}

@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
    return new PersistenceExceptionTranslationPostProcessor();
}

//

final Properties additionalProperties() {
    final Properties hibernateProperties = new Properties();
    hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto", "create-drop"));
    hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));

    // setProperty("hibernate.hbm2ddl.auto", hibernateHbm2ddlAuto);
    // setProperty("hibernate.ejb.naming_strategy", org.hibernate.cfg.ImprovedNamingStrategy.class.getName());
    return hibernateProperties;
}

}

【问题讨论】:

  • 得到错误后直接在mysql中运行SHOW ENGINE INNODB STATUS语句,它会告诉你创建外键到底出了什么问题。
  • 这是我在我的应用程序的 maven 配置上执行“全新安装”时遇到的错误。我认为这是休眠的应用程序配置问题,无法正确与我的 mysql 对话。问题不在mysql表中。
  • 但是您是否按照@shadow 的建议显示了 ENGINE INNODB 状态?
  • SHOW ENGINE INNODB STATUS = foreign key (principal_id) references Principal (principal_id):在被引用的列显示为第一列的引用表中找不到索引,或者表中的列类型和引用的表不匹配约束。请注意,使用 >= InnoDB-4.1.12 创建的表中 ENUM 和 SET 的内部存储类型发生了变化,并且旧表中的此类列不能被新表中的此类列引用。正确的外键定义请参考dev.mysql.com/doc/refman/5.7/en/…
  • 不确定是什么问题?看起来我的 principal_id 对 principals_roles 表的 principal_id 的外部约束是问题所在。是我在我的 Java 实体中使用 Set 作为主体吗?

标签: mysql spring hibernate jpa spring-boot


【解决方案1】:

我的猜测,因为您没有在实体的 id 中标记@column,所以它采用您的 getter 的默认属性名称,即“id”

试试, 校长

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
Column(name="principal_id")
private Long principal_id;

角色

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
Column(name="role_id")
private Long role_id;

【讨论】:

  • 感谢您的回复。我尝试了这个新的配置和同样的错误。当当。
  • @John Stafford 你有没有机会混合注释(字段+属性)。顺便说一句,我会尝试在属性上应用 Column(name="role_id") 并查看
  • 是的,我很确定我对此保持一致。我的 at 列名和实例变量都有 principal_id 和 role_id 以避免这个问题
  • 它看起来就像上面的示例,除了 @Column 也包括在内
  • 好的,今晚下班后让我研究一下我的解决方案,我会在几个小时后发布。
猜你喜欢
  • 2021-10-16
  • 2020-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-19
  • 2013-06-02
  • 2018-04-28
相关资源
最近更新 更多