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

2.7k views Asked by At

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.

3

There are 3 answers

0
AntJavaDev On BEST ANSWER

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.

0
Nicolas Quenon On

Thanks for answers.

Query 'Declaration_Acteur_Avec_Assurance' in my hbm.xml :

<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>

I have solved the issue by not doing

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

In fact, I have the object 'personneImpliquee' and I don't need to call this method for my process. For information, I refactor an old application with the latest technology.

0
couettos On

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

  • session.get(MyClass.class, id) will load from the database the entity MyClass with the corresponding id
  • session.getNamedQuery('myNamedQuery').uniqueResult() will execute the named query

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

It depends on what is behind the named query 'Declaration_Acteur_Avec_Assurance'. It is located somewhere else in your code. Maybe the Acteur class or in a xml file.

Are there more than one transaction concerned?

No