2016-11-16 54 views
6

我有一个问题,我无法坚持或合并只包含一个ID和其他对象的集合的对象。如果我添加另一个字段,它将正常提交事务。另外,如果我将ID生成策略更改为AUTO,它也会起作用。如何坚持仅包含集合和ID的实体?

我的团队其余人员使用“IDENTITY”而不是“AUTO”,所以我想与他们保持一致。他们的实体不仅仅是一个ID +集合,所以它对他们来说工作得很好。以下是我想要做什么工作:

@Entity 
public class Filter implements Serializable { 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Long id; 

    @OneToMany(fetch = FetchType.EAGER, orphanRemoval = true, cascade = { CascadeType.ALL }) 
    private ArrayList<Rule> rules = new ArrayList<>(); 

    public Filter() { 

    } 

} 

的ErrorMessage:

org.apache.openjpa.persistence.PersistenceException: ERROR: syntax error at or near ")" 
    Position: 25 {prepstmnt 693640431 INSERT INTO Filter() VALUES()} [code=0, state=42601] 
FailedObject: [email protected] 

本质,因为它只是一个ID和一个连接表,它试图持续存在或合并过滤器时死亡没有任何领域。

解决办法

  • 变化GenerationType.IDENTITY到GenerationType.AUTO。

    -The只有CON似乎是最初开始主键到50跳来跳去,然后它开始由1

  • 变化GenerationType递增到表

    - 这似乎正是AUTO采摘。

  • 向实体添加一个任意字段(即String test = “test”)。

    - 简单地使实体有一个字段使其坚持。但是,我并不需要这个领域;我只想要一个集合

  • 使双向关系成为可能。

    - 由于双向关系,表格有一个id返回(而不仅仅是一个id)。这仅适用于Filter由另一个记录拥有。

+0

如果您的JPA提供程序不支持有没有列的INSERT语句,然后提出一个BUG。我用我使用的提供程序(DataNucleus)执行此操作,并生成正确的SQL。 –

+0

使用AUTO并不是真正的答案,因为AUTO意味着将其留给提供者使用什么策略,并且他们可能只是在封面下使用IDENTITY而最终导致相同的问题。 –

+0

已从作者中删除 – garfield

回答

0

一个很好的解决方案将使得代码双向的,因为你已经指出的那样,并利用“@PrePersist”注释,设置id为“规则”的对象。喜欢的东西:

Rule.java

@Entity 
public class Rule implements Serializable { 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Long id; 

    private String description; 

    @ManyToOne 
    private Filter filter; 

    // getters, setters, equals, hashcode, toString... 
} 

Filter.java

@Entity 
public class Filter implements Serializable { 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Long id; 

    @OneToMany(fetch = FetchType.EAGER, orphanRemoval = true, cascade = { CascadeType.ALL }, mappedBy="filter") 
    private List<Rule> rules = new ArrayList<>(); 

    @PrePersist 
    public void prePersist() { 
     if (rules != null) { 
      rules.forEach(item -> item.setFilter(this)); 
     } 
    } 

    // getters, setters, equals, hashcode, toString... 
} 

FilterRepository.java

@Repository 
public interface FilterRepository extends JpaRepository<Filter, Integer> { } 

AnUnitTest.java

@RunWith(SpringRunner.class) 
@SpringBootTest 
public class AnUnitTest { 
    @Autowired 
    private FilterRepository filterRepository; 

    @After 
    public void clearDatabase() { 
     bodyPartRespository.deleteAll(); 

     filterRepository.deleteAll(); 
    } 

    @Test 
    public void testFilterRules() { 
     Rule aRule = Rule.builder() 
       .description("A") 
       .build(); 
     Rule anotherRule = Rule.builder() 
       .description("B") 
       .build(); 

     Filter filter = Filter.builder() 
       .rules(Arrays.asList(aRule, anotherRule)) 
       .build(); 

     filterRepository.saveAndFlush(filter); 

     List<Filter> all = filterRepository.findAll(); 

     all.forEach(System.out::println); 
    } 
} 

上面的代码对我来说运行良好。

我希望这可以解决您的问题。

干杯,尼古拉斯。

0

我实现了你的问题有4个不同的例子:

  1. 就在ID

    @Entity 公共类案例1实现Serializable {

    私有静态最后的serialVersionUID长= 1升;

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id;

    // ... }

  2. 的ID + 1个字符串柱

    @Entity 公共类情况2实现Serializable {

    私有静态最后长的serialVersionUID = 1L ;

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; 私人字符串名称;

    // ... }

  3. 的ID + 1个一对多关联

一个。与级联= {CascadeType.ALL}

> @Entity 
> public class Case3 implements Serializable { 
>   
> private static final long serialVersionUID = 1L; 
>    
> @Id 
> @GeneratedValue(strategy = GenerationType.IDENTITY) 
> private Long id; 
> @OneToMany(fetch = FetchType.EAGER, orphanRemoval = true, cascade = { CascadeType.ALL }) 
> private ArrayList<AdminUtilisateur> users = new ArrayList<>();   
> // ... 
>} 

湾无级联= {CascadeType.ALL}

> @Entity 
> public class Case4 implements Serializable { 
>   
> private static final long serialVersionUID = 1L; 
>    
> @Id 
> @GeneratedValue(strategy = GenerationType.IDENTITY) 
> private Long id; 
> 
> @OneToMany(fetch = FetchType.EAGER, orphanRemoval = true) 
> private ArrayList<AdminUtilisateur> users = new ArrayList<>();  
> // ... 
>} 

结果是细跟SQL查询(PostgreSQL的9.3下测试)。 但随着javax.persistence,我已经得到了不同的结果:

  1. 案例1:异常说明:字段列表插入到表[DatabaseTable(情形)是空的。您必须至少为此表定义 一个映射。
  2. 案例2:工作正常。
  3. 案例3:本地异常堆栈:异常[的EclipseLink-4002](Eclipse持久服务 - 2.4.0.v20120608-r11652): org.eclipse.persistence.exceptions.DatabaseException内部 例外:org.postgresql.util。PSQLException:ERREUR:la valeur d'une clédupliquéerompt la contrainte unique«rule_code_key»
  4. 案例4:异常描述:要插入表[DatabaseTable(case4)]的字段列表为空。您必须至少为此表定义 一个映射。

上例1中的错误的解释,3 & 4是简单的。

  1. 对于案例3,当你有级联= {} CascadeType.ALL的 ORM尝试坚持规则坚持过滤之前,一切都取决于需要,我的情况规则它已经存在。

  2. 对于案例1 & 4,你想坚持过滤的只是ID上表N°1和规则的ID +过滤器上的ID加入表。 这意味着过滤器只有ID 设计问题的同义词 =您必须为此表至少定义一个映射。