2016-03-16 6 views
0

У меня есть модель, которая выглядит следующим образом:Hibernate вставка вызывает обновление другой таблицы

@Entity 
@Table(name = "A") 
class A { 
    @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL) 
    @JoinTable(name = "A_categories", joinColumns = { 
     @JoinColumn(name = "A_id", nullable = false, updatable = false) }, 
     inverseJoinColumns = { @JoinColumn(name = "category_id", 
       nullable = false, updatable = false) }) 
    private List<Category> categories; 

} 

@Entity 
@Table(name = "category") 
class Category { 
    @Id 
    @Column(name="id") 
    @GeneratedValue 
    private Integer id; 

    @Column(name = "category_name") 
    private String categoryName; 

    @ManyToMany(fetch = FetchType.LAZY, mappedBy = "categories") 
    private List<A> a; 

} 

Так что есть много-ко-многим между A и Category. Теперь категории являются статическими и не могут быть изменены пользователем. Из пользовательского интерфейса пользователь попытается сохранить объект A, и каждый из них может иметь одну или несколько категорий. Таким образом, JSON, который возвращается выглядит немного как это:

{A: {categories: [{id: 1}, {id: 2}, {id: 3}]}} 

Теперь, когда я пытаюсь сохранить этот A объект (после Джексона unmarshalled на Java), я просто хочу записи должны быть сделаны в соединительной таблице, A_categories , для каждой категории новый объект имеет.

Однако сам объект Category также обновляется. Поэтому, если вы заметили, JSON не имеет category_name, поэтому запись базы данных для каждого Category также будет обновлена ​​до записи null для имени.

Как я могу предотвратить это?

ответ

1

два различных подхода:

1) Установить управляемые категории до слияния.

a.setCategories(readAllByIds(a.getCategories())) 

private Collection<Category> readAllByIds(Collection<Category> categories) { 
    Collection<Category> result = new ArrayList(); 
    for (Category category : categories) { 
    result.add(entityManager.getReference(Category.class, category.getId())); 
    } 
    return result; 
} 

EntityManager.getReference возвращает прокси, так что дополнительное преимущество состоит в том, что не круглых базах данных поездок не выполняются для чтения связанных категорий.

С помощью этого решения вы не объединяете десериализованные категории в контекст персистентности, поэтому Hibernate не синхронизирует свое состояние с базой данных.

2) Не каскадом каких-либо операций с A до categories (удалить cascade атрибут).

Таким образом, ни PERSIST, ни MERGE будет каскадно и спящий режим будет просто использовать идентификаторы отдельных Category экземпляров, чтобы сохранить данные в таблице отношений.

Sidenote: Вообще, каскадные REMOVE или ALL в многие-ко-многим ассоциации не имеет смысла (если вы достаете A вы, вероятно, не хотите, чтобы удалить все категории она принадлежит к).

+0

Второе решение. Это имеет смысл удалить его. Благодаря! – starman1979

0

@Column имеет атрибуты, вставляемые и обновляемые. Вы можете установить их в ложь:

@Entity 
@Table(name = "category") 
class Category { 
    @Id 
    @Column(name="id", insertable=false, updatable=false) 
    @GeneratedValue 
    private Integer id; 

    @Column(name = "category_name", insertable=false, updatable=false) 
    private String categoryName; 

    @ManyToMany(fetch = FetchType.LAZY, mappedBy = "categories") 
    private List<A> a; 

} 
0

Вы можете попробовать добавить этот

@Entity 
@Table(name = "category") 
class Category { 
@Id 
@Column(name="id") 
@GeneratedValue 
private Integer id; 

@Column(name = "category_name") 
private String categoryName; 

@ManyToMany(fetch = FetchType.LAZY, mappedBy = "categories", cascade=CascadeType.DETACH) 
private List<A> a; 

}

с cascade.DETACH не должны сохранить изменения при сохранении сущности, но дайте мне знать, если не работает, чтобы сделать пример модифицируя ManyToMany с этим действием DETACH

Смежные вопросы