Migration Hibernate 1 to 3.3 - exception

We're migrating a project from hibernate 1 to hibernate 3.3.1, and we're a problem with some Querys:
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Long
The code that we have now, used to work with hibernate 1 but get the exception above with hibernate 3.3.1, the piece of code is:
if(args!=null){
for(int i=0; i<args.length; i++)
queryObject.setParameter(i, args[i]);
}
args is a Object[]
and the Query is, for example:
select obj.oid,obj.codTipoTrafico,obj.nomEmpresaOper,obj.codOrigen,obj.codFuente,obj.codIdnFuente,to_char(obj.fecFuente,'DD/MM/YYYY') from OperacionComercial obj where obj.indTpoOper = ? and obj.oidEmpresa = ? order by order by obj.oca desc
Hibernate cannot autoconvert from String to Long no more?
Thanks in advance

Changing the hibernate configuration property "hibernate.query.factory_class" to use the ClassicQueryTranslator for the HQL, the problem is solved...(at least for me).
<props>
<prop key="hibernate.query.factory_class">
org.hibernate.hql.classic.ClassicQueryTranslatorFactory
</prop>
</props>

Related

HQL cannot query JSON data

This is a NativeSql work fine:
session.createSQLQuery(select json_length(fav_goods) from customer where id=1).uniqueResult()
But if I change it to HQL like this follow ,it well raised a Error
session.createQuery(select json_length(favGoods) from CustomerEntity where id=1).uniqueResult()
error
Caused by: org.hibernate.QueryException: No data type for node: org.hibernate.hql.internal.ast.tree.MethodNode
\-[METHOD_CALL] MethodNode: '('
+-[METHOD_NAME] IdentNode: 'json_length' {originalText=json_length}
\-[EXPR_LIST] SqlNode: 'exprList'
\-[DOT] DotNode: 'customeren0_.fav_goods' {propertyName=favGoods,dereferenceType=PRIMITIVE,getPropertyPath=favGoods,path={synthetic-alias}.favGoods,tableAlias=customeren0_,className=cn.phyer.bishe.entity.CustomerEntity,classAlias=null}
+-[IDENT] IdentNode: '{synthetic-alias}' {originalText={synthetic-alias}}
\-[IDENT] IdentNode: 'favGoods' {originalText=favGoods}
[select json_length(favGoods) from cn.phyer.bishe.entity.CustomerEntity where id=?1]
at org.hibernate.QueryException.generateQueryException(QueryException.java:120)
at org.hibernate.QueryException.wrapWithQueryString(QueryException.java:103)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:220)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:144)
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:113)
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:73)
at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:155)
at org.hibernate.internal.AbstractSharedSessionContract.getQueryPlan(AbstractSharedSessionContract.java:600)
at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:709)
... 39 more
Caused by: org.hibernate.QueryException: No data type for node: org.hibernate.hql.internal.ast.tree.MethodNode
\-[METHOD_CALL] MethodNode: '('
+-[METHOD_NAME] IdentNode: 'json_length' {originalText=json_length}
\-[EXPR_LIST] SqlNode: 'exprList'
\-[DOT] DotNode: 'customeren0_.fav_goods' {propertyName=favGoods,dereferenceType=PRIMITIVE,getPropertyPath=favGoods,path={synthetic-alias}.favGoods,tableAlias=customeren0_,className=cn.phyer.bishe.entity.CustomerEntity,classAlias=null}
+-[IDENT] IdentNode: '{synthetic-alias}' {originalText={synthetic-alias}}
\-[IDENT] IdentNode: 'favGoods' {originalText=favGoods}
At the entity class CustomerEntity,field fav_goods is been named as favGoods
JPQL (or HQL) does not support JSON Functions.
Please find all supported functions here:
https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#hql-functions
You have to stick with SQL.
I had a similar problem and I had to use JSON_EXTRACT mysql function.
Extend the MySQL5Dialect class to register the SQL Function in Hibernate.
public class CustomMySQLDialect extends MySQL5Dialect {
public CustomMySQLDialect(){
super();
registerFunction(
"JSON_EXTRACT",
new StandardSQLFunction(
"JSON_EXTRACT",
StandardBasicTypes.STRING
)
);
}
}
Register the Custom MySQL Dialect in Hibernate cfg xml
<property name="hibernate.dialect">com.testsigma.specification.CustomMySQLDialect</property>
Use CriteriaQuery(JPQL) with SQL Function within Hibernate.
Root<EntityType> subRoot = criteriaBuilder.from(Entity.class);
subQuery.select(builder.function("JSON_EXTRACT", String.class, subRoot.get("jsonData"), builder.literal("$.\"jsonPathField\"")));
query1.where(root.get("jsonKey").in(subQuery));
Taken from https://vladmihalcea.com/hibernate-sql-function-jpql-criteria-api-query/
Working as of Hibernate 5.2.3.Final, Spring Data JPA 2.1.9.RELEASE

SnappyData JDBC driver raising SQLState=XCL14 error

SnappyData v.0-5 w/ ClientDriver JDBC driver.
I have a persistent row table in SnappyData called: sensor_data.
From the snappy> shell, this query returns thousands for rows.
snappy> select * from sensor_data where year_num = 2013 and
month_num = 1;
When run from a JDBC connection in SpringBoot, I get this error:
PreparedStatementCallback; uncategorized SQLException for SQL [select
* from sensor_data where year_num = ? and month_num = ?]; SQL state [XCL14]; error code [20000]; (SQLState=XCL14 Severity=20000) The
column position '1' is out of range. The number of columns for this
ResultSet is '0'.
Java Code is:
List<SensorData> list = jdbcTemplateBean.query("select * from sensor_data where year_num = ? and month_num = ?",
new Object[] {year, month}, new SensorDataRowMapper());
What do I need to do to fix this JDBC issue?
Trimmed Stacktrace on Spring boot:
org.springframework.jdbc.UncategorizedSQLException:
PreparedStatementCallback; uncategorized SQLException for SQL [select
* from sensor_data where year_num = ? and month_num = ?]; SQL state [XCL14]; error code [20000]; (SQLState=XCL14 Severity=20000) The
column position '1' is out of range. The number of columns for this
ResultSet is '0'.; nested exception is java.sql.SQLException:
(SQLState=XCL14 Severity=20000) The column position '1' is out of
range. The number of columns for this ResultSet is '0'. at
org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:84)
at
org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)
at
org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)
at
org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:645)
at
org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:680)
at
org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:707)
at
org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:757)
at
org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.query(NamedParameterJdbcTemplate.java:192)
at
org.kritek.scalability.repository.SensorDataRepository.findByYearAndMonth(SensorDataRepository.java:58)
...
at
org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555)
at java.lang.Thread.run(Thread.java:745) Caused by:
java.sql.SQLException: (SQLState=XCL14 Severity=20000) The column
position '1' is out of range. The number of columns for this
ResultSet is '0'.
...
Caused by: ERROR XCL14: The column position '1' is out of
range. The number of columns for this ResultSet is '0'. at
com.pivotal.gemfirexd.internal.client.am.ColumnMetaData.checkForValidColumnIndex(ColumnMetaData.java:856)
at
com.pivotal.gemfirexd.internal.client.am.ColumnMetaData.getColumnType(ColumnMetaData.java:638)
... 72 more
From the stack it looks like NamedParameterJdbcTemplate is being used but '?' placeholders are being used. For NamedParameterJdbcTemplate you need to use named parameters like here.
I will recommend using the standard '?' placeholder mechanism with JdbcTemplate like:
private JdbcTemplate jdbcTemplateBean;
public void setDataSource(DataSource dataSource) {
this.jdbcTemplateBean = new JdbcTemplate(dataSource);
}
List<SensorData> list = jdbcTemplateBean.query(
"select * from sensor_data where year_num = ? and month_num = ?",
new Object[] { year, month }, new SensorDataRowMapper());
The issue has been resolved. Here is what happened.... SnappyData routed the query to Spark because it determined it could not handle it. Spark knows nothing about JDBC PreparedStatements or bind variables and raised the error. To fix, I had to set the SnappyData JDBC property "route-query = false" in my DataSource configuration. This ensured it was not routed to Spark.

hibernate criteria putting a contains / does not contain restriction on a set of elements

Hi I'm trying to migrate my old sql based query framework to be Hibernate Criteria based, currently I'm using Hibernate version 3.2. and mysql v 5.0.54
My question is I want to write a criteria that returns all the Beans that do not have a value in a contained set of elements.
A summary of the hibernate config file for the bean is:
<hibernate-mapping package="com.mydomain.beans">
<typedef class="com.mydomain.dao.util.HibernateAgentOptionType" name="agent-option"/>
<class name="Agent" table="agent">
...
<set name="agentOptions" table="agent_options" fetch="join" lazy="true">
<key column="agt_id"/>
<element column="identifier" type="agent-option"/>
</set>
</class>
</hibernate-mapping>
The class file is something like:
public class Agent {
...
public Set<Option> getAgentOptions() {
return agentOptions;
}
public void setAgentOptions(Set<Option> _agentOptions) {
this.agentOptions = _agentOptions;
}
public enum Option {
WEB_SITE_SYNDICATE ("web-site-syndicate"),
RECEIVE_PREMIUM_ENQUIRIES ("receive-premium-enquiries"),
DO_NOT_SYNDICATE_ADS_TO_THIRD_PARTIES ("do-not-syndicate-ads-to-third-parties")
}
}
I would like to retrieve all the agents who do not have the Option "DO_NOT_SYNDICATE_ADS_TO_THIRD_PARTIES" in their agentOptions
the sql that I was using for this previously was something like:
SELECT agt.id
FROM agent agt
WHERE agt.id NOT IN (
SELECT sub_agt.id FROM agent sub_agt
JOIN agent_options AS agt_options ON agt_options.agt_id = sub_agt.id
WHERE agt_options.identifier = 'do_not_syndicate_ads_to_third_parties'
)
I've tried this:
...
Criteria crit = getHibernateSession().createCriteria(Agent.class);
crit.addRestriction(Restriction.not(Restriction.in("agentOptions", noSyndicatedAds)));
...
Which spits out bad sql
I've also tried this using aliases:
...
crit.createAlias("agentOptions", "agentOption");
crit.add(Restrictions.not(Restrictions.in("agentOption", options)));
...
Which throws an exception:
org.hibernate.MappingException: collection was not an association: Agent.agentOptions
Finally I decided to try a brute sql Criterion:
...
crit.add(Restrictions.sqlRestriction(" {alias}.id not in " +
"(select agt_sub.id " +
"from agent agt_sub " +
"join agent_options as agent_options_sub on agent_options_sub.agt_id = agt_sub.id " +
"where agent_options_sub.identifier in (?)) ",
Agent.Option.DO_NOT_SYNDICATE_ADS_TO_THIRD_PARTIES.getIdentifier(),
new org.hibernate.type.StringType()
));
...
Which worked but seems a little bit ugly.
Does anyone know if there is a way using the std Criteria API without having to resort to sql.
Any help or suggestions would be very welcome. Even if they require upgrading to a more recent version of Hibernate.
Cheers
Simon
Structure your subquery as a DetachedCriteria, and then use your nested Restrictions to achieve a NOT IN. In your case:
DetachedCriteria subquery = DetachedCriteria.forClass(Agent.class);
subquery.createAlias("agentOptions", "agentOption");
subbquery.add(Restrictions.eq("identifier", Agent.Option.DO_NOT_SYNDICATE_ADS_TO_THIRD_PARTIES.getIdentifier());
subquery.setProjection(Projections.property("agt_id")); // only return one field
crit.add(Restrictions.not(Restrictions.in("agt_id", subquery)));

The specified type member 'DateTime' is not supported in LINQ to Entities

I am using the latest development version of the connector - 6.3.3 beta to connect to a mysql database via the Entity Framework 4 in VS2010.
I have the following Linq statement which uses a TIMESTAMP column - createdDate - in the query. Here is the code:
int timeThreshold = 5;
DateTimeOffset cutoffTime = DateTime.Now.AddMinutes(-timeThreshold);
using (var context = new opusismEntities())
{
var unprocessedMessages = from m in context.messages
where m.createdDate <= cutoffTime
select m;
try
{
foreach (var message in unprocessedMessages)
{
int gfff = 5;
}
}
catch (Exception e)
{
string exceptionString = e.InnerException.ToString();
}
}
The CLR is throwing the following exception:
"MySql.Data.MySqlClient.MySqlException (0x80004005): Fatal error encountered during command execution. ---> MySql.Data.MySqlClient.MySqlException (0x80004005): Unable to serialize date/time value.\r\n at MySql.Data.Types.MySqlDateTime.MySql.Data.Types.IMySqlValue.WriteValue(MySqlPacket packet, Boolean binary, Object value, Int32 length)\r\n at MySql.Data.MySqlClient.MySqlParameter.Serialize(MySqlPacket packet, Boolean binary, MySqlConnectionStringBuilder settings)\r\n at MySql.Data.MySqlClient.Statement.SerializeParameter(MySqlParameterCollection parameters, MySqlPacket packet, String parmName)\r\n at MySql.Data.MySqlClient.Statement.InternalBindParameters(String sql, MySqlParameterCollection parameters, MySqlPacket packet)\r\n at MySql.Data.MySqlClient.Statement.BindParameters()\r\n at MySql.Data.MySqlClient.Statement.Execute()\r\n at MySql.Data.MySqlClient.PreparableStatement.Execute()\r\n at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader(CommandBehavior behavior)\r\n at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader(CommandBehavior behavior)\r\n at MySql.Data.Entity.EFMySqlCommand.ExecuteDbDataReader(CommandBehavior behavior)\r\n at System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior)\r\n at System.Data.EntityClient.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand, CommandBehavior behavior)"
I’ve attempted to follow the advice from the following link:
http://bugs.mysql.com/bug.php?id=52550
by declaring a DateTime instead of DateTimeOffset:
DateTime cutoffTime = DateTime.Now.AddMinutes(-timeThreshold);
...
var unprocessedMessages = from m in context.messages
where m.createdDate.DateTime <= cutoffTime
select m;
and use the format .createdDate.DateTime, but Entity Framework doesn’t like it and returns back an exception:
The specified type member 'DateTime' is not supported in LINQ to Entities
This was reported as a bug in previous versions of NET/Connector.
Hopefully the GA version 6.3.4 will fix this issue, but it still persists in 6.3.3 beta.
Well this is LINQ to Entities issue..it does not allow you to use properties/methods like that in a query...not only for DateTime but for others too.
Get the value in another variable and use that variable in the query like
DateTime dt=createdDate.DateTime;
Or just remove DateTime...because it's value is the same...that should get rid of exception.But I am not sure what you are trying achieve though...

JPA native query for LONGTEXT field in a MySQL view results in error

I have the following JPA SqlResultSetMapping:
#SqlResultSetMappings({
#SqlResultSetMapping(name="GroupParticipantDTO",
columns={
#ColumnResult(name="gpId"),
#ColumnResult(name="gpRole"),
// #ColumnResult(name="gpRemarks")
}
)
Which is used like this:
StringBuilder sbQuery = new StringBuilder("Select ");
sbQuery.append(" gpId, ");
sbQuery.append(" gpRole, ");
// sbQuery.append(" gpRemarks ");
sbQuery.append(" FROM v_group_participants_with_details ");
Query query = em.createNativeQuery(sbQuery.toString(), "GroupParticipantDTO");
The view is like this:
DROP VIEW IF EXISTS `v_group_participants_with_details`;
CREATE VIEW `v_group_participants_with_details`
AS
SELECT
gp.id AS gpId,
gp.role AS gpRole,
gp.remarks AS gpRemarks
FROM GroupParticipation gp
;
The GroupParticipation table has the remarks column defined as LONGTEXT (I'm using Mysql 5.x)
Now for the problem:
When the remarks field is commented out from the query everything works perfectly, but if I try to include the remarks field in the query, I get the following error:
javax.persistence.PersistenceException: org.hibernate.MappingException:
No Dialect mapping for JDBC type: -1
at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException
(AbstractEntityManagerImpl.java:614)
at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:76)
What gives? How can I get a LONGTEXT column from a native query?
This problem is reported in HHH-1483 and HHH-3892. In short, Hibernate does not know, how to map a LONGVARCHAR column returned by a native query.
This problem is fixed in Hibernate 3.5.0+. For previous versions, a workaround would be to extend the MysqlDialect to register the correct Hibernate Type for a LONGVARCHAR:
import java.sql.Types;
import org.hibernate.Hibernate;
public class MyMySQL5Dialect extends org.hibernate.dialect.MySQL5Dialect {
public MyMySQL5Dialect() {
super();
// register additional hibernate types for default use in scalar sqlquery type auto detection
registerHibernateType(Types.LONGVARCHAR, Hibernate.TEXT.getName());
}
}