Issue with binary field and named query - nHibernate - nhibernate

I am using nHibernate to try and log a user in using a named query but their password is hashed and so stored as a binary field in the MS SQL DB. However I can't get the login code to work. It throws an error:
using (var session = sessionFactory.OpenSession())
{
user = (CreamUser)session.GetNamedQuery("loginuser")
.SetString("UserName", userName)
.SetBinary("Password", hashedPassword).UniqueResult();
}
<sql-query name="loginuser">
<query-param name="UserName" type="string" />
<query-param name="Password" type="binary" />
<return alias="User" class="components.User"/>
<![CDATA[
SELECT * FROM users
WHERE username=:UserName AND
password=:Password
]]>
</sql-query>
I have tried everything I can think of but can't get this to work.

Ok so I worked it out. I turns out it was to do with the fact the the query I was executing was missing some fields that matched with the type (user) that I was returning.
this was the error in case anyone else comes across this issue:
could not execute query\r\n[ SELECT * FROM users \n WHERE username=#p0 AND \n
password=#p1 ]\r\n Name:UserName - Value:admin Name:Password - Value:System.Byte[]\r\n[SQL:
SELECT * FROM users \n WHERE username=#p0 AND \n password=#p1]
thanks for making me look deeper ExpectoPatronum

Related

How to use the result of a query as liquibase defaultValueComputed?

Working with liquibase I've found that it's possible to define properties, and use them as defaultValue for columns.
Everything is ok if you use pre-made functions, but how to do when you have some custom SQL that produces some data, to be used in the same manner?
I tried to do something like this:
<property name="myFunc" value="SELECT CURRENT_DATE + time '08:00:00' + (random() * interval '3 hours')::time" dbms="postgresql"/>
...
<column name="selected_pickup_date" type="datetime" defaultValueComputed="${myFunc}" remarks="Selected from customer during order creation">
<constraints nullable="false"/>
</column>
But it didn't work! The error code showed that liquibase was just placing my SQL string as the column's default value.
SQL wasn't parsed as I expected.
How to proceed to get the query result used as default value?
After many attempts, I understood that Liquibase doesn't parse SQL in properties, probably it only executes functions and places their result in the property value, and the placeholder ${xxx} is replaced with the function's output.
Once a new row is added to the table, and the column with defaultValue is empty, the property value is read and used in place of NULL.
I tried many solutions and luckily the last one worked:
Take the SQL and create a new function in a sql file, in my case it was simple:
DROP FUNCTION IF EXISTS fixed_date_rand_time;
CREATE FUNCTION fixed_date_rand_time() RETURNS timestamp
AS $$ SELECT CURRENT_DATE + time '08:00:00' + (random() * interval '3 hours')::time $$
LANGUAGE SQL;
Import the sql before other changelogs
<include relativeToChangelogFile="true" file="func.sql" />
Now..you can create the property! This time calling the function instead of the SQL string
<property name="myFunc" value="fixed_date_rand_time()" dbms="postgresql"/>
...
<changeSet id="20201026174848-1" author="jhipster">
<createTable tableName="my_table">
<column name="selected_pickup_date" type="datetime" defaultValueComputed="${myFunc}" remarks="Selected from customer during order creation">
<constraints nullable="true"/>
</column>
</createTable>
</changeSet>
...
Et VoilĂ ! It works now!
The very-nice thing is that properties can be used with context too, allowing you to bypass the new function when outside of local test environment:
<property name="myFunc" value="fixed_date_rand_time()" dbms="postgresql" context="test"/>
<property name="myFunc" value="NULL" dbms="postgresql" context="!test"/>
Not perfect, it works only with nullable columns, but there must a solution.
Finally the database is loaded with correct values automatically, taking away the hassle of updating dates everyday, to have everything work as expected.
I hope that this solution can help somebody, who maybe has the will to refine it a bit :-)
My Liquibase version is 3.10, I cannot update to the latest due to other dependencies... maybe the problem has been addressed there.
I don't exclude that the feature has been disabled intentionally in favour of the pro version.
Have a nice day

Named sql-query: could not execute native bulk manipulation query (but script works fine when executed directly in DB)

i'm trying to execute a SQL native script using hibernate sql-query. The script is the following:
<sql-query name="setAllColors" >
UPDATE chair
SET COLOR = 'Grey' WHERE NAME='AustrianWinter';
UPDATE chair
SET COLOR = 'Brown' WHERE NAME='ItalianSummer';
</sql-query>
If i execute this same query in Mysql (it's the DB i'm using) all works fine. If i try to execute it via code, recalling the xml where this query is stored, i get:
could not execute native bulk manipulation query
THE STRANGE FACT is that if i try to execute just the first update, without the second one, all works fine.
Any idea on how to avoid this error?
In db works fine because MySQL executes them sequentially.
In hibernate you can't do that. There you have to define each update statement in separate sql-query.
However you can try smth like:
UPDATE chair SET color = CASE WHEN NAME='AustrianWinter' THEN 'Grey' ELSE 'Brown' END WHERE NAME IN ('AustrianWinter', 'Brown')
if you want simple case as you gave, you can use answer from #Adrian.
BUT - #Adrian 'In hibernate you can't do that.' -- it's not true.
it's not hibernate restriction , it's restriction jdbc connection. By default it's not allowed to have multiple queries. BUT you can set setting database connection property to allow multiple queries, separated by a semi-colon by default.This is additional connection property.
allowMultiQueries=true
jdbc:mysql://localhost:3306/hibernate_db?allowMultiQueries=true
with whis option you can execute :
<sql-query name="setAllColors" >
UPDATE chair
SET COLOR = 'Grey' WHERE NAME='AustrianWinter';
UPDATE chair
SET COLOR = 'Brown' WHERE NAME='ItalianSummer';
</sql-query>
UPDATE 2:
as you use DriverManagerDataSource , allowMultiQueries it's not a part of connection, you should put it as Properties.
from AbstractDriverBasedDataSource
/**
* Specify arbitrary connection properties as key/value pairs,
* to be passed to the Driver.
* <p>Can also contain "user" and "password" properties. However,
* any "username" and "password" bean properties specified on this
* DataSource will override the corresponding connection properties.
* #see java.sql.Driver#connect(String, java.util.Properties)
*/
public void setConnectionProperties(Properties connectionProperties) {
this.connectionProperties = connectionProperties;
}
so ,configuration should be:
<bean id="dataSourceBean" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost/chairDB"/>
<property name="username" value="root"/>
<property name="password" value="pass123"/>
<property name="connectionProperties">
<props>
<prop key="allowMultiQueries">true</pro>
</props>
</property>
</bean>

Spring data Jpa findTop and findFirst generating error Incorrect syntax near '#P0'

I am using spring data JPA 1.8.2 and trying to get top result. I am using the following method
LearningSession findTopBySourceAndExternalLmsSessionIdAndCourseCodeAndLearnerEnrollmentEnrollmentStatusOrderByIdAsc(String source, String externalLmsSessionId, String courseCode, String enrollmentStatus);
I tried also by removing OrderBy
LearningSession findTopBySourceAndExternalLmsSessionIdAndCourseCodeAndLearnerEnrollmentEnrollmentStatus(String source, String externalLmsSessionId, String courseCode, String enrollmentStatus);
In both cases hibernate is generating the following query. Just use * for every thing. For order by in the end order by learningse0_.id asc
select TOP ? learningse0_.*
from LearningSession learningse0_
left outer join LearnerEnrollment learnerenr1_ on learningse0_.ENROLLMENT_ID=learnerenr1_.id
where learningse0_.source=?
and learningse0_.externalLmsSessionId=?
and learningse0_.courseCode=?
and learnerenr1_.enrollmentStatus=?
Query is right But I am getting the following exception
Hibernate: select TOP ? learningse0_.id as id1_47_, learningse0_.brandName as brandNam2_47_, learningse0_.courseApprovalId as courseAp3_47_, learningse0_.courseCode as courseCo4_47_, learningse0_.endTime as endTime5_47_, learningse0_.externalLmsSessionId as external6_47_, learningse0_.externalLmsUrl as external7_47_, learningse0_.isCourseMessageDisplay as isCourse8_47_, learningse0_.LANGUAGE_ID as LANGUAG15_47_, learningse0_.LEARNER_ID as LEARNER16_47_, learningse0_.ENROLLMENT_ID as ENROLLM17_47_, learningse0_.learningSessionGuid as learning9_47_, learningse0_.lmsProvider as lmsProv10_47_, learningse0_.redirectUrl as redirec11_47_, learningse0_.source as source12_47_, learningse0_.startTime as startTi13_47_, learningse0_.uniqueUserGuid as uniqueU14_47_ from LearningSession learningse0_ left outer join LearnerEnrollment learnerenr1_ on learningse0_.ENROLLMENT_ID=learnerenr1_.id where learningse0_.source=? and learningse0_.externalLmsSessionId=? and learningse0_.courseCode=? and learnerenr1_.enrollmentStatus=? order by learningse0_.id asc
13:53:47.686 [main] DEBUG org.hibernate.engine.jdbc.spi.SqlExceptionHelper - could not extract ResultSet [n/a]
com.microsoft.sqlserver.jdbc.SQLServerException: Incorrect syntax near '#P0'
com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:216) ~[sqljdbc4-4.0.jar:?]
What I am doing wrong ? I tried First, Top1, First1 but result is error. Please help.
Thanks
Not sure if this will work for you, but I ran into the same error and after a lot of digging I figured out that I was using SqlServerDialect in my JpaVendorAdapter, and when I changed it to be more specifically for SqlServer2012 (SqlServerDialect2012) the error went away:
<bean id="jpaVendorAdapter"
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="SQL_SERVER" />
<property name="databasePlatform" value="org.hibernate.dialect.SQLServer2012Dialect" />
<property name="showSql" value="true" />
</bean>
I had the same issue with Hibernate 5 + Spring Data.
Changing the Dialect to SQLServer2012Dialect worked for me.
public class SQLServerNativeDialect extends SQLServer2012Dialect
For reference::
https://hibernate.atlassian.net/browse/HHH-10032
Thanks,

Nhibernate Named SQL Query

Can any body tell me what is wrong with below query Named SQL Query using NHibernate.
As I am getting error - "Error in Named Query : GetSecondReviewIncomeStatements ":
<sql-query name="GetSecondReviewIncomeStatements" read-only="true">
<![CDATA[
SELECT I.TotalNetSales,I.CostOfGoodsSold,I.GrossProfit
FROM IncomeStatement as incomeStatement
INNER JOIN FETCH CompSearchResultItem as resultItem
ON incomeStatement.Comparable.ID = resultItem.Comparable.ID
AND resultItem.CompSearch.ID = :compSearchID
]]>-->
</sql-query>-->
I have searched a lot on the web, some say instead on On put Where.
I also tried NamedQuery only but everytime I get the same error.
Please check the Format for Named Query in .hbm.xml file.
in hbm.xml
<sql-query name="ShowProducts">
<return alias="Product" class="Product" />
exec ShowProducts
</sql-query>
<sql-query name="DeleteProducts">
<query-param name="Id" type="int"></query-param>
exec DeleteProducts #ID=:Id
</sql-query>
in Code Usage
IQuery query = (IQuery)session.GetNamedQuery("ShowProducts");
var listProducts = query.List<Product>();
GridView1.DataSource = listProducts;
GridView1.DataBind();
Does your SQL runs if you put it 'as-is' in your rdbms sql executor?
Besides the strange --> after the enclosing CDATA element, I've noticed that you haven't declared the I alias in your query.
I mean, these columns preceded with I...
SELECT I.TotalNetSales,I.CostOfGoodsSold,I.GrossProfit
...are coming from where?

NHibernate query against the key field of a dictionary (map)

I have an object model where a Calendar object has an IDictionary<MembershipUser, Perms> called UserPermissions, where MembershipUser is an object, and Perms is a simple enumeration. This is in the mapping file for Calendar as
<map name="UserPermissions" table="CalendarUserPermissions" lazy="true" cascade="all">
<key column="CalendarID"/>
<index-many-to-many class="MembershipUser" column="UserGUID" />
<element column="Permissions" type="CalendarPermission" not-null="true" />
</map>
Now I want to execute a query to find all calendars for which a given user has some permission defined. The permission is irrelevant; I just want a list of the calendars where a given user is present as a key in the UserPermissions dictionary. I have the username property, not a MembershipUser object. How do I build that using QBC (or HQL)? Here's what I've tried:
ISession session = SessionManager.CurrentSession;
ICriteria calCrit = session.CreateCriteria<Calendar>();
ICriteria userCrit = calCrit.CreateCriteria("UserPermissions.indices");
userCrit.Add(Expression.Eq("Username", username));
return calCrit.List<Calendar>();
This constructed invalid SQL -- the WHERE clause contained WHERE membership1_.Username = #p0 as expected, but the FROM clause didn't include the MemberhipUsers table.
Also, I really had to struggle to learn about the .indices notation. I found it by digging through the NHibernate source code, and saw that there's also .elements and some other dotted notations. Where's a reference to the allowed syntax of an association path? I feel like what's above is very close, and just missing something simple.
Just trying to do this myself and it looks like this can be done with HQL but not the Criteria API.
https://nhibernate.jira.com/browse/NH-1795
To do it in HQL:
http://ayende.com/Blog/archive/2009/06/03/nhibernate-mapping-ndash-ltmapgt.aspx
Specifically look for Ayende's comment:
It is something like:
select 1 from Profile p join p.Entries e
where index(e) = 'HasCats' and e = 'true'