Sono ancora in fase di apprendimento di hibernate/hql e ho una domanda che è metà delle migliori pratiche di controllo/metà sanità mentale.hibernate column unqueness question
Diciamo che ho una classe A:
@Entity
public class A
{
@Id @GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
@Column(unique=true)
private String name = "";
//getters, setters, etc. omitted for brevity
}
voglio far rispettare che ogni istanza di un che viene salvato ha un nome univoco (da qui l'annotazione @Column), ma voglio anche essere in grado per gestire il caso in cui è già presente un'istanza A salvata con quel nome. Vedo due modi per farlo:
1) Posso rilevare org.hibernate.exception.ConstraintViolationException che potrebbe essere generata durante la chiamata session.SaveOrUpdate() e provare a gestirla.
2) Posso interrogare per istanze esistenti di A che hanno già quel nome nel DAO prima di chiamare session.saveOrUpdate().
In questo momento sono inclinato verso l'approccio 2, perché nell'approccio 1 non so come determinare a livello di codice quale vincolo è stato violato (ci sono un paio di altri membri univoci in A). In questo momento il mio DAO.save codice() appare grosso modo così:
public void save(A a) throws DataAccessException, NonUniqueNameException
{
Session session = sessionFactory.getCurrentSession();
try
{
session.beginTransaction();
Query query = null;
//if id isn't null, make sure we don't count this object as a duplicate
if(obj.getId() == null)
{
query = session.createQuery("select count(a) from A a where a.name = :name").setParameter("name", obj.getName());
}
else
{
query = session.createQuery("select count(a) from A a where a.name = :name " +
"and a.id != :id").setParameter("name", obj.getName()).setParameter("name", obj.getName());
}
Long numNameDuplicates = (Long)query.uniqueResult();
if(numNameDuplicates > 0)
throw new NonUniqueNameException();
session.saveOrUpdate(a);
session.getTransaction().commit();
}
catch(RuntimeException e)
{
session.getTransaction().rollback();
throw new DataAccessException(e); //my own class
}
}
Sto andando su questo nel modo giusto? Può ibernare dirmi programmaticamente (cioè non come una stringa di errore) quale valore sta violando il vincolo di unicità? Separando la query dal commit, sto invitando errori di sicurezza del thread o sono sicuro? Come si fa di solito questo?
Grazie!
Avrò problemi di sicurezza del thread con il secondo approccio? Per quanto ho capito, la parte "Isolation" dei principi ACID DB dovrebbe aiutarmi qui, ma non sono sicuro di quanto hibernate/hsqldb sia compatibile con questo. – Seth
Non capisco perché l'isolamento sia importante per questo caso. Verificare se un nome esiste avverrebbe nella stessa transazione e non altera lo stato dei dati nel database. – Rachel