Hibernate - таблица ссылок с дополнительными столбцами - сохранение в одной транзакции - PullRequest
1 голос
/ 20 августа 2010

Я изучаю Hibernate и только что прочитал главу «7.2.3 Добавление столбцов для объединения таблиц» книги «Java Persistance with Hibernate».Моя цель - сохранить Item, Category и CategoryorizedItem в одной транзакции.

Там есть конструктор (стр. 305):

public CategorizedItem(String username, Category category, Item item) {
    // Set fields
    this.username = username;

    this.category = category;
    this.item = item;

    // Set identifier values
    this.id.categoryId = category.getId();
    this.id.itemId = item.getId();

    // Guarantee referential integrity
    category.getCategorizedItems().add(this);
    item.getCategorizedItems().add(this);
}

Он принимает объекты категории и элемента.Если я создаю Категорию и Элемент и хочу связать их с помощью этой техники, они, очевидно, должны быть сохранены ДО, так как category.getId () и item.getId () возвращают ноль.трюк в сумке Hibernate ", который может каскадно сэкономить на объединении таблицы?В соединительной таблице есть дополнительные столбцы.Я хочу сохранить все три объекта в обработчике onSuccess в моем контроллере веб-страницы.Все три объекта или ни один из них не должен быть вставлен.

1 Ответ

2 голосов
/ 20 августа 2010

Вы сказали

Моя цель - сохранить элемент, категорию и категоризированный элемент в одной транзакции

Есть ли хитрость в сумке Hibernate, которая может каскадно сэкономить на объединении таблицы?

Да, используйте MutableInt

@Entity
public class CategorizedItem implements Serializable {

    private CategorizedItemId categorizedItemId;

    private String userName;

    private Category category;
    private Item item;

    /**
      * required no-arg constructor
      */
    public CategorizedItem() {}
    public CategorizedItem(CategorizedItemId categorizedItemId) {
        this.categorizedItemId = categorizedItemId;
    }
    public CategorizedItem(String userName, Category category, Item item) {
        this.userName = userName;

        this.categorizedItemId = new CategorizedItemId(category.getIdAsMutableInt(), item.getIdAsMutableInt());
    }

    @EmbeddedId
    public CategorizedItemId getCategorizedItemId() {
        return this.categorizedItemId;
    }

    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="CATEGORY_ID", insertable=false, updateable=false)
    public Category getCategory() {
        return this.category;
    }

    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="ITEM_ID", insertable=false, updateable=false)
    public Item getItem() {
        return this.item;
    }

    // setter's goes here

    /**
      * It MUST implements Serializable
      * It MUST overrides equals and hashCode method
      * It MUST has a no-arg constructor
      *
      * Hibernate/JPA 1.0 does not support automatic generation of compound primary key
      * You SHOULD set up manually
      */
    @Embeddable
    public static class CategorizedItemId implements Serializable {

        private MutableInt categoryId = new MutableInt(-1);
        private MutableInt itemId = new MutableInt(-1);

        /**
          * required no-arg constructor
          */
        public CategorizedItemId() {}
        public CategorizedItemId(MutableInt categoryId, MutableInt itemId) {
            this.categoryId = categoryId;
            this.itemId = itemId;
        }

        @Column(name="CATEGORY_ID", updateable=false, nullable=false)
        public Integer getCategoryId() {
            return this.categoryId.intValue();
        }

        public void setCategoryId(Integer categoryId) {
            return this.categoryId.setValue(categoryId);
        }

        @Column(name="ITEM_ID", updateable=false, nullable=false)
        public Integer getItemId() {
            return this.itemId.intValue();
        }

        public void setItemId(Integer itemId) {
            return this.itemId.setValue(itemId);
        }

        // getter's and setter's

        @Override
        public boolean equals(Object o) {
            if(!(o instanceof CategorizedItemId))
                return null;

            finalCategorizedItemId other = (CategorizedItemId) o;
            return new EqualsBuilder().append(getCategoryId(), other.getCategoryId())
                                      .append(getItemId(), other.getItemId())
                                      .isEquals();
        }

        @Override
        public int hashCode() {
            return new HashCodeBuilder().append(getCategoryId())
                                        .append(getItemId())
                                        .toHashCode();  
        }

    }

}

Здесь идет Категория

@Entity
public class Category implements Serializable {

    public MutableInt id = new MutableInt(-1);

    private List<CategorizedItem> categorizedItemList = new ArrayList<CategorizedItem>();

    @Transient
    public MutableInt getIdAsMutableInt() {
        return this.id;
    }

    @Id
    @GeneratedValue
    public Integer getId() {
        return this.id.intValue();
    }

    public void setId(Integer id) {
        return this.id.setValue(id);
    }

    @OneToMany(mappedBy="category")
    @JoinColumn(name="CATEGORY_ID", insertable=false, updateable=false)
    @Cascade(CascadeType.SAVE_UPDATE)
    public List<CategorizedItem> getCategorizedItemList() {
        return categorizedItemList;
    }

    // setter's

    /**
      * Use this method when you have a saved Item
      */
    public void addCategorizedItem(CategorizedItem categorizedItem) {
        categorizedItem.setCategorizedItemId(new CategorizedItemId(getIdAsMutableInt(), categorizedItem.getItem().getIdAsMutableInt()));
        categorizedItem.setCategory(this);

        getCategorizedItemList().add(categorizedItem);
    }

}

И Item

@Entity
public class Item implements Serializable {

    public MutableInt id = new MutableInt(-1);

    private List<CategorizedItem> categorizedItemList = new ArrayList<CategorizedItem>();

    @Transient
    public MutableInt getIdAsMutableInt() {
        return this.id;
    }

    @Id
    @GeneratedValue
    public Integer getId() {
        return this.id.intValue();
    }

    public void setId(Integer id) {
        return this.id.setValue(id);
    }

    @OneToMany(mappedBy="item")
    @JoinColumn(name="ITEM_ID", insertable=false, updateable=false)
    @Cascade(CascadeType.SAVE_UPDATE)
    public List<CategorizedItem> getCategorizedItemList() {
        return this.categorizedItemList;
    }

    // setter's

    /**
      * Use this method when you have a saved Category
      */
    public void addCategorizedItem(CategorizedItem categorizedItem) {
        categorizedItem.setCategorizedItemId(new CategorizedItemId(getIdAsMutableInt(), categorizedItem.getCategory().getIdAsMutableInt()));
        categorizedItem.setItem(this);

        getCategorizedItemList().add(categorizedItem);
    }

}

Теперь, потому что вам нужны categoryId и itemId перед сохранением CategoryorizedItem, выполните следующее

Category category = new new Category();
Item item = new Item();

session.save(new Category());
session.save(new Item());
session.save(new CategorizedItem(userName, category, item));

Обратите внимание, что каскадирование работает только тогда, когда у вас есть либо сохраненная категория, либо сохраненный элемент. В противном случае вам необходимо следовать указанному выше подходу

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...