Search code examples
javahibernatedaohibernate-session

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


In the a transaction process I create/save an object and next to end of transaction I read again object (before setting an history event)

@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;
    }
}

The 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;
    }
...
}

When I use session.getNamedQuery(...). I got always null value for the object acteur. The method creerActeur(Integer pkDeclaration, Acteur acteur) called before save an actor in session but don't persist it into database. In fact, the actor is persisted only at the end of the transaction.

The problem is solved when we got the object from the session session.get(Acteur.class, pkActeur). I got the object acteur like I want.

My questions are: Why I can't see the object actor (in DB) when I execute the Query "Declaration_Acteur_Complet"? Are there more than one transaction concerned? What is the difference between session.get(...) and session.getNamedQuery(...)?

Thanks for you help.


Solution

  • You are using sessionFactory.getCurrentSession() which gives you a Spring managed session bean back. Ordinarily you would get an exception (no active transaction), but you don't cause you have placed @Transactional on your UIService so it wraps the whole ajouterPersonneImpliquee() method into one transaction.

    The flush time is depended on the spring-hibernate configuration you have. So if i have understood correctly, you can either call session.flush() after session.save(), or call creerActeGestionActeur() inside a different method in the UIService so it gets properly wrapped by spring.