2016-11-16 16 views
6

У меня проблема, когда я не могу сохранить или слить объект, содержащий только ID и коллекцию других объектов. Если я добавлю другое поле, он совершит транзакцию как обычно. Кроме того, если я изменю стратегию генерации ID на AUTO, она также будет работать.Как сохранить объект, который содержит только коллекцию и идентификатор?

Остальная часть моей команды использует «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 и Join Table, он умирает при попытке упорствовать или объединить фильтр без каких-либо полей.

Обходные

  • Изменение GenerationType.IDENTITY в GenerationType.AUTO.

    -The только жулик, кажется, что первый запуск первичных ключей прыгать на 50, то он начинает приращением на 1.

  • Изменение GenerationType в таблице

    -Этот, кажется, что AUTO выбрал.

  • Добавить произвольное поле в объект (т. Е. Тест строки = «тест»).

    -Просто заставляя сущность иметь еще одно поле, оно сохраняется. Однако я не нуждаюсь в этом поле; Мне просто нужна коллекция

  • Сделать отношения двунаправленными.

    -Выставляя отношения двунаправленным, таблицы возвращаются id (вместо того, чтобы просто быть id). Это работает только потому, что Filter принадлежит другой записи.

+0

Если ваш поставщик JPA не поддерживает инструкции INSERT без столбцов, тогда поднимите BUG на нем. Я делаю это с поставщиком, который я использую (DataNucleus), и он генерирует правильный SQL. –

+0

Использование AUTO на самом деле не является ответом, поскольку AUTO означает предоставление ему провайдеру какой стратегии использовать, и они могут просто использовать IDENTITY под обложками, которые заканчиваются той же проблемой. –

+0

Убрано из автора – garfield

ответ

0

Хорошее решение будет сделать код двунаправленным, как вы уже указали, и сделать использование «@PrePersist» аннотация, чтобы установить идентификатор в «Правилах» объекты. Что-то вроде:

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

Код выше подходит для меня.

Я надеюсь, что это решит вашу проблему.

Cheers, Nikolas.

0

Я реализовал проблематичной с 4-х различных примеров:

  1. Просто ID

    @Entity общественный класс реализует Serializable Случай 1. {

    частный статический окончательный длинный serialVersionUID = 1L;

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

    // ...}

  2. Идентификатор + 1 строка столбец

    @Entity общественный класс реализует Serializable Вариант 2 {

    частный статический окончательный длинный serialVersionUID = 1L ;

    @Id @GeneratedValue (strategy = GenerationType.IDENTITY) private Long id; имя частной строки;

    // ...}

  3. Идентификатор + 1 OneToMany ассоциация

а. каскадным = {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 (case1)] пусто. Вы должны определить не менее одно сопоставление для этой таблицы.
  2. Корпус 2: Хорошо работает.
  3. Случай 3: Локальное Исключение Stack: Исключение [EclipseLink-4002] (Eclipse, Постоянство Услуга - 2.4.0.v20120608-r11652): org.eclipse.persistence.exceptions.DatabaseException Внутренняя Исключения: org.postgresql.util.PSQLException: ERREUR: la valeur d'une clé dupliquée rompt la contrainte unique «rule_code_key»
  4. Случай 4: Исключение Описание: Список полей для вставки в таблицу [DatabaseTable (case4)] пуст. Вы должны определить не менее одно сопоставление для этой таблицы.

экспликации ошибок на случаях 1, 3 4 & прост.

  1. Для случая 3, когда у вас есть каскада = {} CascadeType.ALL ОРМ пытается сохраняться Правилом перед тем сохраняющиеся фильтра и все зависит от потребности в моем случае Правила его уже существует.

  2. Для случая 1 & 4, вы пытаетесь упорствовать только идентификатор фильтра на стол N ° 1 и идентификатор правила + ид Фильтр по Join Table. Это означает, что у фильтра есть только идентификатор Синоним проблемы с дизайном = Вы должны определить хотя бы одно сопоставление для этой таблицы.