select length of oracle long raw with sql statement - java

storing filedata via a hibernate (using postgresql or oracle 10g/11g) property mapped as
<property name="fileData" type="binary">
<column name="fileData" length="104857600" />
</property>
from a java application i need to access the length of the field from the db (i do not want to load whole the object, for performance reasons). i did not find any hibernate (hql) solution to query that information, so i decided to search for features of the different databases that were used. for postgresql i found:
select BIT_LENGTH(filedata) from table
which works perfectly (and astonishing fast). now i need something similar for the use with oracle. i already tried
select utl_raw.length(filedata) from table
and
select DBMS_LOB.GETLENGTH(filedata) from table
which both results in the error msg:
"Error: ORA-00997: illegal use of LONG datatype"
is there any possibilty to query the length of that hibernate property on an oracle db without selecting the object itself?
(hibernate creates a "long raw" field on oracle, and a "bytea" field on postgresql)
thx in advance
(addition: statement will be used in a migration-context, newly created filedata entities will get a filesize property programatically)

Well, looks like i found an answer here:
https://community.oracle.com/thread/2137593
create table temp_deleteme as select to_lob(<long raw field>) obj from <tablename>;
select dbms_lob.getlength(obj) from temp_deleteme;
after creating the tempTable i can select the filedatalength from it, write it to my entities, and delete the table again. still not really good performance, but that let the db do the work and i will not have to transfer entities to my server for only calculating the needed information.

Related

How to change the way Talend formulates SQL queries in a JDBC connection?

In Talend Data Quality, I have configured a JDBC connection to an OpenEdge database and it's working fine.
I can pull the list of tables and select columns to analyse, but when executing analysis, I get this :
Table "DBGSS.SGSSGSS" cannot be found.
This is because it does not specify a schema, only the database name - DBGSS.
How can I make it specify database, schema and then the table name ? Or just the table name, its would work too.
Thanks !
You can use a tDBConnection component that give you the right to specify a schéma
Then , use it with the option of Use Existing connection
See below documentation , https://help.talend.com/r/en-US/7.3/db-generic/tdbconnection

HSQL database user lacks privilege or object not found error

I am trying to use hsqldb-2.3.4 to connect from Spring applicastion.
I created data base using the following details
Type : HSQL Database Engine Standalone
Driver: org.hsqldb.jdbcDriver
URL: jdbc:hsqldb:file:mydb
UserName: SA
Password: SA
I created a table named ALBUM under "MYDB" schema
In spring configuration file:
<bean id="jdbcTemplate"
class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
<constructor-arg ref="dbcpDataSource" />
</bean>
<bean id="dbcpDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.hsqldb.jdbcDriver" />
<property name="url" value="jdbc:hsqldb:file:mydb" />
<property name="username" value="SA" />
<property name="password" value="SA" />
</bean>
And in my spring controller I am doing jdbcTemplate.query("SELECT * FROM MYDB.ALBUM", new AlbumRowMapper());
And It gives me exception:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [SELECT * FROM MYDB.ALBUM]; nested exception is java.sql.SQLSyntaxErrorException: user lacks privilege or object not found: ALBUM
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
If I execute same query through SQL editor of hsqldb it executes fine. Can you please help me with this.
As said by a previous response there is many possible causes. One of them is that the table isn't created because of syntax incompatibility. If specific DB vendor syntax or specific capability is used, HSQLDB will not recognize it. Then while the creation code is executed you could see that the table is not created for this syntax reason. For exemple if the entity is annoted with #Column(columnDefinition = "TEXT") the creation of the table will fail.
There is a work around which tell to HSQLDB to be in a compatible mode
for pgsl you should append your connection url with that
"spring.datasource.url=jdbc:hsqldb:mem:testdb;sql.syntax_pgs=true"
and for mysql with
"spring.datasource.url=jdbc:hsqldb:mem:testdb;sql.syntax_mys=true"
oracle
"spring.datasource.url=jdbc:hsqldb:mem:testdb;sql.syntax_ora=true"
note there is variant depending on your configuration
it could be hibernate.connection.url= or spring.datasource.url=
for those who don't use the hibernate schema creation but a SQL script you should use this kind of syntax in your script
SET DATABASE SQL SYNTAX ORA TRUE;
It will also fix issues due to vendor specific syntax in SQL request such as array_agg for posgresql
Nota bene : The the problem occurs very early when the code parse the model to create the schema and then is hidden in many lines of logs, then the unitTested code crash with a confusing and obscure exception "user lacks privilege or object not found error" which does not point the real problem at all. So make sure to read all the trace from the beginning and fix all possible issues
If you've tried all the other answers on this question, then it is most likely that you are facing a case-sensitivity issue.
HSQLDB is case-sensitive by default. If you don't specify the double quotes around the name of a schema or column or table, then it will by default convert that to uppercase. If your object has been created in uppercase, then you are in luck. If it is in lowercase, then you will have to surround your object name with double quotes.
For example:
CREATE MEMORY TABLE "t1"("product_id" INTEGER NOT NULL)
To select from this table you will have to use the following query
select "product_id" from "t1"
user lacks privilege or object not found can have multiple causes, the most obvious being you're accessing a table that does not exist. A less evident reason is that, when you run your code, the connection to a file database URL actually can create a DB. The scenario you're experiencing might be you've set up a DB using HSQL Database Manager, added tables and rows, but it's not this specific instance your Java code is using. You may want to check that you don't have multiple copies of these files: mydb.log, mydb.lck, mydb.properties, etc in your workspace. In the case your Java code did create those files, the location depends on how you run your program. In a Maven project run inside Netbeans for example, the files are stored alongside the pom.xml.
I had the error user lacks privilege or object not found while trying to create a table in an empty in-memory database.
I used spring.datasource.schema and the problem was that I missed a semicolon in my SQL file after the "CREATE TABLE"-Statement (which was followed by "CREATE INDEX").
I had similar issue with the error 'org.hsqldb.HsqlException: user lacks privilege or object not found: DAYS_BETWEEN' turned out DAYS_BETWEEN is not recognized by hsqldb as a function. use DATEDIFF instead.
DATEDIFF ( <datetime value expr 1>, <datetime value expr 2> )
When running a HSWLDB server. for example your java config file has:
hsql.jdbc.url = jdbc:hsqldb:hsql://localhost:9005/YOURDB;sql.enforce_strict_size=true;hsqldb.tx=mvcc
check to make sure that your set a server.dbname.#. for example my server.properties file:
server.database.0=eventsdb
server.dbname.0=eventsdb
server.port=9005
I was inserting the data in hsql db using following script
INSERT INTO Greeting (text) VALUES ("Hello World");
I was getting issue related to the Hello World object not found and HSQL database user lacks privilege or object not found error
which I changed into the below script
INSERT INTO Greeting (text) VALUES ('Hello World');
And now it is working fine.
Add these two extra properties:
spring.jpa.hibernate.naming.implicit-strategy=
org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
spring.jpa.hibernate.naming.physical-strategy=
org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
I bumped into kind of the same problem recently. We are running a grails application and someone inserted a SQL script into the BootStrap file (that's the entry point for grails). That script was supposed to be run only in the production environment, however because of bad logic it was running in test as well. So the error I got was:
User lacks privilege or object not found:
without any more clarification...
I just had to make sure the script was not run in the test environment and it fixed the problem for me, though it took me 3 hours to figure it out. I know it is very, very specific issue but still if I can save someone a couple of hours of code digging that would be great.
I was having the same mistake. In my case I was forgetting to put the apas in the strings.
I was doing String test = "inputTest";
The correct one is String test = "'inputTest'";
The error was occurring when I was trying to put something in the database
connection.createStatement.execute("INSERT INTO tableTest values(" + test +")";
In my case, just put the quotation marks ' to correct the error.
In my case the error occured because i did NOT put the TABLE_NAME into double quotes "TABLE_NAME" and had the oracle schema prefix.
Not working:
SELECT * FROM FOOSCHEMA.BAR_TABLE
Working:
SELECT * FROM "BAR_TABLE"
had this issue with concatenating variables in insert statement. this worked
// var1, var3, var4 are String variables
// var2 and var5 are Integer variables
result = statement.executeUpdate("INSERT INTO newTable VALUES ('"+var1+"',"+var2+",'"+var3+"','"+var4+"',"+var5 +")");
In my case the issue was caused by the absence (I'd commented it out by mistake) of the following line in persistence.xml:
<property name="hibernate.hbm2ddl.auto" value="update"/>
which prevented Hibernate from emitting the DDL to create the required schema elements...
(different Hibernate wrappers will have different mechanisms to specify properties; I'm using JPA here)
I had this error while trying to run my application without specifying the "Path" field in Intellij IDEA data source (database) properties. Everything else was configured correctly.
I was able to run scripts in IDEA database console and they executed correctly, but without giving a path to the IDEA, it was unable to identify where to connect, which caused errors.
You have to run the Database in server mode and connect.Otherwise it wont connect from external application and give error similar to user lacks privilege.
Also change the url of database in spring configuration file accordingly when running DB in server mode.
Sample command to run DB in server mode
$java -cp lib/hsqldb.jar org.hsqldb.server.Server --database.0 file:data/mydb --dbname.0 Test
Format of URL in configuration file
jdbc:hsqldb:hsql://localhost/Test
In my case, one of the columns had the name 'key' with the missing #Column(name = "key") annotation so that in the logs you could see the query that created the table but in fact it was not there. So be careful with column names
For what it's worth - I had this same problem. I had a column named 'TYPE', which I renamed to 'XTYPE' and a column named ORDER which I renamed to 'XORDER' and the problem went away.
Yet another reason could be a misspelt field name. If your actual table has an id column named albumid and you'd used album_id, then too this could occur.
As another anwer remarked, case differences in field names too need to be taken care of.
I faced the same issue and found there was more than one PersistenceUnit (ReadOnly and ReadWrite) , So the tables in HSQLDDB created using a schema from one persistence unit resulted in exception(HSQL database user lacks privilege or object not found error) being thrown when accessed from other persistence unit .It happens when tables are created from one session in JPA and accessed from another session
In my case the table MY_TABLE was in the schema SOME_SCHEMA. So calling select/insert etc. directly didn't work. To fix:
add file schema.sql to the resources folder
in this file add the line CREATE SCHEMA YOUR_SCHEMA_NAME;

How to pass SQL query as a context variable in Talend Open Studio job

I am creating a job to pull data from a database to CSV file using talend open studio. There are 100 of tables, the data types and no of columns differ in the tables, I want to pull the data from database tables with a single job and customizable SQL query. I know how to create and use context variables.
If I understood you correctly you should be using tMap's reload at each row -option and defining table names in Excel sheet or in tFixedFlowInput.
tMap settings
Whole job and results
SQL Script:
"SELECT TOP(1) Name, Code from mdm." + (String)globalMap.get("row4.table")
I used Microsoft SQL Server for example but same script works as well with MySQL.
You can simply use a context-variable which you set via the --context_param argument in a tWhicheverDatabaseInput. E.g. define a context variable "my_sql" which you can set in the commandline as
my_job.sh --context_param my_sql="select a,b,c from a_test_table"
and then use context.my_sql as the SQL in you database input component.
However, as garpitmzn already mentioned, you will need dynamic schemas to actually work with this unknown structure in Talend. This feature only exists in the enterprise version.
If the enterprise version is available to you, simply declare a single column of type "Dynamic", which you can pass through the rest of your flow.
Declare a local context say query as type string.
Prepare a context file with variable query: query=select name from employee
Excecute the query: toraclecomponent use context.query
Query is throwing some error when you have where conditions with string type.
Need to investigate more on that. Otherwise it works.

No Dialect mapping for JDBC type: -102

i have a problem. Some sql in my program could be written by the user. So I don't know which table or which columns are in this sql. Therefore i want to detect which column names are in the sql. But if a date is in the sql i get the No Dialect mapping for JDBC type: -102 error.
How could i handle that? I am using hibernate 3.6 or 4.1.3 with java. My database is an oracle database. The dialect is org.hibernate.dialect.Oracle10gDialect.
I really don't know what is in the sql.
Here is my code:
SQLQuery q=session.createSQLQuery("SELECT * FROM tbl WHERE id = 2");
q.setResultTransformer(AliasToEntityMapResultTransformer.INSTANCE);
List<Map<String,Object>> aliasToValueMapList=q.list();
for(Map<String,Object> map : aliasToValueMapList){
System.out.println(map.keySet());
break;
}
I hope anyone knows a solution for this problem.
Greetz
Your query is attempt to return a column that the JDBC ResultSetMetaData is reporting a type (-102) which Hibernate does not know how to read. You need to register the type for that column with the query using org.hibernate.SQLQuery#addScalar or you may not be able to use that transformer and actually define the entire result set mapping to your entity org.hibernate.SQLQuery#addRoot/org.hibernate.SQLQuery#addEntity. See the docs for usage
If you use session.createQuery() this will use your dialect to talk to the database using Hibernate Query Language. but if you use createSQLQuery() you have to use PL/SQL to talk to the oracle.

Simple hibernate query returning very slowly

I have the following hibernate query:
Query query = session.createQuery("from MyHibernateClass");
List<MyHibernateClass> result = query.list();// executes in 7000ms
When logging the sql being executed in MySQL I see
select
myhibernat0_.myFirstColumn as myfirstcolumn92_,
myhibernat0_.mySecondColumn as mysecondcolumn92_,
myhibernat0_.mythirdcolumn as mythirdcolumn92_,
myhibernat0_.myFourthColumn as myfourthcolumn92_
from MyHibernateClass myhibernat0_
where (1=1);
When measurering the java code in the jvm on a small dataset of 3500 rows in MyHibernateClass database table this takes about 7000ms.
If I on the otherhand uses direct jdbc as follows:
Statement statement = session.connection().createStatement();
ResultSet rs = statement.executeQuery("select * from MyHibernateClass");// 7ms
List<MyHibernateClass> result = convert(rs);// executes in 20ms
I see the same sql going into the database but now the time spend in the java code in the jvm is 7ms.
The MyHibernateClass is a simple java bean class with getters and setters, I use no special resulttransformers as can be seen in the example. I only need a read-only instance of the class, and it doesn't need to be attached to the hibernate session.
I would rather like to use the hibernate version but cannot accept the execution times.
Added information:
After adding hibernate logging I see
[2011-07-07 14:26:26,643]DEBUG [main] [logid: ] -
org.hibernate.jdbc.AbstractBatcher.logOpenResults(AbstractBatcher.java:426) -
about to open ResultSet (open ResultSets: 0, globally: 0)
followed by 3500 of the following log statements
[2011-07-07 14:26:26,649]DEBUG [main] [logid: ] -
org.hibernate.loader.Loader.getRow(Loader.java:1197) -
result row: EntityKey[com.mycom.MyHibernateClass#1]
followed by 3500 log statements like
[2011-07-07 14:27:06,789]DEBUG [main] [logid: ] -
org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:130) -
resolving associations for [com.mycom.MyHibernateClass#1]
[2011-07-07 14:27:06,792]DEBUG [main] [logid: ] -
org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:226) -
done materializing entity [com.mycom.MyHibernateClass#1]
What does this mean?
What is Hibernate doing in the first implementation, how can I find out?
Adding a constructor with all attributes of the class did the trick, now the execution times are 70ms for the hibernate query. Previously the class only had a default constructor without arguments and a constructor with the entity id argument.
Based on the new information I felt I should provide another answer. The difference looks like that you have a one-to-many association specified for a List or Set property in your bean.
You are probably specifying that lazy=false which will turn off lazy loading. With lazy loading turned off it will fetch every associated record for every MyHibernateClass entity and this is why it is taking so long to execute.
Try setting lazy=true and this will perform much faster and then only retrieve the associated entities when explicitly requesting them from the entity.
If you utilize Log4j in your application you can set a variety of different logging options specific to Hibernate to get a better picture of what is going on behind the scenes in Hibernate.
http://docs.jboss.org/hibernate/core/3.3/reference/en/html/session-configuration.html#configuration-logging
My guess is that this is the typical initial load time that occurs when first calling an HQL query in an application. Subsequent HQL queries should be noticeably and considerably faster after this first one.
I know this thread is old, but to update I ran into the same problem but with SQL Server and it turns out to be that SQL being printed by Hibernate and SQL Sent using the driver is different. Using MSSQL Driver by default sends the queries as stored procedures as RPC calls it's because the driver tries to optimize the query plan for MSSQL Standards , so it sends the queries something like
Hibernate Query:
select c.col1,c.col2 from customer c where c.name like #param1 and c.country like #param2
Actual Driver Sent Query:
#param1=somevalue, #param2=somevalue
declar sp ....
select c.col1,c.col2 from customer c where c.name like #param1 and c.country like #param2
go
Note: This Query I got through SQL Profiler Tool directly listening on DB
It turns out to be that sp_exec optimizations on the MSSQL tend to produce good Query plans that's get cached, but this would result in 'parameter sniffing' to know more about this problem read here...
So to overcome this I had following options:
Change my HQL to native Queries and add OPTION RECOMPILE FOR SOME PARAM
Use Direct query values instead of prepared statements so there will be no translation for param values and queries will not be modified as Stored Procedures by the Driver
Change the driver settings to not send the stored procedures (this is still bad because now the query plans in MSSQL server will be specific to this query, this is same as Option:2 but outside the code)
I didn't want to use OPTION 1 & 2 since that eliminates the whole purpose of using ORM Frameworks and I end up using OPTION 3 for now
So I changed the JDBC URL to send option prepareStatement=false
After setting this I had one more problem the query being sent like
Select * from customer c where c.name like **N**'somename' and c.country=**N**'somevalue'
Here there is a prefix before the values which states that to convert the encoding scheme , so I disable the JDBC url to sendUnicode = false
This all I did in JTDS driver options.. As far as I am concerned now the application is up and running fast. I have also introduced second level caches to cache it for some time..
Hope this helps for someone, if you have any good suggestion please let me know.
I had an incident where my application was always using every row in the result set of a query. I found a 40-fold increase in speed by setting my fetch size using the setFetchSize method below. (The performance improvement includes the addition of the count query.)
Long count = getStoreCount(customerId);
Query query = session.getNamedQuery("hqlGetStoresByCustomerId")
.setString("i_customerid",customerId)
.setFetchSize(count.intValue());
Be careful while doing this; my data set had about 100 rows, and it was scoped to a the life of a web request. If you have larger data sets, you will be eating Java Heap for the duration of the existence of that data, prior to returning it to the Java Heap.
I know this is an old question but here is what fixed it for me...
In your hibernate.cfg.xml make sure you have the correct !DOCTYPE... it should be as follows:
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
Anyone else who is facing a similar issue with SQL Server can use sendStringParametersAsUnicode=false in the JDBC Query String as shown in this answer:
JPA (Hibernate) Native Query for Prepared Statement SLOW
If you're not using Unicode for your prepared statement parameters and want to utilize the index on the varchar field which you're using as a parameter for the prepared statement, this can help.
It took me 10 seconds to execute a simple select all query before I found out that DOCTYPE tag is written wrongly in hibernate.cfg.xml and *mapping object*.hbm.class
Make sure that hibernate.cfg.xml start with
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
And mapping xml.class with
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
Now it took me 1-2 seconds to execute any queries.

Categories

Resources