我有两个类PLibObject和PLibEntry。 PLibObject可以有多个PLibEntries。 PLibEntry只能有一个PLibObject。
使用PLibEntry存储PLibObject时会抛出ConstraintViolationException(请参阅底部的异常)。
@Entity
@Table(name = "pla_objects")
public class PLibObject {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
@Column(name = "plibid", unique = true, nullable = false)
private String plibId;
@Column(name = "oid", nullable = false)
private String oid;
@OneToMany(mappedBy = "pLibObject", orphanRemoval = true, cascade = CascadeType.ALL)
private Set<PLibEntry> pLibEntries = new HashSet<PLibEntry>();
...
@Entity
@Table(name = "pla_entries")
public class PLibEntry {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
@Column(name = "entryid", unique = true, nullable = false)
private String entryId;
@Column(name = "userid", nullable = false)
private int userId;
@ManyToOne(optional = false, cascade = CascadeType.ALL)
@JoinColumn(name = "plibid")
private PLibObject pLibObject;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "creationdate", nullable = false)
private Date creationDate;
@Column(name = "sharedfrom", nullable = false)
private String sharedFrom;
@Enumerated(EnumType.STRING)
@Column(name = "sharingstatus", nullable = false)
private SharingStatus sharingStatus;
@ElementCollection
@CollectionTable(name = "pla_tags", joinColumns = @JoinColumn(name = "entryid"))
@Column(name = "tag")
private Set<String> tags;
...
public enum SharingStatus {
UNSHARED,
SHARING_PENDING,
SHARING_ACCEPTED,
SHARING_CANCELLED_BY_SHARER;
}
数据库表(MySQL):
create table pla_objects(
id int(10) not null auto_increment,
plibid varchar(255) not null,
oid varchar(255) not null,
primary key (id),
unique (plibid)
) charset=utf8 engine=innodb;
create table pla_entries(
id int(10) not null auto_increment,
entryid varchar(255) not null,
userid int(10) not null,
plibid varchar(255) not null,
creationdate datetime not null,
sharedfrom varchar(255),
sharingstatus enum('UNSHARED', 'SHARING_PENDING', 'SHARING_ACCEPTED', 'SHARING_CANCELLED_BY_SHARER') not null,
primary key (id),
unique (entryid),
foreign key (plibid) references pla_objects(plibid)
) charset=utf8 engine=innodb;
create table pla_tags(
entryid varchar(255) not null,
tag varchar(255) not null,
primary key (entryid, tag),
foreign key (entryid) references pla_entries(entryid)
) charset=utf8 engine=innodb;
例外:
javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: Referentielle Integrität verletzt: "CONSTRAINT_B23: PUBLIC.PLA_ENTRIES FOREIGN KEY(PLIBID) REFERENCES PUBLIC.PLA_OBJECTS(PLIBID)
产生异常的代码(仅用于测试目的,实际实现要复杂得多):
PLibObject pLibObject = new PLibObject("plibid", "oid");
new PLibEntry("entryid", 0, pLibObject, new Date(1), null, SharingStatus.UNSHARED,
Arrays.asList("tagA", "tagB")); // entry is set in object via constructor
Map<String, String> map = new HashMap<String, String>();
map.put("javax.persistence.jdbc.url", "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;LOCK_TIMEOUT=3000");
map.put("javax.persistence.jdbc.user", "sa");
map.put("javax.persistence.jdbc.password", "sa");
map.put(Environment.SHOW_SQL, "true");
map.put(Environment.FORMAT_SQL, "true");
EntityManagerFactory factory = Persistence.createEntityManagerFactory("plib", map);
EntityManager entityManager = factory.createEntityManager();
entityManager.getTransaction().begin();
entityManager.persist(pLibObject);
entityManager.getTransaction().commit();
答案 0 :(得分:1)
您如何存储数据?
也许您正在为PLibObject设置一组pLibEntries,并且Set的每个元素PLibEntry都有一个空的PLibObject,并且因为您已经标记了CascadeType.ALL它正在尝试使用NULL Pk持久保存PLibObject。
答案 1 :(得分:1)
看起来它认为你试图在另一个表中给plibid列的plibEntry所有权。尝试为其指定表
@ManyToOne(optional = false, cascade = CascadeType.ALL)
@JoinColumn(table = "pla_entries", name = "plibid")
private PLibObject pLibObject;
答案 2 :(得分:1)
这很奇怪 - 我使用Spring并且第一次插入它可以正常工作:
PLibObject pLibObject = new PLibObject("plibid", "oid");
PLibEntry entry = new PLibEntry("entryid", 0, pLibObject, new Date(1), null, SharingStatus.UNSHARED,
Arrays.asList("tagA", "tagB"));
pLibObject.getPLibEntries().add(entry);
SpringUtil.getBean(PLibDao.class).saveOrUpdate(pLibObject);
在PLibEntry
的构造函数中:
public class PLibEntry {
public PLibEntry(String entryId, int i, PLibObject pLibObject2, Date date, String object,
SharingStatus unshared, List<String> asList) {
this.entryId = entryId;
userId = i;
pLibObject = pLibObject2;
this.creationDate = date;
sharedFrom = "";
sharingStatus = unshared;
tags = new HashSet<String>(asList);
}
Spring配置:
@Configuration
@EnableTransactionManagement
public class TestConfiguration {
@Bean
public LocalSessionFactoryBean getSessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(new String[] { "my.package.domain" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
@Bean
public Properties hibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.connection.driver_class", "org.h2.Driver");
properties.put("hibernate.connection.url", "jdbc:h2:db/test;CIPHER=AES");
properties.put("hibernate.connection.username", "root");
properties.put("hibernate.connection.password", "root root");
properties.put("hibernate.connection.pool_size", "1");
properties.put("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
properties.put("hibernate.format_sql", "true");
properties.put("hibernate.use_sql_comments", "true");
properties.put("hibernate.show_sql", "false");
properties.put("hibernate.hbm2ddl.auto", "update");
properties.put("hibernate.c3p0.min_size", "5");
properties.put("hibernate.c3p0.max_size", "20");
properties.put("hibernate.c3p0.timeout", "300");
properties.put("hibernate.c3p0.max_statements", "50");
properties.put("hibernate.c3p0.idle_test_period", "3000");
properties.put("hibernate.cache.use_second_level_cache", "true");
properties.put("hibernate.cache.region.factory_class",
"org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory");
properties.put("hibernate.cache.use_query_cache", "true");
properties.put("hibernate.cache.use_minimal_puts", "true");
properties.put("hibernate.max_fetch_depth", "10");
return properties;
}
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.h2.Driver");
dataSource.setUrl("jdbc:h2:db/test;CIPHER=AES");
dataSource.setUsername("root");
dataSource.setPassword("root root");
return dataSource;
}
@Bean
public HibernateTransactionManager transactionManager() {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(getSessionFactory().getObject());
return txManager;
}
@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
@Bean
public PLibDao pLibDao() {
return new PLibDao();
}
}
在main
:
public class App {
public static void main(String[] args) throws IOException {
PLibObject pLibObject = new PLibObject("plibid", "oid");
PLibEntry entry = new PLibEntry("entryid", 0, pLibObject, new Date(1), null, SharingStatus.UNSHARED,
Arrays.asList("tagA", "tagB"));
pLibObject.getPLibEntries().add(entry);
SpringUtil.getBean(PLibDao.class).saveOrUpdate(pLibObject);
SpringUtil类:
public class SpringUtil {
private static AnnotationConfigApplicationContext ctx = buildContext();
private static AnnotationConfigApplicationContext buildContext() {
return new AnnotationConfigApplicationContext(JCashConfiguration.class);
}
public static AnnotationConfigApplicationContext getCtx() {
return ctx;
}
public static <T> T getBean(Class<T> classType) {
return ctx.getBean(classType);
}
public static <T> T getBean(String beanName) {
return (T) getBean(beanName);
}
}