Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> hibernate и сохранение в таблицу связи one-to-many 
:(
    Опции темы
umen
Дата 25.4.2007, 14:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 11.11.2006

Репутация: нет
Всего: нет



Добрый день.

Есть два класса User, Story

Код

package su.comedyclub.domain;


import java.util.HashSet;
import java.util.Set;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;

public class User {
    private Long id;
    private String name;
    private Set<Story> stories = new HashSet<Story> ();
    
    public User() {
    }
    
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Set<Story> getStories() {
        return stories;
    }

    public void setStories(Set<Story> stories) {
        this.stories = stories;
    }

    public boolean equals(Object o) {
        if (o == null) {
            return false;
        }
        if (o == this) {
            return true;
        }
        if (!(o instanceof User)) {
            return false;
        }
        
        User user = (User)o;
        return new EqualsBuilder().append(this.name, user.name).isEquals();
    }
    
    public int hashCode() {
        return new HashCodeBuilder(this.id.hashCode(), this.name.hashCode()).toHashCode();
    }
    
    public String toString() {
        return new ToStringBuilder(this).append(this.id).append(this.name).toString();
    }
}



Код

package su.comedyclub.domain;


import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;

public class Story {
    private Long id;
    private String title;
    private String content;
    private Boolean isPublic;
    private User author;
    private Map<User, Long> ratings = new HashMap<User, Long> ();
    

    public Story() {
    }

    public User getAuthor() {
        return author;
    }

    public void setAuthor(User author) {
        this.author = author;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Boolean getIsPublic() {
        return isPublic;
    }

    public void setIsPublic(Boolean isPublic) {
        this.isPublic = isPublic;
    }

    public Map<User, Long> getRatings() {
        return ratings;
    }

    public void setRatings(Map<User, Long> ratings) {
        this.ratings = ratings;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
    
    public boolean equals(Object o) {
        if (o == null) {
            return false;
        }
        if (o == this) {
            return true;
        }
        if (!(o instanceof Story)) {
            return false;
        }
        
        Story story = (Story)o;
        return new EqualsBuilder().append(this.title, story.title)
                    .append(this.content, story.content)
                    .isEquals();
    }
    
    public int hashCode() {
        return new HashCodeBuilder(this.id.hashCode(), this.title.hashCode())
                    .append(this.content)
                    .toHashCode();
    }
    
    public String toString() {
        return new ToStringBuilder(this)
                    .append(this.id)
                    .append(this.title)
                    .append(this.content)
                    .append(this.isPublic)
                    .toString();
    }
    
}



Есть маппинги к ним

Код

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package = "su.comedyclub.domain">

    <class name="User">
        <id name="id" column="id" type="long">
            <generator class="identity"/>
        </id>

        <property name="name" />

        <set inverse="true" name="Stories" lazy="false">
            <key column="userId"/>
            <one-to-many class="Story"/>
        </set>        

    </class>

</hibernate-mapping>


Код

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package = "su.comedyclub.domain">

    <class name="Story">
        <id name="id" column="id" type="long">
            <generator class="identity"/>
        </id>

        <property name="Title"/>
        <property name="Content"/>
        <property name="IsPublic"/>

        <many-to-one class="User" name="Author" not-null="true">
            <column name = "userId" />
        </many-to-one>

    </class>

</hibernate-mapping>


есть тестовый класс

Код

package su.comedyclub.domain;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

public class Test {

    /**
     * @param args
     */
    public static void main(String[] args) {
         SessionFactory sessionFactory;
            sessionFactory = new Configuration().configure().buildSessionFactory();
            
            Session session = sessionFactory.openSession();
            Transaction tx = null;
            try {
             tx = session.beginTransaction();
             
//             AddUsers(session);
             AddUsersAndStories(session);
//             AddStories(session);             
             
             tx.commit();
            } catch (Exception e) {
             if (tx != null) {
                 tx.rollback();
                 System.out.println(e);
             }
            } finally {
             if (tx != null) {
                 session.close();
             }
            }
    }
    
    private static void AddUsers(Session session) {
        User user = new User();
        user.setName("Serge");
        session.persist(user);
    }
    

    private static void AddStories(Session session) {
        Story story = new Story();
        story.setTitle("dfxgdsfg");
        session.persist(story);
    }

    private static void AddUsersAndStories(Session session) {
        User user = new User();
        user.setName("Serge");
        session.persist(user);    
    
//        Story story = new Story();
//        story.setTitle("dfgdsg");
//        story.setContent("gfsdgdgf");
//        story.setIsPublic(true);
//        story.setAuthor(user);            
//        
//        user.getStories().add(story);

        
    }
    

}



в таком виде всё работает.
Если в самом конце теста убрать комменты то вываливается ексепшн:

java.lang.NullPointerException

а по идее должна добавлятся запись в таблицу story

Не могу понять в чём проблема, помогите пожалуйста
PM MAIL   Вверх
umen
Дата 25.4.2007, 18:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 11.11.2006

Репутация: нет
Всего: нет



Для того чтобы легче было понять в чём проблема, я написал два минимальных класса (с минимумом кода) User и Story
И организовал между ними двухстороннюю связь one-to-many. Результат работы - такой же как и в первом случае :-(

минимальный код - во вложении (только *.java, *.hbm.xml)

Может всё-таки кто=-то сможет понять в чем проблема

Это сообщение отредактировал(а) umen - 26.4.2007, 10:38

Присоединённый файл ( Кол-во скачиваний: 14 )
Присоединённый файл  test.zip 1,97 Kb
PM MAIL   Вверх
practices
Дата 1.5.2007, 22:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 1.5.2007

Репутация: нет
Всего: нет



Если подумать логически, когда загружаем объекты определённого класса (в даном примере 

User), вместе с каждым объектом загружается набор связанных объектом другого класса (Set 

stories). Таким образом, объект user содержит ссылки на существующие в БД stories. Когда мы 

добавляем новую story user-у, то нужно сначала сохранить её в БД (save(story)),и только 

потом можно сохранять user с этой story. То есть:

Код

    private static void saveOfficeWithWorkstations(Session session) {
        User user = new User();
        
        Set<Story> stories = new HashSet<Story>();
        
        Story story1 = new Story();
        story1.setUser(user);
        stories.add(story1);
        
        session.save(story1);        

        Story story2 = new Story();
        story2.setUser(user);
        stories.add(story2);

        session.save(story2);
        
        user.setStories(stories);
        
        session.save(user);
    }

    
Или перемести строчку save(storyX) перед stories.add.


Цитата

... я ещё только учусь...


PM MAIL   Вверх
umen
Дата 2.5.2007, 00:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 11.11.2006

Репутация: нет
Всего: нет



При всём уважении, позволю себе не согласиться: магия технологии Hibernate в том и состоит, что не нужно заботится о сохранении всех объектов, в данном случае после добавления истории пользователю и сохранении пользователя, Hibernate сам определяет связи объектов и правильно сохраняет в базу пользователя и добавленную ему историю. 

В подтверждение своих слов привожу вложение, где всё работает. Кстати я так до сих пор и непонял, почему это не работает в коде приведённом выше :(



Присоединённый файл ( Кол-во скачиваний: 40 )
Присоединённый файл  test.rar 3,43 Kb
PM MAIL   Вверх
seth
Дата 27.1.2008, 23:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 316
Регистрация: 4.6.2006

Репутация: 1
Всего: 1



мож кому то пригодится - нашел решение этой проблемы:
http://www.laliluna.de/254.html
т.е. нужно добавить 
Код

cascade="all"

удачи всем smile


--------------------
PM MAIL   Вверх
Ornitos
Дата 31.1.2008, 13:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 15
Регистрация: 13.10.2007
Где: Непал

Репутация: 1
Всего: 3



Каскадное поведение в хибернейт имеет некоторые странности.
Например, даже если вы везде выставили cascade="all", при удалении объектов при помощи HQL запроса зависимые объекты каскадно удаляться не будут.
PM MAIL WWW   Вверх
greef
Дата 31.1.2008, 14:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 47
Регистрация: 10.10.2007

Репутация: нет
Всего: нет



Может кто-то объяснит в 2 словах: что значит и в каких случаях использовать
1) cascade="all"
2) inverse="true"
А то прочтение документации полного ответа не дало.
PM MAIL   Вверх
Ornitos
Дата 2.2.2008, 14:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 15
Регистрация: 13.10.2007
Где: Непал

Репутация: 1
Всего: 3



Цитата(greef @  31.1.2008,  14:40 Найти цитируемый пост)
1) cascade="all"

Включает для данной ассоциации все виды каскадного поведения: каскадную вставку, обновление, удаление и репликацию. Например, при вставке сущности в базу, будет автоматически вызвана вставка и тех сущностей, для ассоциаций с которыми включена каскадная вставка. Аналогично обновление, удаление и репликация.

Цитата(greef @  31.1.2008,  14:40 Найти цитируемый пост)
2) inverse="true"

подробный ответ на вопрос
PM MAIL WWW   Вверх
umen
Дата 5.3.2009, 11:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 11.11.2006

Репутация: нет
Всего: нет



Цитата(Ornitos @ 31.1.2008,  12:43)
Каскадное поведение в хибернейт имеет некоторые странности.
Например, даже если вы везде выставили cascade="all", при удалении объектов при помощи HQL запроса зависимые объекты каскадно удаляться не будут.

Чтобы каскад работал и при удалении, нужно использовать cascade="all-delete-orphan" :

Код

 <class name="User" >
...
   <set
   ...
   cascade="all-delete-orphan"
   ...
   </set>
...
</class> 

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java EE (J2EE) и Spring | Следующая тема »


 




[ Время генерации скрипта: 0.0994 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.