JAVA JPA обновляет связанные объекты - PullRequest
1 голос
/ 27 июня 2010

У меня проблема с обновлением связанных сущностей.

Позвольте мне начать с простого примера. Предположим, у меня есть отношение профиля пользователя 1: 1.

Как я могу обновить (заменить) профиль объекта, который принадлежит пользователю?

Я безуспешно пробовал следующее (оба отношения OneToOne имеют свойство CascadeType = ALL)

em.getTransaction().begin();

1.User.setProfile(Profile)
....
2.User.setProfile(Profile)
Profile.setUser(User)
.....
3.em.remove(User.getProfile())
User.setProfile(Profile)
Profile.setUser(User)

em.getTransaction().commit();

Я полностью запутался с JPA, есть несколько полезных примеров, но они не касаются обновления сущностей (просто обновление отдельных значений, повышение зарплаты и т. Д.)

Я надеюсь, что предложенный способ будет работать и в случае отношений 1: N.

Ответы [ 4 ]

0 голосов
/ 28 июня 2010

Я удалил CascadeType ALL, и все работает, как мы ожидали, вот код


......................... CPROFILE
@Entity
public class CProfile {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Key id;
        private String phone;</p>

<pre><code>    @OneToOne(mappedBy="profile")
    private CUser User;

......................... CUSER @Сущность открытый класс CUser { @Я бы @GeneratedValue (стратегии = GenerationType.IDENTITY) идентификатор закрытого ключа; приватный String email;

@OneToMany(mappedBy="user")
private List<CPossibility> Possibilities = new ArrayList<CPossibility>();

@OneToOne 
@JoinColumn(name="cprofile_id") 
private CProfile profile;   

......................... СОЗДАТЬ ... CUser User = em.find (CUser.class, UserId_); ...
em.getTransaction () начинают (). пытаться { Profile_.setUser (Пользователь); User.setProfile (Profile _);

        em.persist(Profile_);

        em.getTransaction().commit();
    }
    catch(Exception e){GAEHelper.getLogger().warning("Exception:"+e.getMessage()+" "+e.getCause());}        
    finally {
        if (em.getTransaction().isActive()) {
            em.getTransaction().rollback();
        }
    }

    em.close();

    return true;
}

......................... ОБНОВЛЕНИЕ
... CUser User = em.find (CUser.class, UserId_); ... em.getTransaction () начинается (). пытаться { em.remove (User.getProfile ());

        Profile_.setUser(User);             
        User.setProfile(Profile_);

        em.persist(Profile_);
        em.getTransaction().commit();
    }

Спасибо, ребята!

cscsaba

0 голосов
/ 27 июня 2010

Это зависит от того, что вы хотите сделать.Если пользователь и профиль действительно один-к-одному, тогда сама идея замены всего объекта Профиль на другой является немного избыточной.Если вы используете платформу, которая сохраняет контекст постоянства для всей операции, то вы можете просто обновить значения в объекте Profile и очистить, так как создание новых объектов будет немного запутаннымиз-за каскадов.

Однако, если ваша инфраструктура не поддерживает контекст постоянства, у вас будут отдельные объекты, которые были изменены, и вы должны либо использовать em.merge() , либо * 1013.* вы можете получить исходную сущность (em.find) и скопировать свойства в. IMO, это утомительно, подвержено ошибкам и не нужно, учитывая структуру, которая правильно использует JPA.Гораздо лучше изменить объекты в контексте постоянства и позволить «автообновлению сущности» выполнить свою работу (что, очевидно, я большой поклонник).Требуется немного привыкнуть, но как только вы его получите, вам больше не придется возвращаться.

В любом случае все изменения будут записаны в соединение JDBC при вызове em.flush()и ожидающие изменения в соединении будут зафиксированы после завершения транзакции.

0 голосов
/ 28 июня 2010

Как я могу обновить (заменить) профиль объекта, который принадлежит пользователю?

Поскольку ваша связь является двунаправленной, вы должны управлять обеими сторонами связи между User и Profile. Поэтому для «изменения» профиля пользователя потребуется что-то вроде этого:

User user = em.find(User.class, key);

Profile profile = new Profile();
...
user.setProfile(profile);
profile.setUser(user);

em.getTransaction().commit(); 

При использовании JPA-реализации для приведенного выше кода был выполнен следующий запрос:

INSERT INTO CPROFILE (ID) VALUES (?)
    bind => [2]
UPDATE CUSER SET CPROFILE_ID = ? WHERE (ID = ?)
    bind => [2, 1]
0 голосов
/ 27 июня 2010

Я всегда делаю em.merge(user); после обновления сущности. Это также обновит все связанные объекты, если у вас есть соответствующие параметры каскадирования.

Теперь я знаю (слышал), что объект должен обновлять базу данных сам к концу транзакции, но я предпочитаю прямой вызов. И, честно говоря, я считаю, что весь шаблон «автообновления сущности» является скорее проблемой, чем преимуществом в реальной разработке.

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