JavaEE/Hibernate从数据库中提取数据,并通过持久化将其分离

JavaEE/Hibernate从数据库中提取数据,并通过持久化将其分离,hibernate,jakarta-ee,jpa,Hibernate,Jakarta Ee,Jpa,我是JavaEE新手。 我的问题是持久化包含我之前从数据库中提取的数据的数据。它总是说数据是被检测到的(我知道从数据库中提取数据是有问题的,但是没有它我怎么能做到呢?) 这就是我所拥有的: 我有三个实体:游戏、流派和出版商 游戏: 以及每个实体Dao的findAll()方法 @Override public List<Game> findAll() { final TypedQuery<Game> query = getEm().createQuery(

我是JavaEE新手。 我的问题是持久化包含我之前从数据库中提取的数据的数据。它总是说数据是被检测到的(我知道从数据库中提取数据是有问题的,但是没有它我怎么能做到呢?)

这就是我所拥有的:

我有三个实体:游戏、流派和出版商

游戏:

以及每个实体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();

}
@覆盖
公共列表findAll(){
final TypedQuery query=getEm().createQuery(
“从“+Game.class.getSimpleName()+”a“,Game.class”中选择一个);
返回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;
    }
}
manager是GameManagerBo的一个实例:
@无国籍
@ManagedBean(name=“manager”)
公共类GameManagerBo实现GameManager{
@注入
私家刀游戏刀;
@注入
私家道根热道;
@注入
私家道;
@覆盖//类型和发布者相同
公共无效保存游戏(游戏){
if(game.getId()==null){
this.gameDao.create(游戏);
}否则{
this.gameDao.update(游戏);
}
}
@覆盖//类型和发布者相同
公开列表阅读游戏(){
返回这个.gameDao.findAll();
}
@凌驾
公共发布服务器getPublisherByName(字符串publisherName){
List publisher=publisherDao.findAll();
Publisher-foundPublisher=new Publisher();
for(发布者:发布者){
if(publisher.getName().equals(publisherName)){
foundPublisher=publisher;
}
}
归还出版商;
}
}
这里我调用函数: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);
}
private void createGame(字符串名称、字符串genreName、字符串publisher名称){
游戏=新游戏();
游戏名称(名称);
流派=新流派();
genre.setName(genreName);
出版商;
if(manager.getPublisherByName(publisherName.getId()==null){
publisher=新publisher();
publisher.setName(publisherName);
}否则{
publisher=manager.getPublisherByName(publisherName);
}
Set games=新HashSet();
games.add(游戏);
game.setPublisher(publisher);
games.addAll(publisher.getGames());
出版者:setGames(游戏);
manager.savePublisher(publisher);
saveGame(游戏);
saveGenre(风格);
}
当我第一次运行这个函数时,一切都很好。数据将持久化到数据库。但如果我再次运行它,我会得到以下错误:

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

和其他一些长的东西,但这并不重要

我不明白的是,为什么游戏会变得持久和风格。应该更新已发布的文档吗? 无论我遇到什么错误,请帮助我


很抱歉,如果已经有答案了,我没有找到它,只是在我花了大约2天的时间通过在互联网上爬行找到解决方案后询问

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

区别在于:

Persist获取一个实体实例,将其添加到上下文中,并对该实例进行管理(即跟踪实体的未来更新)

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


希望这有助于

当我从数据库中提取一个对象时,它是分离的。问题是我给出了一个我在会话中创建的对象的引用。比如:publisher=manager.getPublisherByName(publisherName);但这是完全错误的。。。我必须复制对象,并且不提供对它的引用。我应该这样做:Publisher-tmpPub=manager.getPublisherByName(publisherName);publisher.setName(tmpPub.getName());setId(tmpPub.getId());publisher.setGames(tmpPub.getGames());很简单…欢迎来到Stackoverflow。虽然包含重现您的问题的代码是值得称赞的,但我最初的反应只是“什么?”因为您的示例太长了。有趣的是:您没有包含相关的代码,即抛出错误的
save
方法。我从JPA中学到:您几乎总是想使用
merge()
,但请记住,更新后的实体将由调用返回(您的dao会吞噬该值)。保存在那里:D是的,我知道它很长,但我不知道什么对问题真正重要。啊,我错过了关于其他人都一样的评论。这正是帮助我的原因:)
@Override
public void create(final T t) {
    this.em.persist(t);
}

@Override
public void update(final T t) {
    this.em.merge(t);
}
@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;
    }
}
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);
}