PSQLException:错误:使用Hibernate时重复的键值违反了唯一约束

Avi*_*Avi 1 java spring hibernate

我有两个对象,它们之间具有一对多的关系,实现如下:

@Entity
@Table(name = "details")
public class MainDetails {
     @Id
     @Column(name = "details_id")
     @GeneratedValue(strategy= GenerationType.AUTO)
     private Long id;

     // Some other fields here - omitted

     @OneToMany(fetch = FetchType.LAZY,
                mappedBy = "details",
                targetEntity = State.class,
                cascade = CascadeType.ALL)
     @OrderBy("timestamp DESC")
     private List<State> states;
}
Run Code Online (Sandbox Code Playgroud)

第二个:

@Entity
@Table(name = "state")
public class State {

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

     @ManyToOne(fetch = FetchType.LAZY)
     @JoinColumn(name = "details_id")
     private MainDetails details;

     // Other fields omitted (including timestamp)

}
Run Code Online (Sandbox Code Playgroud)

save()MainDetails对象上调用一个方法。该方法如下所示:

public T save(T obj) { // The T in this case is MainDetails
  entityManager.persist(obj);
  entityManager.flush();
  return obj;
}
Run Code Online (Sandbox Code Playgroud)

但是然后我得到这个异常:

Caused by: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "details_pkey" Detail: Key (details_id)=(8) already exists.
Run Code Online (Sandbox Code Playgroud)

我的persistence.xml样子是这样的:

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
         version="2.0">
  <persistence-unit name="my-persistence-unit">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <!-- Annotated entity classes -->
    <class>com.company.entity.MainDetails</class>
    <class>com.company.entity.State</class>

    <properties>
      <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQL82Dialect" />
      <property name="hibernate.hbm2ddl.auto" value="create-drop" />
      <property name="hibernate.enable_lazy_load_no_trans" value="true"/>
    </properties>
  </persistence-unit>
</persistence>
Run Code Online (Sandbox Code Playgroud)

我的春季背景看起来像这样:

@EnableJpaRepositories(basePackages = {"com.company.dao", "com.company.*.dao"})
@EnableTransactionManagement(proxyTargetClass = true)
@Import(BasicConfig.class)
public class DbConfig {

  @Value("${db.connection_string}")
  private String connectionString;

  @Value("${db.user_name}")
  private String dbUserName;

  @Value("${db.password}")
  private String dbPassword;

  @Bean
  public DataSource dataSource() {
    DriverManagerDataSource driver = new DriverManagerDataSource();
    driver.setDriverClassName("org.postgresql.Driver");
    driver.setUrl(connectionString);
    driver.setUsername(dbUserName);
    driver.setPassword(dbPassword);
    return driver;
  }

  @Bean
  public JpaVendorAdapter jpaVendorAdapter() {
    HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
    adapter.setShowSql(true);
    adapter.setGenerateDdl(true);
    adapter.setDatabase(Database.POSTGRESQL);
    return adapter;
  }

  @Bean
  public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws ClassNotFoundException {
    LocalContainerEntityManagerFactoryBean factoryBean = new  LocalContainerEntityManagerFactoryBean();
    factoryBean.setDataSource(dataSource());
    factoryBean.setPersistenceUnitName("my-persistence-unit");
    factoryBean.setJpaVendorAdapter(jpaVendorAdapter());

    return factoryBean;
  }

  @Bean
  public JpaTransactionManager transactionManager() throws ClassNotFoundException {
    JpaTransactionManager transactionManager = new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());

    return transactionManager;
  }
}
Run Code Online (Sandbox Code Playgroud)

Avi*_*Avi 5

好的,那是我的错误(自然地),为了使它起作用,我更改了3件事:

  1. 将两个类都更改为:(@GeneratedValue(strategy= GenerationType.TABLE)最初使用GenerationType.AUTO)。

  2. 我发现调用的方法save()也会调用entityManager.flush()。删除冗余线路后,它解决了问题。让我感到沮丧-我希望休眠状态在冗余flush()呼叫上什么也不做,但是显然这是解决问题的必要条件。