Customizing Spring Data queries - java

I have 'iddId'(primary key) column and 'idd_id'(unused column) in the table. When I trying to execute
'findAll' method via Spring Data JPA I get empty 'iddId' field in created object because the hibernate query looks like:
select 'idd0_.idd_id as col_0_0_'...
I tried to map fields manually with a #Column(name = "iddId") annotation but nothing was changed. Then I tryed to add an additional field to the entity 'idd_id' which is annotated with #Column(name="idd_id) and received the exception:
'org.hibernate.DuplicateMappingException: Table [idd] contains physical column name [idd_id] referred to by multiple logical column names: [idd_id], [iddId]'.
Is it possible to make a query like that: 'select idd0_.iddId as col_0_0_'?
public class Idd {
#Id
#Column(name = "iddId")
private String iddId;
#Column(name = "idd_id")
private String idd_id;
}
MySql: 5.7.28
Spring Data: 2.2.2

Just add:
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
to application.properties

Related

Spring JPA automatically fetch system time stamp from database

I'd like to fetch the current system timestamp: SELECT CURRENT_TIMESTAMP; automatically every time I run a select operation.
Sample code below:
SomeEntity.java
#Entity
#Table(name = "some_table")
public class SomeEntity {
#Column(name = "name", length = 500)
private String name;
#Column(name = "current_timestamp")
private LocalDate currentTimestamp;
}
The currentTimestamp column is not physically present in the table but I wish to get the CURRENT_TIMESTAMP value from the database to be populated in this field every time I perform a SELECT operation as below:
List<SomeEntity> records = someCrudRepository.findByName("someName")
OR List<SomeEntity> records = someCrudRepository.findAll()
In short, I'd like to run this query via Spring JPA: SELECT name, current_timestamp FROM some_table;
Is there any way to achieve the same except using native or jpql queries?
I don't want to use Java time library for getting the timestamp as that is not the overall purpose of getting the current timestamp.
Hibernate's #Formula is what you are looking for:
import org.hibernate.annotations.Formula;
public class SomeEntity {
...
#Formula("current_timestamp")
private LocalDate currentTimestamp;
}

Quarkus with hibernate found [bpchar (Types#CHAR)], but expecting [char (Types#VARCHAR)]

Hello i'm trying to learn Quarkus with Hibernate but i've ran into an issue the schema-validation.
The error:
2021-12-29 16:05:14,915 ERROR
[io.qua.hib.orm.run.sch.SchemaManagementIntegrator] (Hibernate
post-boot validation thread for ) Failed to validate Schema:
Schema-validation: wrong column type encount ered in column [BED_INFO]
in table [ROOM]; found [bpchar (Types#CHAR)], but expecting [char
(Types#VARCHAR)] 2021-12-29 16:05:14,921 ERROR
[io.qua.hib.orm.run.sch.SchemaManagementIntegrator] (Hibernate
post-boot validation thread for ) The following SQL may
resolve the database issues, as generated by the Hibernate schema
migration tool. WARNING: You must manually verify this SQL is correct,
this is a best effort guess, do not copy/paste it without verifying
that it does what you expect.
the class Room looks like this
#Entity
#Table(name = "ROOM")
public class Room {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ROOM_ID")
private long id;
#Column(name = "NAME")
private String name;
#Column(name = "ROOM_NUMBER")
private String roomNumber;
#Column(name = "BED_INFO", columnDefinition = "char")
private String bedInfo;
public Room(String name, String roomNumber, String bedInfo) {
this.name = name;
this.roomNumber = roomNumber;
this.bedInfo = bedInfo;
}
}
and the mysql schema like this
CREATE TABLE ROOM(
ROOM_ID BIGSERIAL PRIMARY KEY,
NAME VARCHAR(16) NOT NULL,
ROOM_NUMBER CHAR(2) NOT NULL UNIQUE,
BED_INFO CHAR(2) NOT NULL
);
According to their documentation this "should" work but i'm perhaps missing something here.
[BED_INFO] in table [ROOM]; found [bpchar (Types#CHAR)], but expecting [char (Types#VARCHAR)]
Means that Hibernate has found a bpchar(char) where it would expect a varchar. It seems that columnDefinition does not handle char. If you really want it to be a char, try bpchar instead.
In case it doesn't work, try running your quarkus app in dev mode with this option in the application.properties file.
quarkus.hibernate-orm.database.generation=create
This will generate the actual DDL for your database that Hibernate is expecting.
Personally I would refrain from columnDefinition, instead i would use length and nullable. Unless you are building an app on an existent, I would also remove name and #Table.

What hibernate do with unmapped column?

Suppose there is a class like that:
public class Entity {
private Long id;
private String name;
}
And table with 3 columns: id, name and address.
CREATE TABLE entity (
id NUMBER(9,0),
name VARCHAR2(255),
address VARCHAR2(1000),
Then en insert was performed:
INSERT INTO entity (id, name, address) VALUES (1, "a", "b")
Then we load and update hibernate entity:
Session session = ...
Entity entity = session.get(Entity.class, 1);
Then update name and save it again:
entity.setName("newName");
session.save(entity);
So what is address column value now - null or b? Does hibernate provide some stgrategies for such situations or I have to
add address field into entity and mark it as #Column(updatable=false, insertable = false)?
If you would put the following properties in persistence.xml(or where you have defined your hibernate properties)
<property name="hibernate.show_sql" value="false"/>
<property name="hibernate.format_sql" value="false"/>
Then you could see the queries executed by hibernate when server is run in debug mode with logged configured for debug.
If your entity is
public class Entity {
private Long id;
private String name;
private String secondName;
//Getters & Setters
}
Then executing below HQL
SELECT e FROM Entity e WHERE e.id = 121
would produce results similar to
SELECT entity0_.id AS id1_63_,
entity0_.name AS name6_63_,
entity0_.secondName AS secondName6_63_,
FROM yout_db.Entity entity0_
WHERE entity0_.id = 121
You see that here SELECT * FROM Entity was not executed instead all the fields from the Class were fetched and added to the query. So if you have ignored any field from DB then it will NOT be taking part in Queries.
For Select-Update also same thing happens.
entity.setName("newName");
session.save(entity);
Below is formatted query if you would update an entity:
UPDATE your_db.Entity
SET name = ?
secondName = ?
WHERE id = ?
This query will be executed even if only one field is changed.
Hibernate operates only with columns taken from entities, based on property name or described in annotation. So in your case 'address' value will be 'b'.

hibernate.hbm2ddl.auto with auto does not add new column

After I add #Embedded with BigDecimals:
#Embeddable
public class ChildGrossNetTransformVariables {
#Column(name = "amount", precision = 19, scale = 4)
public BigDecimal amount;
...
Usage in another entities:
#Embedded
protected ParentGrossNetTransformVariables grossNetTransform;
lConf.setProperty("hibernate.hbm2ddl.auto", "auto") stoped working (I need argument "auto" but I checked also lConf.setProperty("hibernate.hbm2ddl.auto", "create-drop") and with "create-drop" argument the database was created properly). When I try to add new column to check if column autoupdate works:
#Type(type="java.lang.String")
#Column(name = "test")
protected String test;
The error
SQLGrammarException: could not extract ResultSet
...
org.postgresql.util.PSQLException: Error: the Column this._test doesnt exist
Can i debug it somehow?
I tried lConf.setProperty("hibernate.show_sql", "true"); but the first log is SELECT ... statement instead of ALTER TABLE
auto is not valid value for hibernate.hbm2ddl.auto you really mean update. Try again.

How to pass Dynamic column name one by one in mysql Update query using java spring?

public static final String UPDATE="update basic_structure.time_table set #{b_id}=#{a_id} where days='MON'";
#Update(UPDATE)
int update(#Param("b_id") String b_id,#Param("a_id") String a_id);
instead of passing dynamic column name to query you can use dynamicUpdate=true or dynamicInsert=true
so hibernate will update only those column which are modified.
e.g
#Entity
#Table(name = "<table_name>")
#org.hibernate.annotations.Entity(
dynamicUpdate = true
xml
<class ... table="<table_name>" dynamic-update="true">

Categories

Resources