0

我有两个类 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();
4

3 回答 3

1

看起来它认为您正在尝试将 plibEntry 的所有权授予另一个表中的 plibid 列。尝试为它指定表格

 @ManyToOne(optional = false, cascade = CascadeType.ALL)
  @JoinColumn(table = "pla_entries", name = "plibid")
  private PLibObject pLibObject;
于 2012-05-16T20:15:25.810 回答
1

你是如何存储数据的?

也许您正在为您的 PLibObject 设置一组 pLibEntries,并且该集合的每个元素 PLibEntry 都有一个空 PLibObject,并且因为您已标记 CascadeType.ALL 它试图使用 NULL Pk 持久化 PLibObject。

于 2012-05-16T20:14:29.313 回答
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);
}

弹簧配置:

@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);
}

}

于 2012-05-16T21:51:49.187 回答