How to populate H2 DB UUID primary key using sql file in Spring Boot - spring-boot

I am developing a Spring Boot-2.4 application which use Spring Data JPA and I am writing test for my CURD implementation. I have few scenarios needs to load table data with specific primary key values before my test execution. I thought of using import.sql or data.sql in which i can write native SQL queries and use those supplied primary key values. As my primary key is defined as UUID eventhough I gave valid UUID data in SQL while fetching using findById its not working.
data.sql
insert into TEST_TABLE(id,name,pass) value ('2B12245566587878779679','test','xxxxx');
Assume given UUID value is valid and I can able to insert this data in H2 and able to view.
But when in JPA try to access this same ID using findById('2B12245566587878779679') will not returning this record. Is there any correct way to load the UUID and access it using .sql file.
EDIT: Included code sample
#Entity(name="TEST_TABLE")
public class TestTable{
#Id
#GeneratedValue
private UUID id;
}
#Repository
public interface TestTableRepository extends JpaRepository<TestTable,UUID>{}
#Service
public class TestTableService {
#Autowired
TestTableRepository testTableRepository;
public UUID getTableData(UUID id){
testTableRepository.findById(id); // here passing 2B12245566587878779679
}
}
Expecting one row returned but its not returning any

Related

Get back autogenerated columns from database when saving an entity with Spring Data R2dbc

I have an issue when I create an entity like this
#Table("event_service.EVENT")
public class Event implements Persistable<UUID> {
#Id
private UUID id;
//Autogenerated by database if null
private UUID eventId;
}
I have a normal repository like this defined:
interface EventRepository extends ReactiveCrudRepository<Event, UUID>
When I use the repository to save this entity, the entity that is return still has eventId as null and I have to refetch the entity again from the DB to get it populated correctly. I can see that the query generated does only include the ID field in the RETURNING clause of the auto generated SQL. Is there a way to get the other auto generated field back automatically on the save method?

JPA issue mapping Cassandra Java Entity to table name with snake case

I am using below drivers.
implementation 'com.datastax.astra:astra-spring-boot-starter:0.3.0'
implementation 'com.datastax.oss:java-driver-core:4.14.1'
implementation 'com.datastax.oss:java-driver-query-builder:4.14.1'
implementation 'com.datastax.oss:java-driver-mapper-runtime:4.14.1'
implementation 'org.springframework.boot:spring-boot-starter-data-cassandra'
Here are my entities:
#NamingStrategy(convention = NamingConvention.SNAKE_CASE_INSENSITIVE)
#CqlName("engine_torque_by_last_miles")
#Entity
public class EngineTorqueByLastMiles {
private UUID id;
#PartitionKey(1)
private String vinNumber;
}
Here is my repository:
public interface EngineTorqueByLastMilesRepository extends CassandraRepository<EngineTorqueByLastMiles, String> {
List<EngineTorqueByLastMiles> findAllByVinNumberAndOrganizationId(String vinNumber, Integer organizationId);
}
The problem I am facing is the soring.data.jpa.cassandra does not map the Entity name or the attributes to snake_case even after using NamingStrategy or CqlName annotations from datastax drivers.
Does datastax provide any driver that supports jpa so that I can write my Entities and their attributes in typical java naming convention and cassandra tables or attributes with snake_case ?
Datastax provides indeed a way to map objects to your Cassandra Tables and it is called the Cassandra object mapper. The documentation is here https://docs.datastax.com/en/developer/java-driver/4.13/manual/mapper/ BUT YOU DO NOT NEED IT HERE.
Looking at your code it seems you want to use Spring Data Cassandra. This is totally fine. You are simply not using the proper set of annotations. You should the Spring data annotations.
Your bean becomes:
#Table("engine_torque_by_last_miles")
public class EngineTorqueByLastMiles {
#PrimaryKeyColumn(name = "vin_number", ordinal = 0, type = PrimaryKeyType.PARTITIONED)
private String vinNumber;
#Column("id")
#CassandraType(type = Name.UUID)
private UUID id;
// default constructor
// getters
// setters
}
Given the table name, it seems your partition key should be last_miles but it was not provided in your question.
You provided an id but it was not annotated also I assumed it was not part of the primary key. If you have a composite primary key with Partition key and cluster columns you need to create an ANOTHER internal bean for the PK and annotate it with #PrimaryKey (sample)
You can find a full-fledge working application here with multiple entities https://github.com/datastaxdevs/workshop-betterreads/tree/master/better-reads-webapp
If you edit or complete your question we could propose the exact beans needed.
Try setting the property:
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
since Hibernate 5 it's the default and you would get your snake-cased naming.
For more reference see the documentation here

Specify foreign key reference in Spring Data Rest, Update Request using HTTP PUT

I have an entity
#Entity
#Table(name="Indications")
#NamedQuery(name="Indication.findAll", query="SELECT i FROM Indication i")
public class Indication implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="IndicationID")
private int indicationID;
#Column(name="IndicationDescription")
private String indicationDescription;
#ManyToOne
#JoinColumn(name="ParentIndicationID")
private Indication indication;
}
As is evident in the entity the table has 3 columns
IndicationID which is a primary key
IndicationDescription which is a string
Indication which is a foreign key reference to a row in the same table, so it is many-to-one relationship
Since I am using Spring Data Rest I can create a new record using HTTP POST with the following body
{
"indicationDescription": "dummy1",
"indication": "/indications/1"
}
This creates a new row in the database with the content dummy1 and creates a foreign key reference to the record with id 1.
But when I try to update the foreign key reference using HTTP PUT with the following body
{
"indicationDescription": "dummy2",
"indication": "/indications/2"
}
While it updates the indicationDescription it does not actually update the foreign key reference.
I am aware that I can update the foreign key reference by using the URL http://localhost:8080/indications/7733/indication
and sending body as
http://localhost:8080/indications/2
after setting the content type to text/uri-list
My question is , Is there a way to perform the update in one request using the body similar to the one I used for creation of the record instead of making another update request using the URL - http://localhost:8080/indications/7733/indication
Thanks in advance.

H2 JdbcSQLException: "Table not found" with camelcase table & entity name

Using Spring Boot, with Spring Data JPA and H2 in-memory database (in PostgreSQL mode if it makes a difference).
I have a table & entity class named ContentBlock, yet H2 is complaining about missing CONTENT_BLOCK table, when I do a findAll() or findOne():
org.h2.jdbc.JdbcSQLException: Table "CONTENT_BLOCK" not found
I'm not sure if uppercase/camelcase makes a difference, but where does the underscore in CONTENT_BLOCK come from?
In my schema definition:
CREATE TABLE ContentBlock (
id BIGSERIAL PRIMARY KEY,
content TEXT
-- etc
);
And in the entity class:
#Entity
#Table(name = "ContentBlock")
public class ContentBlock {
// ...
}
(Of course I first tried without #Table annotation, as the class name exactly matches the table name.)
With my other tables/entities, with names like Asset, there are no problems, and I don't need to explicitly specify the table name on Java side:
#Entity
public class Asset {
// ...
}
In my setup, the H2 datasource is explicitly defined like this:
#Bean
public DataSource devDataSource() {
return new EmbeddedDatabaseBuilder()
.generateUniqueName(true)
.setType(EmbeddedDatabaseType.H2)
.setScriptEncoding("UTF-8")
.ignoreFailedDrops(true)
.addScripts("database/init.sql", "database/schema.sql", "database/test_data.sql")
.build();
}
(Contents of init.sql is SET MODE PostgreSQL;)
As workaround, I just renamed the ContentBlock table to Block in schema.sql, with #Table(name = "Block") in the Java class which I still call ContentBlock.
But this is weird, surely you can map a table with camelcase name to an entity somehow?
By default Spring Boot uses SpringNamingStrategy. It extends org.hibernate.cfg.ImprovedNamingStrategy from Hibernate 4. ImprovedNamingStrategy generates underscores in table names.
To map a table with camel case name to an entity you can use org.hibernate.cfg.EJB3NamingStrategy or implement your own.
An example of set a name strategy using properties
spring.jpa.hibernate.naming_strategy=org.hibernate.cfg.EJB3NamingStrategy

Unable to see generated tables generated by hibernate schema export (H2 database)

I am trying to get a small app going using Spring Boot (v1.1.1.RELEASE), and H2 database. In the logging i see that the ddl is correctly generated but it i just cannot find the tables inside the H2 database.
I manually copied the ddl into a db visualizer and the sql is ok. I have no clue what i am missing here. When executing code the JPA persistence layer seems to store the data correctly as i get generated ID's back etc.. I was thinking that i made a mistake in the jdbc url, but they all point to the same file based H2 database. But this database just seems to hold no data.
The JPA object
#Entity
#Table(name = "rawdata", schema = "PUBLIC")
public class RawData {
#Id
#GeneratedValue
private Long id;
#Lob
#Column(name = "payload", nullable = false)
private String payload;
// getters and setters omitted
}
The JPARepository
#Repository
public interface RawDataRepository extends JpaRepository<RawData, Long> {
}
Application properties
spring.datasource.url=jdbc:h2:file:/home/username/dev-db
spring.datasource.driverClassName=org.h2.Driver
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.show-sql=true
Logging info
org.hibernate.tool.hbm2ddl.SchemaExport : HHH000227: Running hbm2ddl schema export
Hibernate: drop table PUBLIC.rawdata if exists
Hibernate: create table PUBLIC.rawdata (id bigint generated by default as identity, payload clob not null, primary key (id))
org.hibernate.tool.hbm2ddl.SchemaExport : HHH000230: Schema export complete
Test code
#Autowired
private RawDataRepository repository;
repository.saveAndFlush(new RawData("test"));
System.out.println(repository.count());
So saving a JPA object actually seems to persist the object (the count increases etc) but the data and table structure do not appear in the database. I see that the modified date changes of the database when persisting an object but i seem unable to view the data with for example squirrel/dbvisualizer etc.. Any hints or tips?
The problem is that when the application is shutdown, Hibernate will drop the entire schema, because you have configured spring.jpa.hibernate.ddl-auto=create-drop.
If you change your configuration to spring.jpa.hibernate.ddl-auto=create the schema will not be dropped at the end of the session and you will be able to see the tables that where created along with any data you inserted

Resources