休眠:session.get(...) 与 session.getNamedQuery(...)

Hibernate : session.get(...) vs session.getNamedQuery(...)

在交易过程中,我 create/save 一个对象,在交易结束时我再次读取对象(在设置历史事件之前)

@org.springframework.stereotype.Service
@Transactional(value="transactionManager")
public class UTServiceImpl implements UTService {
    private static final Logger logger = Logger.getLogger(UTServiceImpl.class);
    ...

    @Autowired
    private DeclarationDao declarationDao;
...

public Integer ajouterPersonneImpliquee(ContexteService contexte, Integer pkQualification, Integer pkUT, Acteur personneImpliquee) throws ExceptionValidation {
...

            pk = declarationDao.creerActeur(pkDeclaration, personneImpliquee);

....        

        // History
        personneImpliquee = declarationDao.rechercherActeurAvecAssurance(personneImpliquee.getPk());
        creerActeGestionActeur(creationActeur, personneImpliquee, contexte.getIdentifiantUtilisateur(), declaration, ut);

        return pk;
    }
}

DAO

@Repository
public class DeclarationDaoImpl implements DeclarationDao { 
    private Logger logger;  

    @Autowired @Qualifier("sessionFactorySinistre")
    private SessionFactory sf;

    public DeclarationDaoImpl() {

    }
....

 public Integer creerActeur(Integer pkDeclaration, Acteur acteur) {
        final Session session = sf.getCurrentSession();

        // On retrouve la déclaration
        Declaration declaration = (Declaration) session.get(Declaration.class, pkDeclaration);
        if (declaration == null) {
            throw new ExceptionPkEntiteInconnu(Declaration.class, pkDeclaration);
        }

        // On ne persiste pas la personne quand c'est un sociétaire, appel NOA systématique
        if (Acteur.TYPE_SOCIETAIRE.equals(acteur.getTypePersonne())) {
            acteur.setPersonne(null);
        }

        declaration.getActeurs().add(acteur);
        session.save(acteur);
        return acteur.getPk();
    }
...
    public Acteur rechercherActeurAvecAssurance(Integer pkActeur) {
        final Session session = sf.getCurrentSession();

        Query query = session.getNamedQuery("Declaration_Acteur_Avec_Assurance");
        query.setInteger(0, pkActeur.intValue());
        Acteur acteur = (Acteur) query.uniqueResult();

        // On met la personne en cas de sociétaire
        if (Acteur.TYPE_SOCIETAIRE.equals(acteur.getTypePersonne())) {
            // Il faut ABSOLUMENT détacher l'objet de la session pour ne pas persister la personne rajoutee au flush !!!
            session.evict(acteur);
        }
        return acteur;
    }
...
}

当我使用session.getNamedQuery(...)。我总是得到对象 acteur 的空值。 creerActeur(Integer pkDeclaration, Acteur acteur) 在会话中保存演员之前调用的方法,但不要将其保存到数据库中。 实际上,actor只是在事务结束时才被持久化。

当我们从会话 session.get(Acteur.class, pkActeur) 中获取对象时,问题就解决了。 我得到了我想要的对象演员。

我的问题是: 为什么在执行查询 "Declaration_Acteur_Complet" 时看不到对象参与者(在数据库中)?是否涉及不止一项交易? session.get(...)session.getNamedQuery(...) 有什么区别?

谢谢你的帮助。

您正在使用 sessionFactory.getCurrentSession(),这会返回一个 Spring 托管会话 bean。通常你会得到一个异常(没有活动事务),但你不会因为你已经将 @Transactional 放在你的 UIService 上所以它将整个 ajouterPersonneImpliquee() 方法包装到一个事务中。

刷新时间取决于您的 spring-hibernate 配置。因此,如果我理解正确,您可以在 session.save() 之后调用 session.flush(),或者在 UIService 的不同方法内调用 creerActeGestionActeur(),以便它被 spring 正确包装。

What is the difference between session.get(...) and session.getNamedQuery(...)?

  • session.get(MyClass.class, id)将从数据库中加载对应id
  • 的实体MyClass
  • session.getNamedQuery('myNamedQuery').uniqueResult() 将执行命名查询

Why I can't see the objet actor (in DB) when I execute the Query "Declaration_Acteur_Complet"?

这取决于命名查询背后的内容 'Declaration_Acteur_Avec_Assurance'。它位于您代码中的其他位置。也许是 Acteur class 或在 xml 文件中。

Are there more than one transaction concerned?

没有

感谢您的回答。

在我的 hbm.xml 中查询 'Declaration_Acteur_Avec_Assurance' :

<query name="Declaration_Acteur_Avec_Assurance"><![CDATA[
        select act from com.prima.solutions.primaclaims.core.modele.sinistre.declaration.Acteur act
        left join fetch act.personne
        left join fetch act.assureur assu left join fetch assu.personne
        left join fetch act.intermediaire inter left join fetch inter.personne
        left join fetch act.correspondantAssureur corr left join fetch corr.personne
        where act.pk = ?
    ]]></query>

我没有做就解决了问题

personneImpliquee = declarationDao.rechercherActeurAvecAssurance(personneImpliquee.getPk());

事实上,我有对象'personneImpliquee',我不需要为我的进程调用这个方法。 作为参考,我用最新的技术重构了一个旧的应用程序。