How to get db information using Spring JdbcTemplate and plain SQL (Micronaut) - spring

I am trying to create a web application using Micronaut and need to get information from travelLog table using Spring JdbcTemplate and plain
SQL. I was using this tutorial https://www.greggbolinger.com/posts/using-springs-jdbctemplate-with-micronaut/ to solve this, but I faced the following problem:
30.869 [default-nioEventLoopGroup-1-2] ERROR i.m.h.s.netty.RoutingInBoundHandler - Unexpected error occurred: StatementCallback; bad SQL grammar [SELECT * FROM travelLog]; nested exception is org.postgresql.util.PSQLException: ERROR: relation "travellog" does not exist
Position: 15
org.springframework.jdbc.BadSqlGrammarException: StatementCallback; bad SQL grammar [SELECT * FROM travelLog]; nested exception is org.postgresql.util.PSQLException: ERROR: relation "travellog" does not exist
Position: 15
at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:237)
at
Here is travelLog table Schema
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet id="01" author="julia">
<createTable tableName="travelLog"
remarks="A table to contain all travel logs">
<column name="id" type="int">
<constraints nullable="false" unique="true" primaryKey="true"/>
</column>
<column name="date" type="timestamp">
<constraints nullable="false"/>
</column>
<column name="regNumber" type="varchar">
<constraints nullable="false"/>
</column>
<column name="ownersName" type="varchar(50)">
<constraints nullable="false"/>
</column>
<column name="odometerValueBeg" type="int">
<constraints nullable="false"/>
</column>
<column name="odometerValueEnd" type="int">
<constraints nullable="false"/>
</column>
<column name="departurePlace" type="varchar(255)">
<constraints nullable="false"/>
</column>
<column name="destinationPlace" type="varchar(255)">
<constraints nullable="false"/>
</column>
<column name="description" type="varchar">
</column>
</createTable>
</changeSet>
</databaseChangeLog>
Here is JdbcTemplateFactory.java
#Factory
public class JdbcTemplateFactory {
#Inject
DataSource dataSource;
#Bean
#Singleton
JdbcTemplate jdbcTemplate() {
return new JdbcTemplate(dataSource);
}
}
Here is TravelLogService.java
#Singleton
#Requires(beans = JdbcTemplate.class)
public class TravelLogService {
private final JdbcTemplate jdbcTemplate;
public TravelLogService(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
#Transactional
public void printUsernames() {
jdbcTemplate.query("SELECT * FROM travelLog", (rs) -> {
System.out.println(rs.getString("ownersName"));
});
}

To create and query case sensitive table, columns etc, names must be quoted like this:
SELECT * FROM "travelLog"
For liquibase settings check this answer https://stackoverflow.com/a/60654633/1854103
Also please consider change your naming conventions

Related

Hibernate Envers Audit Join Table defenition

I want to add history to my entities and I am playing arround with hibernate Envers.
I have defined Handbook and Chapter classes with the coresponding 5 tables:
HANDBOOK, HANDBOOK_AUD, CHAPTER, CHAPTER_AUD and REVINFO.
If there is no connection between the 2 entities, everithing works fine, but when I add oneToMany relationship for HANDBOOK and CHPATER the application fails to start because of missing HANDBOOK_CHAPTER_AUD table.
Thinking about it is absolutely fine to have that JoinTable, but the problem is how should define it.
Handbook entity:
#Entity
#Audited
#Getter
#Setter
#NoArgsConstructor
public class Handbook {
#Id
#SequenceGenerator(name = "HANDBOOK_ID_SEQUENCE", sequenceName = "HANDBOOK_ID_SEQUENCE", allocationSize = 1)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "HANDBOOK_ID_SEQUENCE")
private Long id;
private String title;
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
#JoinColumn(name = "HANDBOOK_ID")
#AuditJoinTable(name = "REV_HANDBOOK_CHAPTER")
private Set<Chapter> chapters;
}
Chapter entity:
#Entity
#Audited
#Getter
#Setter
#NoArgsConstructor
public class Chapter {
#Id
#SequenceGenerator(name = "CHAPTER_ID_SEQUENCE", sequenceName = "CHAPTER_ID_SEQUENCE", allocationSize = 1)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "CHAPTER_ID_SEQUENCE")
private Long id;
private String name;
#Column(name = "HANDBOOK_ID")
private Long handbookId;
}
Tables deffinition:
<createTable tableName="REVINFO">
<column name="rev" type="integer">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="revtstmp" type="bigint"/>
</createTable>
<!-- Hibernate Envers need this seq exact to increase the revision number for versioned entities-->
<createSequence sequenceName="HIBERNATE_SEQUENCE"
startValue="1"
incrementBy="1"/>
<createTable tableName="HANDBOOK">
<column name="ID" type="bigint">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="TITLE" type="varchar2(128 char)"/>
</createTable>
<createTable tableName="REV_HANDBOOK">
<column name="ID" type="bigint"/>
<column name="TITLE" type="varchar2(128 char)"/>
<column name="REV_ID" type="integer">
<constraints foreignKeyName="FK_HANDBOOK_REV"
references="REVINFO(REV)"/>
</column>
<column name="REV_TYPE" type="smallint"/>
</createTable>
<!-- CHAPTER TABLES -->
<createTable tableName="CHAPTER">
<column name="ID" type="bigint">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="NAME" type="varchar2(128 char)"/>
<column name="HANDBOOK_ID" type="integer">
<constraints foreignKeyName="FK_CHAPTER_HANDBOOK_ID"
references="HANDBOOK(ID)"/>
</column>
</createTable>
<createTable tableName="REV_CHAPTER">
<column name="ID" type="bigint"/>
<column name="NAME" type="varchar2(128 char)"/>
<column name="HANDBOOK_ID" type="integer">
<constraints foreignKeyName="FK_CHAPTER_AUD_HANDBOOK_ID"
references="HANDBOOK(ID)"/>
</column>
<column name="REV_ID" type="integer">
<constraints foreignKeyName="FK_CHAPTER_REV"
references="REVINFO(REV)"/>
</column>
<column name="REV_TYPE" type="smallint"/>
</createTable>
NOTE:
I have edited some namings according to the hibernate envers documentation:
org:
hibernate:
envers:
audit_table_prefix: REV_
audit_table_suffix: ~ # No suffix
revision_field_name: REV_ID
revision_type_field_name: REV_TYPE
I have found out a sollution based on the series of errors hibernate gave me after running the code. Here is how I defiend the revision join table:
<createTable tableName="REV_HANDBOOK_CHAPTER">
<column name="ID" type="bigint"/>
<column name="REV_ID" type="integer">
<constraints foreignKeyName="FK_REV_HANDBOOK_CHAPTER_REV"
references="REVINFO(REV)"/>
</column>
<column name="HANDBOOK_ID" type="bigint">
<constraints foreignKeyName="FK_REV_HANDBOOK_CHAPTER_HANDBOOK"
references="HANDBOOK(ID)"/>
</column>
<column name="REV_TYPE" type="smallint"/>
</createTable>

Liquibase Unknown change type 'loadData'

I have been using JHipster for a long time.
But suddenly, I faced this stupid exception, and I couldn't find any solution for it.
I have exactly one other project that works without any problem, but in this project Liquibase says that it does not recognize the loadData change type.
liquibase.parser.core.ParsedNodeException: Error parsing config/liquibase/changelog/00000000000000_initial_schema.xml: Unknown change type 'loadData'. Check for spelling or capitalization errors and missing extensions such as liquibase-commercial.
I would appreciate any help🙏
Full Stacktrace:
2022-10-19T13:19:45.872+02:00 ERROR 182498 --- [all-club-task-1] t.j.c.liquibase.AsyncSpringLiquibase : Liquibase could not start correctly, your database is NOT ready: liquibase.exception.SetupException: liquibase.parser.core.ParsedNodeException: Error parsing config/liquibase/changelog/00000000000000_initial_schema.xml: Unknown change type 'loadData'. Check for spelling or capitalization errors and missing extensions such as liquibase-commercial.
liquibase.exception.ChangeLogParseException: liquibase.exception.SetupException: liquibase.parser.core.ParsedNodeException: Error parsing config/liquibase/changelog/00000000000000_initial_schema.xml: Unknown change type 'loadData'. Check for spelling or capitalization errors and missing extensions such as liquibase-commercial.
at liquibase.parser.core.xml.AbstractChangeLogParser.parse(AbstractChangeLogParser.java:25)
at liquibase.Liquibase.getDatabaseChangeLog(Liquibase.java:380)
at liquibase.Liquibase.getDatabaseChangeLog(Liquibase.java:365)
at liquibase.Liquibase.lambda$update$1(Liquibase.java:222)
at liquibase.Scope.lambda$child$0(Scope.java:180)
at liquibase.Scope.child(Scope.java:189)
at liquibase.Scope.child(Scope.java:179)
at liquibase.Scope.child(Scope.java:158)
at liquibase.Liquibase.runInScope(Liquibase.java:2414)
at liquibase.Liquibase.update(Liquibase.java:209)
at liquibase.Liquibase.update(Liquibase.java:195)
at liquibase.integration.spring.SpringLiquibase.performUpdate(SpringLiquibase.java:314)
at liquibase.integration.spring.SpringLiquibase.afterPropertiesSet(SpringLiquibase.java:269)
at org.springframework.boot.autoconfigure.liquibase.DataSourceClosingSpringLiquibase.afterPropertiesSet(DataSourceClosingSpringLiquibase.java:46)
at tech.jhipster.config.liquibase.AsyncSpringLiquibase.initDb(AsyncSpringLiquibase.java:118)
at tech.jhipster.config.liquibase.AsyncSpringLiquibase.lambda$afterPropertiesSet$0(AsyncSpringLiquibase.java:93)
at tech.jhipster.async.ExceptionHandlingAsyncTaskExecutor.lambda$createWrappedRunnable$1(ExceptionHandlingAsyncTaskExecutor.java:79)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: liquibase.exception.SetupException: liquibase.parser.core.ParsedNodeException: Error parsing config/liquibase/changelog/00000000000000_initial_schema.xml: Unknown change type 'loadData'. Check for spelling or capitalization errors and missing extensions such as liquibase-commercial.
at liquibase.changelog.DatabaseChangeLog.handleChildNode(DatabaseChangeLog.java:391)
at liquibase.changelog.DatabaseChangeLog.load(DatabaseChangeLog.java:339)
at liquibase.parser.core.xml.AbstractChangeLogParser.parse(AbstractChangeLogParser.java:23)
... 19 common frames omitted
Caused by: liquibase.exception.ChangeLogParseException: liquibase.parser.core.ParsedNodeException: Error parsing config/liquibase/changelog/00000000000000_initial_schema.xml: Unknown change type 'loadData'. Check for spelling or capitalization errors and missing extensions such as liquibase-commercial.
at liquibase.parser.core.xml.AbstractChangeLogParser.parse(AbstractChangeLogParser.java:25)
at liquibase.changelog.DatabaseChangeLog.include(DatabaseChangeLog.java:671)
at liquibase.changelog.DatabaseChangeLog.handleChildNode(DatabaseChangeLog.java:383)
... 21 common frames omitted
Caused by: liquibase.parser.core.ParsedNodeException: Error parsing config/liquibase/changelog/00000000000000_initial_schema.xml: Unknown change type 'loadData'. Check for spelling or capitalization errors and missing extensions such as liquibase-commercial.
at liquibase.changelog.ChangeSet.toChange(ChangeSet.java:525)
at liquibase.changelog.ChangeSet.handleChildNode(ChangeSet.java:454)
at liquibase.changelog.ChangeSet.load(ChangeSet.java:382)
at liquibase.changelog.DatabaseChangeLog.createChangeSet(DatabaseChangeLog.java:715)
at liquibase.changelog.DatabaseChangeLog.handleChildNode(DatabaseChangeLog.java:370)
at liquibase.changelog.DatabaseChangeLog.load(DatabaseChangeLog.java:339)
at liquibase.parser.core.xml.AbstractChangeLogParser.parse(AbstractChangeLogParser.java:23)
... 23 common frames omitted
My databaseChangeLog file:
<?xml version="1.0" encoding="utf-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd">
<changeSet id="00000000000000" author="jhipster">
<createSequence sequenceName="sequence_generator" startValue="1050" incrementBy="50"/>
</changeSet>
<!--
JHipster core tables.
The initial schema has the '00000000000001' id, so that it is over-written if we re-generate it.
-->
<changeSet id="00000000000001" author="jhipster">
<createTable tableName="jhi_user">
<column name="id" type="${uuidType}">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="login" type="varchar(50)">
<constraints unique="true" nullable="false" uniqueConstraintName="ux_user_login"/>
</column>
<column name="password_hash" type="varchar(60)"/>
<column name="email" type="varchar(191)">
<constraints unique="true" nullable="true" uniqueConstraintName="ux_user_email"/>
</column>
<column name="image_url" type="varchar(256)"/>
<column name="activated" type="boolean" valueBoolean="false">
<constraints nullable="false" />
</column>
<column name="lang_key" type="varchar(10)"/>
<column name="activation_key" type="varchar(20)"/>
<column name="reset_key" type="varchar(20)"/>
<column name="created_by" type="varchar(50)">
<constraints nullable="false"/>
</column>
<column name="created_date" type="timestamp"/>
<column name="reset_date" type="timestamp">
<constraints nullable="true"/>
</column>
<column name="last_modified_by" type="varchar(50)"/>
<column name="last_modified_date" type="timestamp"/>
</createTable>
<createTable tableName="jhi_authority">
<column name="name" type="varchar(50)">
<constraints primaryKey="true" nullable="false"/>
</column>
</createTable>
<createTable tableName="jhi_user_authority">
<column name="user_id" type="${uuidType}">
<constraints nullable="false"/>
</column>
<column name="authority_name" type="varchar(50)">
<constraints nullable="false"/>
</column>
</createTable>
<addPrimaryKey columnNames="user_id, authority_name" tableName="jhi_user_authority"/>
<addForeignKeyConstraint baseColumnNames="authority_name"
baseTableName="jhi_user_authority"
constraintName="fk_authority_name"
referencedColumnNames="name"
referencedTableName="jhi_authority"/>
<addForeignKeyConstraint baseColumnNames="user_id"
baseTableName="jhi_user_authority"
constraintName="fk_user_id"
referencedColumnNames="id"
referencedTableName="jhi_user"/>
<addNotNullConstraint columnName="password_hash"
columnDataType="varchar(60)"
tableName="jhi_user"/>
<loadData
file="config/liquibase/data/user.csv"
separator=";"
tableName="jhi_user"
usePreparedStatements="true">
<column name="id" type="${uuidType}"/>
<column name="activated" type="boolean"/>
<column name="created_date" type="timestamp"/>
</loadData>
<dropDefaultValue tableName="jhi_user" columnName="created_date" columnDataType="${datetimeType}"/>
<loadData
file="config/liquibase/data/authority.csv"
separator=";"
tableName="jhi_authority"
usePreparedStatements="true">
<column name="name" type="string"/>
</loadData>
<loadData
file="config/liquibase/data/user_authority.csv"
separator=";"
tableName="jhi_user_authority"
usePreparedStatements="true">
<column name="user_id" type="${uuidType}"/>
</loadData>
</changeSet>
<changeSet author="jhipster" id="00000000000002" context="test">
<createTable tableName="jhi_date_time_wrapper">
<column name="id" type="BIGINT">
<constraints primaryKey="true" primaryKeyName="jhi_date_time_wrapperPK"/>
</column>
<column name="instant" type="timestamp"/>
<column name="local_date_time" type="timestamp"/>
<column name="offset_date_time" type="timestamp"/>
<column name="zoned_date_time" type="timestamp"/>
<column name="local_time" type="time"/>
<column name="offset_time" type="time"/>
<column name="local_date" type="date"/>
</createTable>
</changeSet>
</databaseChangeLog>
I spoke with #nvoxland about this yesterday, and he said that he answered a very similar question on the Liquibase forum.
The short version: you need to update to the most current Liquibase release and then try again. If that doesn't work, then you should add open.csv to the dependency.

Unkown column in 'field list' after creating tables by liquibase

I prepare liquibase scripts to generate my tables and relationships.
ChangeLog which create relationships:
<changeSet id="1" author="xyz">
<createTable tableName="drivers_and_tickets">
<column name="driver_id" type="varchar(36)">
<constraints nullable="false" />
</column>
<column name="ticket_id" type="varchar(36)">
<constraints nullable="false" />
</column>
</createTable>
<addForeignKeyConstraint constraintName="fk_drivers"
baseTableName="drivers_and_tickets" baseColumnNames="driver_id"
referencedTableName="drivers" referencedColumnNames="id" />
<addForeignKeyConstraint constraintName="fk_tickets"
baseTableName="drivers_and_tickets" baseColumnNames="ticket_id"
referencedTableName="tickets" referencedColumnNames="id" />
</changeSet>
<changeSet id="2" author="xyz">
<createTable tableName="tickets_and_offences">
<column name="ticket_id" type="varchar(36)">
<constraints nullable="false" />
</column>
<column name="offence_id" type="varchar(36)">
<constraints nullable="false" />
</column>
</createTable>
<addForeignKeyConstraint constraintName="fk_tickets_from_offences"
baseTableName="tickets_and_offences" baseColumnNames="ticket_id"
referencedTableName="tickets" referencedColumnNames="id" />
<addForeignKeyConstraint constraintName="fk_offences"
baseTableName="tickets_and_offences" baseColumnNames="offence_id"
referencedTableName="offences" referencedColumnNames="id" />
</changeSet>
And it ok, app is starting without any errors.
I use hibernate too, so I prepared entites:
public class DriverEntity {
#Id
#GeneratedValue(generator = "system-uuid")
#GenericGenerator(name = "system-uuid", strategy = "uuid")
private String id;
private String name;
private String surname;
private String email;
#OneToMany(mappedBy="driver")
private List<TicketEntity> tickets;
public class TicketEntity {
#Id
#GeneratedValue(generator = "system-uuid")
#GenericGenerator(name = "system-uuid", strategy = "uuid")
private String id;
private LocalDate date;
#OneToMany(mappedBy="ticket")
private Set<OffenceEntity> offences;
#ManyToOne
#JoinColumn(name="driver_id")
private DriverEntity driver;
and next when I call repository findAllDrivers I am getting error:
"Unknown column 'tickets0_.driver_id' in 'field list'" .
When I was using hibernate.ddl-auto mapping like that in entities was enough to create tables and getting records from database.
Edit:
I have checked how it looks in my DB and do not know what is wrong

Liquibase , how to add a group of fields like primary key?

I have an entity with a group of fields in primary key.
Like this :
#Entity
#Table(name = "pv_object")
#NamedQuery(name = "PreviousObject.findAll", query = "SELECT p FROM PreviousObject p")
public class PreviousObject implements Serializable {
#EmbeddedId
private FieldsDTO fieldsdto;
//
}
FieldsDTO class contains 2 String and 2 Integer.
I have and I use Liquidbase on my project in a XML file, but, I don't know how to represent this ID of 4 fields in liquidbase.
Thanks for your help :)
In <addPrimaryKey you can configure columnNames by all your columns that compose your primary key
<changeSet author="liquibase-docs" id="addPrimaryKey-example">
<addPrimaryKey
columnNames="id, name"
constraintName="pk_person"
schemaName="public"
tableName="person"
tablespace="A String"/>
</changeSet>
Assign the same primaryKeyName to them.
<createTable tableName="pv_object">
<column name="x" type="bigint">
<constraints nullable="false" primaryKey="true" primaryKeyName="PK_pv_object"/>
</column>
<column name="y" type="bigint">
<constraints nullable="false" primaryKey="true" primaryKeyName="PK_pv_object"/>
</column>
</createTable>
or add separately
<addPrimaryKey tableName="REPRESENTATIVE" columnNames="REPRESENTED_USER_ID,REPRESENTATIVE_ID"
constraintName="REPRESENTED_REPRESENTATIVE_PK" />

spring-boot with liquibase #OneToMany mapping

I have two entity Person and Address. And Person can have multiple Address.
<createTable tableName="ADDRESS">
<column name="id" type="bigint(20)" autoIncrement="true">
<constraints primaryKey="true" nullable="false" />
... //columns
</column>
</createTable>
<createTable tableName="PERSON">
<column name="id" type="bigint(20)" autoIncrement="true">
<constraints primaryKey="true" nullable="false" />
... //columns
</column>
</createTable>
<addForeignKeyConstraint
constraintName="fk_constraint_worker_phone_number"
referencedTableName="CONTACT_NUMBER" baseColumnNames="ContactNumbers"
baseTableName="WORKER" referencedColumnNames="id" />
I want 3rd table (like hibernate generate in #OneToMany mapping).
How to do this with liquibase-springboot?
If the relation is truly a OnToMany, you don't need a 3rd table. Simply, add PrimaryKeyJoinColumn.
If the address can be reused for many persons, it's a ManyToMany relation.
You can use #ManytoMany and add information about you joined table un #jointable
Well, in case of liquibase we have to create the 3rd table manually and have to apply the necessary constraints.
Create the table which manages the mapping :
<createTable tableName="PERSON_ADDRESS">
<column name="PERSON_ID" type="BIGINT">
<constraints primaryKey="true" nullable="false" />
</column>
<column name="ADDRESS_ID" type="BIGINT">
<constraints primaryKey="true" nullable="false" />
</column>
</createTable>
Apply the constraints:
1) Ensure that Persons id is unique in the mapping table
2) A foreign key relationship between ADDRESS's id and PERSON_ADDRESS's PERSON_ID
3) A foreign key relationship between PERSON's id and PERSON_ADDRESS's ADDRESS_ID
<addUniqueConstraint
columnNames="PERSON_ID" tableName="PERSON_ADDRESS"
constraintName="UK_PHONE_NUMBERS_ID" />
<addForeignKeyConstraint
constraintName="FK_ADDRESS_PERSON_ADDRESS"
referencedTableName="ADDRESS"
baseColumnNames="ADDRESS_ID"
baseTableName="PERSON_ADDRESS" referencedColumnNames="id" />
<addForeignKeyConstraint
constraintName="FK_PERSON_PERSON_ADDRESS"
referencedTableName="PERSON"
baseColumnNames="PERSON_ID"
baseTableName="PERSON_ADDRESS" referencedColumnNames="id" />

Resources