Default Value on OneToOne Association JPA - spring

i have a transactional entity and one of the fields is an association with a tenant.
#Entity
public class transactionalClass
....
#OneToOne
#JoinColumn(name = "tenant_id")
private Tenant tenant;
So this is generate a tenant_id (String) column in my transactionalClass but the type of my field is a object tenant type.
Now, i want to set directly a contextualised string (already have) on tenant_id column when create a new object. I have to do a getTenant and after set field(tenant object) in transactionalClass or is also possible to set string directly once i'm sure the key exists.
Thanks

Related

Spring does not persist bi-directional OneToOne relation on owning side

In my spring boot project I have a Document class that has a bi-directional OneToOne relationship to an Invoice class, which share the same ID.
Document
public class Document {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#OneToOne(cascade = CascadeType.ALL)
#PrimaryKeyJoinColumn
private Invoice invoice;
Invoice
public class Invoice {
#Id
#Column(name = "document_id")
private Long documentId;
#OneToOne(mappedBy = "invoice")
#MapsId
#JoinColumn(name = "document_id")
private Document document;
The document entity is created prior to the invoice entity. Later on I create an invoice entity via a MapStruct DTO-Mapping. I then save the entity to "generate" the document_id value.
After saving the invoice entity, I assign the invoice entity to the document entity and save the document entity via the repository. However, the relation to the invoice entity is not persisted in the database.
The invoice entity persists as should be with the corresponding document_id as primary key.
Service code
Invoice newInvoice = invoiceMapper.fromDto(dto);
newInvoice = invoiceRepository.save(newInvoice);
document.setInvoice(newInvoice);
documentRepository.save(document);
InvoiceMapper
#Mapper(componentModel = "spring", nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE, uses = {DocumentService.class})
public interface InvoiceMapper {
#BeanMapping(ignoreByDefault=true)
#Mapping(source = "document", target = "document")
Invoice fromDto(Dto dto);
Previously, I tried mapping the document_id in the MapStruct mapper aswell, but then I received an "attempted to assign id from null one-to-one property" exception on save (even though document and document_id were correctly defined).
When debuggin the code, it correctly shows that the invoice entity was set on the document entity, but unfortunately it is not persisted in the database.
Curiously, I am almost certain that at some point in the coding process it did work as intended. But I can not figure out where the issue is. Help would be much appreciated.
This is not setup correctly as you have not specified anything to set the Invoice's document_id column - you'd have to set this yourself from the documentId long. You must pick one side to have a foreign key to the other - presumably the Invoice has the foreign key to Document and is going to use that as its primary key as well. If that is the case, this needs to be:
public class Invoice {
#Id
#Column(name = "document_id")
private Long documentId;
#OneToOne //this is the owning side of the relationship!
#MapsId
#JoinColumn(name = "document_id")
private Document document;
..
}
public class Document {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#OneToOne(mappedBy = "document")
private Invoice invoice;
..
}
MappedBy indicates that the other side controls setting the foreign key values. Note though that your Invoice will not have a documentId value set, and that you do not need to manually set it. The MapsId annotation tells JPA to pull the value from the Document ID when it is generated and to use that for the document_id column, and will set the documentId Long at the same time.
This then will allow you to create a new Document and Invoice and just call save on the document - once. It isn't enough to just add an invoice to the document - the ID within Invoice is entirely controlled by the Invoice.document reference, so if it isn't set, it will be left null. You must maintain both sides of bidirectional relationships yourself to have the model in synch with what you want in the database. Or at least set the owning side of any bidirectional relationship.

Save only one field of an entity to another table

How do I only save a certain field/property of an Entity for another entity?
I have a Key entity with id and name properties.
In my Door entity, I would like to accept a Key but only save in the database the id
Is that possible?
Have a look at the #Transient annotation. Example from the docs:
#Entity
public class Employee {
#Id int id;
#Transient User currentUser;
...
}
#Transient will mark the annotated element to not be persisted.

Spring Data JDBC One-To-Many with Custom Column Name

I'm using spring-boot-starter-data-jdbc 2.4.2. In my domain aggregate I need to map a List of Strings that is populated from a column in another table. It is a legacy database so I have no control over the table and column names and need to use custom names. I see there is an #MappedCollection annotation, but can't see how to use it in this scenario. Below is my class:
#Data
#Table("NMT_MOVIE_THEATRE")
public class MovieTheatre {
#Id
#Column("MOVIE_THEATRE_ID")
private Long id;
#Column("ZIP_CODE")
private String zipCode;
// this comes from table NMT_CURRENT_MOVIE, column CM_ID, joined by MOVIE_THEATRE_ID
private List<String> currentMovieIds;
}
Using Spring Data JDBC, how can I create the one-to-many relation?
Wrap your String in a little entity.
#Table("NMT_CURRENTMOVIE")
class MovieId {
#Id
#Column("CM_ID")
final String id
// add constructor, equals and hashCode here or generate using Lombok
}
Then use it in the MovieTheatre. Since you don't have a column for an index, the proper collection to use is a Set
// ...
class MovieTheatre {
// ...
#MappedCollection(idColumn="MOVIE_THEATRE_ID")
Set<MovieId> currentMovieIds;
}
Note that equals and hashCode is important as well as the constructor taking all arguments used in those, since the entity is used in a Set.

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

Spring JPA one to many

I have two entities :
#Entity
#Table(name="Registration")
public class Registration{
#Id
private UUID uuid;
#OneToMany(cascade = {CascadeType.PERSIST, CascadeType.REMOVE, CascadeType.MERGE}, fetch = FetchType.LAZY)
#JoinColumn(name="registration", nullable = false)
private List<Payment> payment;
}
#Entity
#Table(name="Payment")
public class Payment {
#Id
private UUID uuid;
/*#ManyToOne(targetEntity = Registration.class) <-- MappingException: Repeated column in mapping for entity
private Registration registration;*/
}
This entities create two tables :
TABLE `registration` (
`uuid` binary(16) NOT NULL,
PRIMARY KEY (`uuid`))
TABLE `payment` (
`uuid` binary(16) NOT NULL,
`registration` binary(16) NOT NULL,
PRIMARY KEY (`uuid`),
CONSTRAINT `FK_jgemihcy9uethvoe3l7mx2bih` FOREIGN KEY (`registration`) REFERENCES `registration` (`uuid`))
I'm using Rest Service. I can access to
registration.payment
but not
payment.registration
why ? I need a relation oneToMany bidirectionnal ?
Yes, you need to add the payment.registration #ManyToOne relationship if you use it in your code.
Take into account that JPA allows you to map a SQL database model to an object oriented one. Once you have the mapping between your objects and your database, you always work at the object level. That's why, although you have the relationship in the database, your Payment object doesn't know anything about it unless you map it to an attribute.
Of course it applies when you are using you data model objects or performing JPQL or Criteria queries. If you use native queries you have access to the database model as it is.

Resources