I'm trying to test my optimistic locking implementation of my application. However the result is not what I expect. The steps I take to test are the following
load an entity from the database
set the version attribute to one less than present in the database
change another attribute thats just a string to something else
save the entity
I expected a staleException now, however the entity just gets saved and the version increases to the next in line.
Here is a small extract of my save code
public <T extends DomainObject> T save(T objectToSave) {
Session currentSession = null;
try {
currentSession = sessionFactory.getCurrentSession();
currentSession.save(objectToSave);
return objectToSave;
} catch (Exception ex) {
logger.error("save error",ex);
}
return null;
}
I load objects by id with named queries thru my entire application with following code
#SuppressWarnings("unchecked")
public <T extends Object> List<T> query(Class<T> returnClass, String query, List<String> namedParams, List<? extends Object> params, Integer limit) {
Session currentSession = null;
try {
currentSession = sessionFactory.getCurrentSession();
Query namedQuery = currentSession.getNamedQuery(query);
if(limit != null){
namedQuery.setMaxResults(limit);
}
namedQuery.setCacheable(true);
if (namedParams != null && namedParams.size() > 0) {
addParams(namedQuery, namedParams, (List<Object>) params);
}
return namedQuery.list();
} catch (Exception ex) {
logger.error("query error",ex);
}
return null;
}
And this is the configuration of my sessionfactory
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="entityInterceptor" ref="auditInterceptor" />
<property name="dataSource" ref="dataSource" />
<property name="hibernateProperties">
<value>
hibernate.dialect=${hibernate.dialect}
hibernate.show_sql=${hibernate.show_sql}
hibernate.cache.provider_class=org.hibernate.cache.EhCacheProvider
hibernate.cache.region.factory_class=net.sf.ehcache.hibernate.EhCacheRegionFactory
hibernate.cache.use_query_cache=true
hibernate.cache.use_second_level_cache=true
hibernate.cache.provider_configuration_file_resource_path=ehcache.xml
hibernate.generate_statistics=true
hbm2ddl.auto=${hbm2ddl.auto}
hibernate.c3p0.min_size=${hibernate.c3p0.min_size}
hibernate.c3p0.max_size=${hibernate.c3p0.max_size}
hibernate.c3p0.timeout=${hibernate.c3p0.timeout}
hibernate.c3p0.max_statements=${hibernate.c3p0.max_statements}
hibernate.c3p0.idle_test_period=${hibernate.c3p0.idle_test_period}
</value>
</property>
<property name="schemaUpdate">
<value>true</value>
</property>
<property name="annotatedClasses">
<list>
<value>com.mbalogos.mba.domain.site.Site</value>
</list>
</property>
</bean>
Is there anything I missed on the configuration of the sessionFactory or do I test it completly wrong and should I test it in a different way ?
Thanks in advance
Regressing the version field is dangerous as it is Hibernate controlled (if you're using the JPA versioning functionality). Load in an entity, detach it (maybe use session.evict(obj)), alter an attribute. Load in the same entity, keep it attached, alter it, save it. Reattach the first entity and attempt to save it (I think Merge will do this). You should then see the StaleObjectStateException exception.
Related
Currently i am developing an application where users are authenticated via LDAP. The criteria for successful login is based on correct username,password and group(TEST-FFSUS-CALBR-USER).
i was able to login successfully with username and password criteria , but not with group criteria.
Following are the code used for this purpose :
#Resource
LdapTemplate ldapTemplate;
public boolean login(String username, String password) {
try {
ContainerCriteria searchCriteria = getLdapFilterCriteria(username);
boolean result = ldapTemplate.authenticate("OU=User,OU=fo-id,DC=feefusde,DC=rootdom,DC=net",
searchCriteria.filter().encode(), password);
return result;
} catch (Exception e) {
return false;
}
}
private ContainerCriteria getLdapFilterCriteria(String usernameOrEmail) {
ContainerCriteria objectClassCriteria = LdapQueryBuilder.query().base("DC=rootdom,DC=net").where("objectClass")
.is("user");
ContainerCriteria mailCriteria = LdapQueryBuilder.query().where("mail").is(usernameOrEmail);
ContainerCriteria cnCriteria = LdapQueryBuilder.query().where("CN").is(usernameOrEmail);
ContainerCriteria roleCriteria = LdapQueryBuilder.query().where("memberOf=CN").is("TEST-FFSUS-CALBR-USER");
ContainerCriteria userByMailOrCnCriteria = mailCriteria.or(cnCriteria);
ContainerCriteria searchCriteria = objectClassCriteria.and(userByMailOrCnCriteria).and(roleCriteria);
return searchCriteria;
}
In application-context:
<bean id="ldapTemplate" class="org.springframework.ldap.core.LdapTemplate">
<property name="contextSource">
<bean class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
<constructor-arg>
<value>ldap://urlofldap:portno</value>
</constructor-arg>
<property name="userDn" value="${ldap.username}" />
<property name="password" value="${ldap.password}" />
</bean>
</property>
</bean>
Is there any way to fix above issue. ?
The memberOf attribute should match the group distinguished name. For example "CN=TEST-FFSUS-CALBR-USER,OU=roles,DC=feefusde,DC=rootdom,DC=net":
ContainerCriteria roleCriteria = LdapQueryBuilder.query().where("memberOf").is(groupDN);
I have a trouble when running my web application that tries to get all the information from the table snowboard and put it in a list which I will then print out in the xHtml. But I get this exception down below.
org.hibernate.TransactionException: nested transactions not supported
The thing is that I have no clue why this exception happens so would appreciate some explanation. Also if you find any trouble in the code that would be fantastic.
This is the exception that I get.
HibernateUtil
public class HibernateUtil {
private static final SessionFactory sessionFactory;
static {
try {
// Create the SessionFactory from standard (hibernate.cfg.xml)
// config file.
sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
} catch (Throwable ex) {
// Log the exception.
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}
SnowHelper, HelperClass
public class SnowHelper {
Session session = null;
public SnowHelper() {
this.session = HibernateUtil.getSessionFactory().getCurrentSession();
}
public List getSnowboards() {
List<Snowboard> snowboardList = null;
try {
Transaction tx = session.beginTransaction();
Query q = session.createQuery("from Snowboard");
snowboardList = (List<Snowboard>) q.list();
} catch (Exception e) {
e.printStackTrace();
}
return snowboardList;
}
}
HibernateCfg
<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://cpsrv01.misshosting.com:3306/etvffqgz_snowshop</property>
<property name="hibernate.connection.username">etvffqgz_user</property>
<property name="hibernate.connection.password">759486456</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.current_session_context_class">thread</property>
<property name="hibernate.query.factory_class">org.hibernate.hql.internal.classic.ClassicQueryTranslatorFactory</property>
<mapping resource="Hibernate/Account.hbm.xml"/>
<mapping resource="Hibernate/Snowboard.hbm.xml"/>
</session-factory>
</hibernate-configuration>
SnowboardBean, ManagedBean class
#Named(value = "snowboardBean")
#Dependent
public class SnowboardBean {
private List<Snowboard> snowList;
private SnowHelper snow;
/**
* Creates a new instance of SnowboardBean
*/
public SnowboardBean() {
snowList = new ArrayList<>();
snow = new SnowHelper();
snowList = snow.getSnowboards();
}
/**
* #return the snowList
*/
public List<Snowboard> getSnowList() {
return snowList;
}
}
In this bit here.. commit your transaction
Transaction tx = session.beginTransaction();
Query q = session.createQuery("from Snowboard");
snowboardList = (List<Snowboard>) q.list();
tx.commit();
Otherwise you simply open a new transaction without closing it every time you invoke this method.. eventually one of them is opened while some other is not commited yet.
If you were using 'container managed transactions' (provided by Spring of EJB's) you would not have to worry about explicitly committing your transactions. Here you are using 'extended transaction management' and you have to take care of that yourself.
I saw nearly all questions and answers for this on stackoverflow, but all answers are the same. That you should use something like this Query query = session.createQuery("from theme").list();
but .list() is depricated and I can´t use it anymore.
So the first Question is, what should I use instead of .list()and why I get this exeption java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: theme is not mapped [from theme]
Query Method
public ObservableList<String> getThemes(){
ObservableList<String> obsList = FXCollections.observableArrayList();
SessionFactory factory = new Configuration()
.configure("hibernate.cfg.xml")
.buildSessionFactory();
Session session = factory.getCurrentSession();
try {
session.beginTransaction();
Query query = session.createQuery("from theme"); // why not mapped
//cant use .list()?
session.getTransaction().commit();
System.out.println("query " + query);
} catch (Exception e) {
e.printStackTrace();
}finally{
session.close();
}
return obsList; // nothing at the moment
hibernate.cfg.xml
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.driver_class">org.sqlite.JDBC</property>
<!-- I know sqlite with an mysql dialect isnt the best, in the future it
will be mySql--> <property
name="connection.url">jdbc:sqlite:C:\\DokiDB\\database.db</property>
<property name="connection.username">progdm</property>
<property name="connection.password">release</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="connection.pool_size">1</property>
<property name="show_sql">true</property>
<property name="current_session_context_class">thread</property>
</session-factory>
</hibernate-configuration>
mapped class
#Entity
#Table(name="theme")
public class mapTheme {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="theme_id")
private int theme_id;
#Column(name="theme_name")
private String theme_name;
public int getTheme_id() {
return theme_id;
}
public void setTheme_id(int theme_id) {
this.theme_id = theme_id;
}
public String getTheme_name() {
return theme_name;
}
public void setTheme_name(String theme_name) {
this.theme_name = theme_name;
}
public mapTheme(String theme_name) {
super();
this.theme_name = theme_name;
}
public mapTheme(){
}
}
what can I do?
The table name used in the query is not the name of the table in database, it should be the name of the entity class.
In this case you must use
Query query = session.createQuery("from mapTheme");
instead of :
Query query = session.createQuery("from theme")
I'm trying to add a custom save event listener for hibernate. My goal is to have hibernate set the last update and created timestamp values on certain entities. I have read from other posts that JPA annotations will do it but if you are using a Hibernate Session then you need to extend DefaultSaveOrUpdateEventListener. I did this and it hasn't worked. Every example I see is using a hibernate config file. My sessionFactory is configured with Spring.
<bean id="mySessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource">
<ref bean="myDataSource"/>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
<property name="packagesToScan">
<list>
<value>com.mypackages</value>
</list>
</property>
<property name="eventListeners">
<map>
<entry key="save-update">
<ref local="saveEventListener" />
</entry>
</map>
</property>
</bean>
<bean id="saveEventListener" class="com.mypackage.event.SaveOrUpdateDateListener" />
I set a breakpoint and it doesn't go through the listener. My last updated and created fields are not being set in the database.
I have worked with the similar issue and finally resolved.
I have a base pojo with properties for Auditing , Every entity extends this base pojo. on call to save or update, the methods of Event Listeners get triggered where I update the entity with auditing information.
#Component
public class EntitySaveListener implements PersistEventListener, MergeEventListener,
PreInsertEventListener {
private static final long serialVersionUID = 1L;
static final Logger logger = LoggerFactory
.getLogger(EntitySaveListener.class);
#Autowired
private LocalEntityManagerFactoryBean entityManagerFactory;
public EntitySaveListener() {
logger.info("EntitySaveListener created");
}
public void onPersist(PersistEvent event) throws HibernateException {
if (SecurityContextHolder.getContext() != null
&& SecurityContextHolder.getContext().getAuthentication() != null) {
Object principal = SecurityContextHolder.getContext()
.getAuthentication().getPrincipal();
if (principal != null && principal instanceof V2VUserDetails) {
User user = ((V2VUserDetails) principal).getUser();
if (event.getObject() instanceof ModificationTracker &&
user != null) {
ModificationTracker entity = (ModificationTracker) event.getObject();
entity.setCreatedDate(new Date());
entity.setCreatedBy(user);
entity.setLastUpdated(new Date());
entity.setLastUpdatedBy(user);
}
}
}
}
#SuppressWarnings("rawtypes")
#Override
public void onPersist(PersistEvent event, Map arg1)
throws HibernateException {
// TODO Auto-generated method stub
}
#Override
public void onMerge(MergeEvent event) throws HibernateException {
if (SecurityContextHolder.getContext() != null
&& SecurityContextHolder.getContext().getAuthentication() != null) {
Object principal = SecurityContextHolder.getContext()
.getAuthentication().getPrincipal();
if (principal != null && principal instanceof V2VUserDetails) {
User user = ((V2VUserDetails) principal).getUser();
if (event.getEntity() instanceof ModificationTracker
&& user != null) {
ModificationTracker entity = (ModificationTracker) event
.getEntity();
entity.setLastUpdated(new Date());
entity.setLastUpdatedBy(user);
}
}
}
}
#SuppressWarnings("rawtypes")
#Override
public void onMerge(MergeEvent arg0, Map arg1) throws HibernateException {
// TODO Auto-generated method stub
}
#Override
public boolean onPreInsert(PreInsertEvent arg0) {
// TODO Auto-generated method stub
return false;
}
}
I am getting this below exception when I am trying to execute a Stored procedure using HIbernate from DaoImpl Class.
I am not sure of what is wrong ..I tried all the ways to fix it but did not resolve the issue.
Could anyone please help me ,figure out whats wrong with the code or the mapping file.
The more I am trying to fix ,something the more exceptions I am getting.. I am connectuing to Oracle 9i DB.
I am struggling on this from really 2 weeks ending up no where.. can anyone please help me fix this issue.
Mapping file:
<hibernate-mapping>
<sql-query name="proc_drsrr_sel_ValDDSummaryBal">
<!--CALL proc_drsrr_sel_ValDDSummaryBal(:param1)]]>-->
{ call DEFAULT_SCHEMA.proc_name(?,:param1) }
Main-Class:
public static void main(String[] args) {
String procName = "proc_name";// args[0];
String params = "param1:500089" ;
DAO Implementation:
#SuppressWarnings("unchecked")
public void callProc(String procName, Map paramMap) throws SQLException {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtils.getSessionFactory().getCurrentSession();
tx = session.beginTransaction();
String dbURL = session.connection().getMetaData().getURL().toString();
System.out.println("Conenction DB URL "+ dbURL );
tx.setTimeout(5);
String[] keys = new String[paramMap.size()];
keys = (String[]) paramMap.keySet().toArray(keys);
Query query = session.getNamedQuery(procName)
.setParameter("param1", "5501010");
}
List result = query.list();
System.out.println(query.getQueryString());
for (int i = 0; i < result.size(); i++) {
// logging the information.
log.info(i);
}
tx.commit();
} catch (RuntimeException exception) {
exception.printStackTrace();
try {
tx.rollback();
} catch (RuntimeException rbe) {
log.error("Couldn’t roll back transaction", rbe);
rbe.printStackTrace();
}
throw exception;
} finally{
if(session !=null){
session.flush();
session.close();
}
cfg.xml
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.url">jdbc:oracle:thin:#ldap://hdsoid.ute.ovi.com:3060/UT1DEV,cn=OracleContext,dc=ute,dc=ovi,dc=com</property>
<property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="hibernate.connection.username">nameapp</property>
<property name="connection.password">nameapp</property>
<property name="connection.pool_size">1</property>
<property name="hibernate.dialect">org.hibernate.dialect.OracleDialect</property>
<!-- <property name="connection.release_mode">after_statement</property> -->
<property name="default_schema">DEFAULT_SCHEMA</property>
<property name="current_session_context_class">thread</property>
<property name="hibernate.show_sql">true</property>
<!-- mapping files -->
<mapping resource="com/ovi/domain/hibernate.hbm.xml" />
</session-factory>
</hibernate-configuration>
You are missing to set the ? parameter which is a so called positional parameter. In contrast to named parameters like :foo
When you have some SQL you must also ensure not to have any Question Marks inside comments! That's what I just ran into. Same holds for : in comments, especially if they are followed by a space.