Java EE / Hibernate从数据库中提取数据,并通过持久化将它们分离

时间:2014-06-17 18:41:16

标签: hibernate java-ee jpa

我是Java EE的新手。 我的问题是保留包含我从数据库中提取的数据的数据。它总是说数据被检测到(我知道从数据库中提取数据是有问题的,但我怎么能这样做呢?)。

这就是我所拥有的:

我有三个实体:游戏,流派和发布者

游戏:

@Getter
@Setter
@Entity
public class Game extends BaseEntity {

    @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinTable(name = "game_genre", joinColumns = { @JoinColumn(name = "game_id") }, inverseJoinColumns = { @JoinColumn(name = "genre_id") })
    private Set<Genre> genres = new HashSet<Genre>();

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name="publisher_id")
    private Publisher publisher;


    @NotNull(message = "Bitte Namen hinzufügen")
    private String name;

    @Override
    public String toString() {
        return this.name + this.genres.toString() + this.publisher.toString();
    }
}

类型:

@Getter
@Setter
@Entity
public class Genre extends BaseEntity {

    private String name;

    @ManyToMany(mappedBy = "genres", fetch=FetchType.EAGER)
    private Set<Game> games = new HashSet<Game>();

    @Override
    public String toString() {
        return name.toString();
    }
}

出版商:

@Getter
@Setter
@Entity
public class Publisher extends BaseEntity {

    private String name;

    @OneToMany(mappedBy="publisher", fetch = FetchType.EAGER, cascade = CascadeType.ALL )
    private Set<Game> games = new HashSet<Game>();

    @Override
    public String toString() {
        return name.toString();
    }
}

在我的AbstractDao

@Override
public void create(final T t) {
    this.em.persist(t);
}

@Override
public void update(final T t) {
    this.em.merge(t);
}

和每个实体Dao的findAll()方法

@Override
public List<Game> findAll() {

    final TypedQuery<Game> query = getEm().createQuery(
            "Select a FROM " + Game.class.getSimpleName() + " a", Game.class);

    return query.getResultList();

}

我的经理:

manager is an instance of GameManagerBo:

@Stateless
@ManagedBean(name = "manager")
public class GameManagerBo implements GameManager {

    @Inject
    private Dao<Game> gameDao;
    @Inject
    private Dao<Genre> genreDao;
    @Inject
    private Dao<Publisher> publisherDao;

    @Override //Same for Genre and Publisher
    public void saveGame(Game game) {
        if (game.getId() == null) {
            this.gameDao.create(game);
        } else {
            this.gameDao.update(game);
        }
    }

    @Override //Same for Genre and Publisher
    public List<Game> readGames() {
        return this.gameDao.findAll();
    }

    @Override
    public Publisher getPublisherByName(String publisherName) {
        List<Publisher> publishers = publisherDao.findAll();
        Publisher foundPublisher = new Publisher();

        for (Publisher publisher : publishers) {
            if(publisher.getName().equals(publisherName)){
                foundPublisher = publisher;
            }
        }

        return foundPublisher;
    }
}

在这里我调用函数:createGame()包括:

private void createGame(String name, String genreName, String publisherName) {
    Game game = new Game();
    game.setName(name);

    Genre genre = new Genre();
    genre.setName(genreName);

    Publisher publisher;

    if (manager.getPublisherByName(publisherName).getId() == null) {
        publisher = new Publisher();
        publisher.setName(publisherName);
    } else {
        publisher = manager.getPublisherByName(publisherName);
    }

    Set<Game> games = new HashSet<Game>();
    games.add(game);

    game.setPublisher(publisher);
    games.addAll(publisher.getGames());

    publisher.setGames(games);

    manager.savePublisher(publisher);
    manager.saveGame(game);
    manager.saveGenre(genre);
}

第一次运行此功能时一切都很好。数据将持久存储到数据库中。但是,如果我运行它一段时间,我会收到此错误:

javax.ejb.EJBException:javax.persistence.PersistenceException:org.hibernate.PersistentObjectException:传递给persist的分离实体:de.fhb.rangam.data.Publisher

以及其他一些长篇文章,但这并不重要。

我没有得到的是为什么游戏获得Persiste和流派。发布应该更新?  我得到的错误,请帮忙!

很抱歉,如果已经有答案,我没有找到它,只是在我花了大约2天通过爬网找到解决方案之后再问。

1 个答案:

答案 0 :(得分:0)

合并也可以插入或更新..在您的情况下,我认为最好删除条件if (game.getId() == null),并始终调用将插入和更新的update ..

差异是:

Persist接受一个实体实例,将其添加到上下文并使该实例得到管理(即将跟踪该实体的未来更新)。

Merge创建实体的新实例,从提供的实体复制状态,并管理新副本。您传入的实例将不会被管理(您所做的任何更改都不会成为交易的一部分 - 除非您再次调用合并)。

希望有所帮助