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

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.

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?

How to populate H2 DB UUID primary key using sql file in 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

Difference between MongoSpringData id and _id

I am using MongoDB community edition 4.2 on Windows 10 and inserting some documents. My requirement is to store some documents containing 'id' as field name while MongoDB is replacing it with '_id' and making it the primary key. Is it possible to disable this feature and store key '_id' as the separate autogenerated primary key column and store 'id' as well in separated column which is part of my document?
We are using Spring Data MongoDb Repository entities insertion into MongoDb. What we have observerd the entity having name 'id' as primary key get converted to _id while entities having other name like projectId or something stored as it is with another seperate column as _id generated by MongoDB as primary key. Suggestions are helpful.
Code:
#Autowired
TrackHistoryRepository trackHistoryRepository;
trackHistoryRepository.save(entity);
public interface TrackHistoryRepository extends MongoRepository<OdataEntity, String> {}
Entity:
public class CurrencyEntity implements OdataDeleteableEntity<Long> {
#Id
#GeneratedValue(strategy= GenerationType.IDENTITY)
#Column(name="id")
private Long id;
}
MongoDB can't do that. _id in mongodb is auto-incremented and auto-generated id key for specific record or data field. And _id is primary key by default set by mongodb. You can also enter your user defined key(value) to the _id but you cant change name of field.

How to establish foreign key relationship with a non entity table in the database using Spring data JPA?

My spring boot project uses an existing database, I have a new model entity/table in my project that must have a foreign key constraint with an existing table in the database.
I've tried to find solution online but all the answers are for the case where both the tables are present as entities in that project and using some #ManyToOne, #OneToMany annotations.
I can't define those annotations because I don't have the reference table as an entity or model in my project.
Let's say I have class like:
#Entity(name = "user")
public class User {
#Id
#GeneratedValue
private long userId;
private long departmentId;
I want to put a foreign key contraint on the departmentId column to reference to id column of the existing department table that isn't defined as a model or entity in my project.
Thanks
Just do it as normal
example
#Column(name = "department_id")
private Department departmentId;
You can later access it Department.departmentId. Hope this helps.
Try it like this
#ManyToOne
#JoinColumn(name="(column name of current entity)", referencedColumnName="(column name in target entity)")
private Department departmentId;
you can skip the referencedColumnName if the column name is same in both the entities

JPA - Auto-generated field null after save

I have an Account entity and I'm trying to persist it using save function. My code:
#Override
public Account createAccount(String pin) {
Account account = new Account();
account.setBalance(0L);
account.setPin(pin);
return accountRepository.save(account);
}
Now my entity class has an autogenerated field called accountNumber. My entity class:
#Entity
#Table(name = "accounts")
#Data
public class Account {
#Column(name = "account_number", length = 32, insertable = false)
private String accountNumber;
private Long balance;
}
Now after calling save, the entity returned has accountNumber as null but i can see in the intellij database view that it is actually not null. All the other auto-generated fields like id etc are there in the returned entity just the accountNumber is null. Default value for accountNumber is set in the sql file :
ALTER TABLE accounts
ALTER COLUMN account_number SET DEFAULT DefaultValueSerializer(TRUE, TRUE, 12);
Here, DefaultValueSerializer is the function which is generating the account number.
I've tried other solutions available here like using saveAndFlush() etc, nothing worked in my case. What can be an issue?
As mentioned in comment Hibernate is not aware about what happens in database engine level so it does not see the value generated.
It would be wise to move generation of account number to JPA level instead of using db defaults.
I suggest you to study annotations #GeneratedValue and related stuff like #SequenceGenerator. That way the control of generating account number is in JPA level and there is no need for stuff like refreshing entity after save.
One starting point: Java - JPA - Generators - #SequenceGenerator
For non-id fields it is possible to generate value in method annotated with #PrePersist as other answer suggests but you could do the initialization already in the Accounts constructor .
Also see this answer for options.
You can create an annotated #PrePersist method inside the entity in which you set its fields to their default value.
That way jpa is going to be aware of the default.
There are other such annotation avaiable for different entity lifecycle event https://docs.jboss.org/hibernate/entitymanager/3.6/reference/en/html/listeners.html
P.s. if you decide to go this way remember to remove the insertable = false
Use
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
for your IDs. And also leave your saving to saveAndFlush so you can immediately see the changes, If any. I'd also recommend separating IDs and account numbers. They should not be the same. Try debugging your program and see where the value stops passing around.

Resources