java PSQLException:错误:重复键值在使用 Hibernate 时违反了唯一约束
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/36397008/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
PSQLException: ERROR: duplicate key value violates unique constraint when using Hibernate
提问by Avi
I have two objects with one-to-many relationship between them that I implemented as follows:
我有两个对象,它们之间具有一对多的关系,我实现如下:
@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;
}
And the second one:
第二个:
@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)
}
I call a save()
method on the MainDetails
object. The method looks like this:
我save()
在MainDetails
对象上调用一个方法。该方法如下所示:
public T save(T obj) { // The T in this case is MainDetails
entityManager.persist(obj);
entityManager.flush();
return obj;
}
But then I get this exception:
但后来我得到了这个例外:
Caused by: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "details_pkey" Detail: Key (details_id)=(8) already exists.
My persistence.xml
looks like this:
我的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>
My spring context looks like this:
我的 spring 上下文如下所示:
@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;
}
}
回答by Avi
Ok, that was my mistake (naturally) and I changed 3 things in order for it to work:
好吧,那是我的错误(自然地),我改变了 3 件事以使其正常工作:
Changed both classes to have:
@GeneratedValue(strategy= GenerationType.TABLE)
(Originally I usedGenerationType.AUTO
).I figured out that the method that calls
save()
also callsentityManager.flush()
. After removing the redundant line it solved the issue. Beats me why - I would expect hibernate to just do nothing on a redundantflush()
call, but apparently it was a must in order to solve the issue.
将两个类都更改为:(
@GeneratedValue(strategy= GenerationType.TABLE)
最初我使用GenerationType.AUTO
)。我发现调用的方法
save()
也调用entityManager.flush()
. 去掉多余的线后,问题就解决了。打败我的原因 - 我希望 hibernate 在冗余flush()
调用中什么都不做,但显然这是解决问题的必要条件。