JPA - Как избежать получения пустого списка? - PullRequest
1 голос
/ 29 октября 2011

Я создаю своего рода сайт социальной сети, такой как Facebook, как университетский проект. Пользователи могут загружать фотографии, но я почему-то не могу получить список фотографий для конкретного пользователя.

Вот как я это делаю прямо сейчас:

@Entity
@Table(name = "users")
public class User implements Serializable {

@Id
private String emailAddress;
private String password;
private String firstName;
private String lastName;

(...)

@OneToMany(mappedBy = "owner", fetch = FetchType.EAGER)
private List<Photo> photos;

public User() {
}

(...)

public void addPhoto( Photo photo){
    photos.add(photo);
}

public List<Photo> getPhotos() {
    return photos;
}
}

А вот объект "Фото":

@Entity
public class Photo implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String url;
private String label;     
@ManyToOne
private User owner;

public Photo() {
}

(...)

public User getOwner() {
    return owner;
}    
}

Каждая фотография загружается путем создания поста, который содержит ее. Вот EJB, который делает это:

@Stateless
public class PublicPost implements PublicPostRemote {

@PersistenceContext
EntityManager em;

@Override
public void createPost(LoginUserRemote loginUserBean, String targetEmail, final String content, final String photoURL) {
    if (loginUserBean.isLoggedIn()) {
        final User author = loginUserBean.getLoggedUser();
        System.out.println(targetEmail);
        final User target = em.find(User.class, targetEmail);
        if (author != null && target != null) {
            //See if there's a photo to post as well
            Photo photo = null;
            if (photoURL != null) {
                photo = new Photo(photoURL, author, content);
                em.persist(photo);
            }

            MessageBoard publicMessageBoard = target.getPublicMessageBoard();
            Post post = new Post(author, content);
            post.setMessageBoard(publicMessageBoard);
            if (photo != null) {
                post.setPostPhoto(photo);
            }
            em.persist(post);
            em.refresh(publicMessageBoard);
            //Send an e-mail to the target (if the author and the target are different)
            if (!author.getEmailAddress().equals(target.getEmailAddress())) {
                final String subject = "[PhaseBook] " + author.getEmailAddress() + " has posted on your public message board.";
                Thread mailThread = new Thread() {

                    @Override
                    public void run() {
                        try {
                            GMailSender.sendMessage(target.getEmailAddress(), subject, content);
                        } catch (MessagingException ex) {
                            Logger.getLogger(PublicPost.class.getName()).log(Level.SEVERE, null, ex);
                        }
                    }
                };
                mailThread.start();
            }
        }
    }
}
}

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

LoginUserRemote lur = (LoginUserRemote)session.getAttribute("loginUserBean");
User user = lur.getLoggedUser();
List<Photo> photos = user.getPhotos();
System.out.println();
System.out.println("This user has this many photos: " + photos.size());

... это всегда говорит мне, что у пользователя 0 фотографий. Почему это? Я неправильно определяю отношения между пользователем и фотографией? Я забыл что-то сохранить / обновить? Или проблема кроется где-то еще?

Ответы [ 2 ]

1 голос
/ 29 октября 2011

Если вы сохраняете отдельный пользовательский объект (зарегистрированный пользователь) в сеансе HTTP, а затем создаете и сохраняете фотографии, имеющие этого отдельного пользователя в качестве владельца, JPA не будет автоматически добавлять фотографию отдельному пользователю.Для менеджера сущностей этого отдельного пользователя не существует: он больше не находится под его ответственностью.

Даже если пользователь все еще был подключен, вы несете ответственность за поддержание согласованности графа объектов.Если вы изменяете одну сторону ассоциации (устанавливая пользователя в качестве владельца фотографии), вам также следует изменить другую сторону (добавляя фотографию в список фотографий владельца).

I 'Я не совсем уверен, что это является причиной проблемы, потому что вы не показали нам, что было и сделал loginUserBean, чтобы получить зарегистрированного пользователя, но это может быть ответом.

0 голосов
/ 29 октября 2011

Здесь есть ряд проблем:

  • Действительно ли фотографии хранятся в базе данных?Может быть, у вас нет открытой транзакции?

  • Вы не обновляете обе стороны ассоциации.

Теоретически вам нужно только обновитьвладелец, но лучше быть в безопасности, чем потом сожалеть:

photo = new Photo(photoURL, author, content);
em.persist(photo);
author.addPhoto(photo);
  • Вы извлекаете пользователя из сеанса, а затем извлекаете связанную коллекцию фотографий.Вы действительно знаете, что это значит?Если у пользователя есть сотни фотографий, вы действительно хотите хранить их в сеансе HTTP вместе с пользователем?Это не то, как работает Facebook; -).

Я думаю, обновление вашей сущности (с помощью em.refresh(lur.getLoggedUser())) может работать, но только в университете, а не в реальной жизни.Загрузка всех пользовательских фотографий одновременно в память является излишним.Лично я бы даже удалил photos ассоциацию с пользователя, чтобы избежать этого.Загружайте по одной странице за раз и только по требованию.

  • Даже если вы знаете, что делаете, или такое поведение приемлемо, объекты, хранящиеся в сеансе HTTP, называются отсоединенными из контекста постоянства, что означает, что ваш поставщик постоянства больше не отслеживает их.Таким образом, добавление фотографии не означает, что коллекция photos будет магически обновляться в каждом объекте.Я тщательно обдумываю, это было бы еще хуже.

  • И последнее, но не менее важное, ваш createPost() действительно нуждается в некотором пересмотре кода.Он делает по крайней мере 4 вещи одновременно, System.out, один раз потоки создаются по требованию, молча ничего не делая, когда не выполняются предварительные условия (например, пользователь не вошел в систему, пропускает параметры), смешивая проблемы на другом уровне абстракции.Не хочу быть слишком дотошным, но качество вашей оценки может зависеть от качества кода.

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