I have very simple named query on JPA (toplink ):
UPDATE Server s SET s.isECM = 0
I don't carry about cache or validity of already preloaded entities. But database connection is performed from restricted account (only INSERT/UPDATE/DELETE). It is appeared that toplink on this query executes (and failed since TL_Server is not exists) very strange SQL:
INSERT INTO TL_Server (elementId, IsECM)
SELECT t0.ElementId, ?
FROM Element t0, Server t1
WHERE ((t1.elementId = t0.ElementId) AND (t0.elementType = ?))
bind => [0, Server]
What is this? How the simple UPDATE appears an INSERT? Why toplink queries TL_?
The TL_Server is a temp table. Because the UpdateAll query is determined to be complex the temp table must be used. I assume it is determined to be complex because the class has multiple tables, so they must be joined, which cannot be done on a simple update.
If you class just had a single table, then just a simple update would be done.
If this is failing, then it is an issue with your database platform's temp table support. Ensure you are setting you "toplink.target-database" correctly. What database are you using?
You seem to be using a very old version of TopLink Essentials? The UpdateAll support has considerably improved in the latest EclipseLink versions, you may consider upgrading.
If you cannot get it to work using TopLink Essentials, you could always just use a native SQL query instead of JPQL.
Related
I have a application which uses Firebird (Version 2.5) database. I wanted to trigger one of the table entry to another database table which is in SQL Server 2008 R2. When I commit I am getting this following error
ErrorCode: 335544569 (ErrorMessage: Dynamic SQL Error SQL error code = -104).
Code:
CREATE TRIGGER "trig_INV"
FOR "INVA"
ACTIVE
AFTER UPDATE
POSITION 100
AS
BEGIN
IF ((updating) AND ((old.cold <> new.cold))) THEN
BEGIN
INSERT INTO 192.168.17.206/1043: [RBT].[dbo].[N_Inv]([COLA], [COLB], [COLC], [COLD], [COLD], [COLE])
SELECT FIRST 1
"COLA", "COLB", "COLC", "COLD", "COLE"
FROM "INVA"
ORDER BY COLA DESC
END
I am not sure firebird trigger allow to push records to a SQL Server database. It will be great if anyone has tried such and provide some reference. Thanks in advance.
You get that error because the syntax you're using doesn't exist in Firebird. Firebird has no support to connect to other database systems than Firebird (in theory you could write a provider that allows connecting to other databases systems, but as far as I know, none exist in reality).
If you want to synchronize to a different database system, you will either need to write a UDF or UDR (the replacement of UDFs introduced in Firebird 3) to do this for you, or a custom application that provides synchronization, or use third-party software to do this (for example, SymmetricDS).
I have created the following materialized query table:
CREATE TABLE SCHEMA.TABLE AS
(SELECT * FROM SCHEMA.TABLEEXAMPLE)
DATA INITIALLY DEFERRED
REFRESH DEFERRED
MAINTAINED BY USER
DISABLE QUERY OPTIMIZATION;
When I execute a REFRESH TABLE SCHEMA.TABLE it get locked for others users to read from it.
Reading this doc from IBM https://www.ibm.com/support/knowledgecenter/en/SSEPGG_9.7.0/com.ibm.db2.luw.sql.ref.doc/doc/r0000977.html
I tried to execute this statement:
REFRESH TABLE SCHEMA.TABLE ALLOW READ ACCESS
But I get the following error: SQL State: 42601 Unexpected keyword ALLOW
What I'm missing on statement? Is there other way to allow read access to materialized query table while it is beign updated?
MQTs on Db2 for IBM i lag behind the functionality available in Db2 for LUW.
I've never bother with them, instead an encoded vector index (EVI) with computed columns meets every need I've every considered. (Note that Db2 LUW doesn't have EVIs)
Per Mao's comment, you might try deleting an recreating the MQT with the following:
CREATE TABLE SCHEMA.TABLE AS
(SELECT * FROM SCHEMA.TABLEEXAMPLE)
DATA INITIALLY DEFERRED
REFRESH DEFERRED
MAINTAINED BY USER
DISABLE QUERY OPTIMIZATION
with NC;
But I think a refresh would still require exclusive access to the MQT.
The only options I can think of for "refreshing" an MQT while it is being used
programmatically , using either triggers on the base tables or perhaps a process that uses SQL to update a few rows at a time.
removing the DISABLE QUERY OPTIMIZATION and not accessing the MQT directly. Instead depend on the optimizer to access it when appropriate. Now you can create a version of it every few hours and the Db should start using the newer version for new queries. Once the older one is no longer being used, you delete it (or REFRESH it)
I tried to use the jooq dsl for an insert/update query.
We have a unique (MemberId, GroupId) combination in our table, and a group membership Enum.
On sending a subscription request with (MemberId, GroupId, RoleEnum)
The query should insert a new entry to the db, but if the MemberId, GroupId combination already exists - then only update the entry if the new RoleEnum is larger than the existing one.
I failed to do this using one query with the jooq Dsl, so instead I had to use two queries (get, then insert or update accordingly) but then I lose the atomicity of the operation...
Is there a way to do this with one query with the jooqDsl?
jOOQ emulates PostgreSQL 9.5's support for the ON CONFLICT clause via:
insertInto(...).values(...).onDuplicateKeyUpdate()... of the MySQL syntax. This is possible only if your table is generated with explicit primary key information on it. (https://github.com/jOOQ/jOOQ/issues/5093, since jOOQ 3.8)
mergeInto(...).key(...).values(...) of the H2 syntax. With this syntax, you can providean explicit key column list specification, so the code generator is not needed to provide constraint meta information. (https://github.com/jOOQ/jOOQ/issues/4464, since jOOQ 3.7).
Unfortunately, there is not yet any native ON CONFLICT support in jOOQ.
I have an Entity with few #Lob fields which contains some images. And when I execute following method,
entityManager.persist(myEnity);
This method produces following query which takes long time to execute as my table is large.
SELECT id, img_1, img_2 FROM my_entity WHERE (ID = :1) FOR UPDATE;
I don't want this query to execute because I want to INSERT a row only.
FYI, I have following Application Environment.
EJB 3.0
EclipseLink 2.3.0
JDK 1.6
WebLogic 10.3
Oracle 11g
Oracle JDBC drivers before Oracle 11 had a 4k LOB size limit, so the only way to write lobs is to insert and empty lob, and the select the lobs back and writing into them. This is what you are seeing.
This is configurable, it is only done if your "eclipselink.target-database" is "Oracle8i", "Oracle9i", "Oracle10g".
For Oracle 11g you should use "Oracle11", this platform will not use the locator, as it should no longer be required in Oracle 11g. You may need to be on the latest version (2.4) for this. Using "Oracle" as your target will also not use the locator.
You can also disable the locator usage in your platform with a customizer,
platform.setShouldUseLocatorForLOBWrite(false);
The default identifier generator for Postgresql in Hibernate is SequenceGenerator [1].
i.e. Hibernate will do SELECT nextval('hibernate_sequence') to generate an ID before doing an INSERT foo (id, ...) VALUES (123, ...) on session commit.
However, PostgreSql supports autoincrement id columns (see e.g. [2]), and the default generator for all other databases which support autoincrement is to use that feature [3], and to perform inserts omitting the id value and to query the database for the new id (before session commit, but within the session's transaction).
I have seen some recent discussion [4] suggesting that the former strategy is better in general, due to the insert-before-session-commit mismatch.
If SequenceGenerator is better (as per [4]), why is it not the default for databases which support it (see [3])?
If IdentityGenerator is better, why does PostgreSql explicitly choose SequenceGenerator when Postgres does support the former (as per [2])?
I tried to find the history of the decision to override the default in the Postgres dialect (see [1]), but I couldn't find the relevant commit in GitHub. I have followed the code back to the SVN repository, but the trail goes cold where the PostgreSQLDialect file is added at r11563 with an unhelpful commit message of "maven migration" [5]. I can't seem to follow the history any further back. Can anyone find the commit which added this override? Perhaps there is more info in the commit message.
Thanks in advance.
[1] https://github.com/hibernate/hibernate-orm/blob/master/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQL81Dialect.java#L267
[2] PostgreSQL Autoincrement
[3] https://github.com/hibernate/hibernate-orm/blob/master/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java#L639
[4] http://nhforge.org/blogs/nhibernate/archive/2009/03/20/nhibernate-poid-generators-revealed.aspx
[5] https://source.jboss.org/browse/Hibernate/core/trunk/core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java?focusedRev=14993&fromRev=11563&toRev=14993#r14993
Maybe because afterInsert generators are generally broken for PG in NHibernate because it uses OracleStyle out-parameter style which is not supported by npgsql-ADONET driver which returns the result as query result and not out parameter.
SQL: INSERT INTO .... returning id into nhoutparameter; :nhoutparameter = null;
using Oracle this works
command.Execute();
object id = command.Parameter["nhoutparameter"].Value;
Assert.NotNull(id);
in PG not. It should be
object id = command.ExecuteScalar();
This is just speculation since I cant find good feature / version docs on postgres but...
Maybe the postgres dialect was added before serial was implemented, stable, widely used, or the developers who implemented the dialect were aware of it. Changing the default identifier generator for a dialect would be a breaking change and those are bad.