I have a query fetching products with some relations, but when adding "orderBy('updated_at', 'desc'), The relation with product images becomes an empty array.
I start with:
$products = \App\Product::where('id', '>', 0)
->with('designer')
->whereIn('id', [$someIds]);
Then I continue adding some relations with "whereHas" queries (if I would remove those, the problem is still exists)
Lastly, if I do:
return $products
->with('gallery.items')
->orderBy('updated_at', 'desc')->paginate($args['count']);
the gallery.items array becomes empty. It works fine if I do 'asc' instead of 'desc'. I also tried the orderByDesc method , but it's the same thing.
If I change the order, doing orderBy before adding "with" relations, it also returns empty array for the gallery images:
return $products->orderBy('updated_at', 'desc')
->with('gallery.items')
->paginate($args['count']);
Edit:
I can make a simpler query to narrow down the problem:
return $products = \App\Product::take(30)
->orderBy('updated_at', 'desc')
->with('gallery.items')
->get();
^^ This also gives empty gallery items. If I remove ->orderBy('updated_at', 'desc'), the gallery items appear as they should. Also 'asc' works (that's the default sorting).
update:
here is the above ^^ query, logged with \DB::enableQueryLog():
{
"query": "select * from `products`
order by `updated_at` desc limit 30",
"bindings": [],
"time": 26.46
},
{
"query": "select * from `galleries` where `galleries`.`id`
in (?, ?, ?, ?, ?, ?,?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
"bindings": [
3970,3971,3973,3974,3975,3976,3977,3978,3979,3980,3981,3982,3983,3984,
3985,3986,3987,3988,3989,3990,3991,3992,3993,3994,3995,3996,3997,3998,
3999,4000],
"time": 3.64
},
{
"query": "select `uploads`.*,
`gallery_items`.`gallery_id` as `pivot_gallery_id`,
`gallery_items`.`upload_id` as `pivot_upload_id`,
`gallery_items`.`order` as `pivot_order`
from `uploads`
inner join `gallery_items` on `uploads`.`id` = `gallery_items`.`upload_id`
where `gallery_items`.`gallery_id`
in (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?)",
"bindings": [
3970,3971,3973,3974,3975,3976,3977,3978,3979,3980,3981,3982,
3983,3984,3985,3986,3987,3988,3989,3990,3991,3992,3993,3994,3995,
3996,3997,3998,3999,4000],
"time": 48.92
Edit 2:
The gallery.items relation on Gallery model is like this:
items(){
return $this->belongsToMany('\App\Upload', 'gallery_items','gallery_id','upload_id')
->withPivot('order');
}
Related
If you create the tables by Liquibase, is it possible to make the table names lower case? Or are there side effects and this is not a good recommendation?
# Done by Liquibase
spring.batch.jdbc.initialize-schema=never
I think it would be a bad idea since the upper case table names are hard coded in spring batch. For example the following is used in JdbcJobExecutionDao...
private static final String SAVE_JOB_EXECUTION = "INSERT into %PREFIX%JOB_EXECUTION(JOB_EXECUTION_ID, JOB_INSTANCE_ID, START_TIME, "
+ "END_TIME, STATUS, EXIT_CODE, EXIT_MESSAGE, VERSION, CREATE_TIME, LAST_UPDATED) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
private static final String CHECK_JOB_EXECUTION_EXISTS = "SELECT COUNT(*) FROM %PREFIX%JOB_EXECUTION WHERE JOB_EXECUTION_ID = ?";
private static final String GET_STATUS = "SELECT STATUS from %PREFIX%JOB_EXECUTION where JOB_EXECUTION_ID = ?";
I use spring boot 2 with jpa, hibernate and postgres.
In my build.gradle, I have
tasks.withType(JavaCompile) {
options.compilerArgs = ["-Xlint:unchecked", "-Xlint:deprecation", "-parameters"]
options.encoding = "UTF-8"
}
I posted some class here https://pastebin.com/WgDqZkjf
I get problem with utf8
In debug I see
select
nextval ('ignar.hibernate_sequence')
Hibernate:
select
nextval ('ignar.samples_id_seq')
Hibernate:
insert
into
ignar.samplings
(available_for_test, build_date, color_id, dimension_id, machine_id, print, product_id, reception_date, remark, special_try, test_done, to_print, delay_before_doing_test, press, quantity_received, dtype, id, year)
values
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'TraditionalSamplings', ?, ?)
Hibernate:
insert
into
ignar.samples
(created_at, updated_at, absorption_printed, aen_remarque, certificat_include, cube, durability_printed, fresh_density, fresh_weigth, gen_remarque, label, position, sample_letter, sampling_id, sampling_year, absorption, absorption_number, coloration, coloration_number, compression, compression_number, density, draw_down, draw_down_number, durability, durability_number, granulometry, granulometry_number, organic_material, organic_material_number, scaling, scaling_number, id)
values
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
2018-05-21 15:38:21.214 WARN 2973 --- [io-8080-exec-10] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 0, SQLState: 22021
2018-05-21 15:38:21.215 ERROR 2973 --- [io-8080-exec-10] o.h.engine.jdbc.spi.SqlExceptionHelper : ERROR: invalid byte sequence for encoding "UTF8": 0x00
2018-05-21 15:38:21.215 ERROR 2973 --- [io-8080-exec-10] o.h.i.ExceptionMapperStandardImpl : HHH000346: Error during managed flush [org.hibernate.exception.DataException: could not execute statement]
probably your char is causing the issue... try to convert it to String in your java file
I've created my table with the following code:
CREATE TABLE "STORES" (
"STOREGLOBALID" SERIAL NOT NULL ,
"STOREUPDATEDATETIME" TIMESTAMP NOT NULL,
"CHAINID" BIGINT ,
"CHAINNAME" VARCHAR(50) ,
"SUBCHAINID" SMALLINT ,
"SUBCHAINNAME" VARCHAR(50) ,
"STOREID" SMALLINT ,
"STORENAME" VARCHAR(50) ,
"STORETYPE" SMALLINT ,
"ADDRESS" VARCHAR(50) ,
"CITY" VARCHAR(50) ,
PRIMARY KEY ("STOREGLOBALID")
);
When I try to insert timestamp by using the following SQL for preparing statement:
INSERT INTO "STORES"
("STOREGLOBALID",
"STOREUPDATEDATETIME",
"CHAINID",
"CHAINNAME",
"SUBCHAINID",
"SUBCHAINNAME",
"STOREID",
"STORENAME",
"STORETYPE",
"ADDRESS",
"CITY")
VALUES (DEFAULT, cast(? as timestamp), ?, ?, ?, ?, ?, ?, ?, ?, ?)
And the following Java code:
ps = con.prepareStatement(sql);
ps.setLong(1, store.getChainId());
ps.setTimestamp(2, new Timestamp(1000000000)); //this value is only for test purposes, actual value gives the same error
I get the following error:
cannot cast type bigint to timestamp without time zone Position: 235
I understand that I need to provide a timestamp, but when I do it as following:
ps.setTimestamp(2, new Timestamp(1000000000), Calendar.getInstance(TimeZone.getTimeZone("UTC")));
I get the same error. What am I doing wrong? Thank you.
The first argument of your prepared statement is used in
cast(? as timestamp)
and the result is stored in STOREUPDATEDATETIME, of type TIMESTAMP. And you're passing a long (store.getChainId()) as argument. So you're trying to cast a long to a timestamp.
The second argument of your prepared statement is stored in CHAINID, of type BIGINT. And you're passing a Timestamp as argument (new Timestamp(1000000000)). So PostgreSQL tries to transform this timestamp into a bigint.
The SQL should be
INSERT INTO "STORES"
("STOREGLOBALID",
"STOREUPDATEDATETIME",
"CHAINID",
"CHAINNAME",
"SUBCHAINID",
"SUBCHAINNAME",
"STOREID",
"STORENAME",
"STORETYPE",
"ADDRESS",
"CITY")
VALUES (DEFAULT, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
And the Java should be
ps.setTimestamp(1, new Timestamp(1000000000));
ps.setLong(2, store.getChainId());
I've just started using Anorm and have stumbled across a weird behavior. When I try to do the following:
val userTableName: String = "User"
SQL("INSERT INTO {userTableName} (email, forename, surname, refreshToken) VALUES ({email}, {forename}, {surname}, {refreshToken})")
.on("userTableName" -> userTableName,
"email"->email,
"forename"->forename,
"surname"->surname,
"refreshToken"->refreshToken).executeInsert()
I the following error:
play.api.Application$$anon$1: Execution exception[[JdbcSQLException: Syntax error in SQL statement "INSERT INTO ?[*] (EMAIL, FORENAME, SURNAME, REFRESHTOKEN) VALUES (?, ?, ?, ?) "; expected "identifier"; SQL statement:
INSERT INTO ? (email, forename, surname, refreshToken) VALUES (?, ?, ?, ?) [42001-175]]]
at play.api.Application$class.handleError(Application.scala:296) ~[play_2.11-2.3.8.jar:2.3.8]
at play.api.DefaultApplication.handleError(Application.scala:402) [play_2.11-2.3.8.jar:2.3.8]
at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$14$$anonfun$apply$1.applyOrElse(PlayDefaultUpstreamHandler.scala:205) [play_2.11-2.3.8.jar:2.3.8]
at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$14$$anonfun$apply$1.applyOrElse(PlayDefaultUpstreamHandler.scala:202) [play_2.11-2.3.8.jar:2.3.8]
at scala.runtime.AbstractPartialFunction.apply(AbstractPartialFunction.scala:36) [scala-library-2.11.1.jar:na]
Caused by: org.h2.jdbc.JdbcSQLException: Syntax error in SQL statement "INSERT INTO ?[*] (EMAIL, FORENAME, SURNAME, REFRESHTOKEN) VALUES (?, ?, ?, ?) "; expected "identifier"; SQL statement:
INSERT INTO ? (email, forename, surname, refreshToken) VALUES (?, ?, ?, ?) [42001-175]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:332) ~[h2-1.3.175.jar:1.3.175]
at org.h2.message.DbException.getSyntaxError(DbException.java:197) ~[h2-1.3.175.jar:1.3.175]
at org.h2.command.Parser.readIdentifierWithSchema(Parser.java:2926) ~[h2-1.3.175.jar:1.3.175]
at org.h2.command.Parser.readTableOrView(Parser.java:5049) ~[h2-1.3.175.jar:1.3.175]
at org.h2.command.Parser.parseInsert(Parser.java:995) ~[h2-1.3.175.jar:1.3.175]
If I hardcode the table name
SQL("INSERT INTO User (email, forename, surname, refreshToken) VALUES ({email}, {forename}, {surname}, {refreshToken})")
.on("email"->email,
"forename"->forename,
"surname"->surname,
"refreshToken"->refreshToken).executeInsert()
it works. I solved the problem, but it would be better not to hardcode the table name for refactoring reasons. Why can't I use the dynamic mapping functionality of Anorm in this case?
As said by m-z, the syntax {placeholder} is only for parameter (when followed by .on("placeholder", value)).
You can mix plain String interpolation with this syntax SQL(s"SELECT $table ... {id}").
I have:
INSERT INTO XYZ (c1, c2, range) VALUES (?, ?, ?)
OleDb call fails here because of range is a reserved keyword - how to quote it through the OleDB?
Use double quotes ":
INSERT INTO XYZ (c1, c2, "range") VALUES (?, ?, ?)