How to name Foreign Key with #CollectionTable in JPA? - postgresql

I need help with resolving our problem with naming FK in JPA. We have one embeddable entity e.g. Foo which is used as collection in another one entity Bar.
embeddable entity:
#Embeddable
public class Foo{
#Column(name = "foo1")
private String foo1;
#Column(name = "foo2")
private String foo2;
}
main entity:
#Entity
#Table(name = "Bar")
public class Bar {
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
#Id
private Long id;
#ElementCollection
#CollectionTable(name = "foos", joinColumns = #JoinColumn(name = "bar_id", foreignKey = #ForeignKey(name = "foo_bar_fk"), nullable = false))
private List<Bar> bars;
}
When I generated tables in database (postgres) foreign key is called fdk44l345k64 instead foo_bar_fk. Can you tell me how to fix it? Thanks.

Related

JPA foreign key without entity

I'm trying to create a favorites table between a user and a business, but I don't want to use the entire entity, just the ids, how can this be done in JPA? Something like this:
#Data
#Entity
#Table(name = "favorite", schema = "public" , uniqueConstraints = {
#UniqueConstraint(columnNames = {"user_id", "business_id"})
})
public class Favorite {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "appuser_id")
#NotNull
private UUID appuser_id;
#Column(name = "business_id")
#NotNull
private Long businessId;
}
instead of:
#Data
#Entity
#Table(name = "favorite", schema = "public" , uniqueConstraints = {
#UniqueConstraint(columnNames = {"user_id", "business_id"})
})
public class Favorite {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "appuser_id", referencedColumnName="id")
private AppUser appUser;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "business_id", referencedColumnName="id")
private Business business;
}
Problem is, solution #1 has no foreign key ref of any kind, is there a way to do this? I would really prefer my result objects to only have ids and not the entire user / business entities every time.
I know I can make a dto with ids only and manually set it up / workaround, but I'd like an answer to this problem if one exists.

Spring Data Jpa OneToMany save bidirectional

I have a problem with saving child entities.
Here is my example. My model classes look like this:
#Entity
public class ImportDocument {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String title;
private boolean imported;
#Transient
private Status status;
#Basic
private char statusValue;
#OneToMany(mappedBy = "importDocument" , cascade = {CascadeType.ALL})
private List<ImportDocumentItem> importDocumentItems;
}
#Entity
public class ImportDocumentItem {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumn(name = "import_document_id")
#JsonIgnore
private ImportDocument importDocument;
}
I have implemented JpaRepository interfaces for both domain classes.
I try to save with:
importDocumentRepository.save(importDocument);
When I save ImportDocument object, everything is inserted. But the problem is that, the import_document_item.import_document_id (which is foreign key of import_document_id) attribute is filled with null value, not with id of import_document that I expected. How can I fix this issue?
Thanks a lot.
You have to set entity relations on both side before saving. Here an example
ImportDocument importDocument = new ImportDocument();
//...
importDocument.setImportDocumentItems(items);
items.forEach(ImportDocumentItem::setImportDocument);
importDocumentRepository.save(importDocument);

In attribute 'employees', the "mapped by" value 'project_id' cannot be resolved to an attribute on the target entity

Hi there I am new to JPA and got following error as
In attribute 'employees', the "mapped by" value 'project_id' cannot be resolved to an attribute on the target entity.
with following code
#Entity
#Table(name = "project")
public class Project {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "project_id")
protected int id;
#Column(name = "project_name")
protected String name;
#ManyToMany(mappedBy = "project_id")
protected List<Employee> employees;
#Entity
#Table(name = "employee")
public class Employee {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "employee_id")
protected int id;
#Column(name = "employee_name")
protected String name;
#ManyToMany(targetEntity = Project.class)
#JoinTable(name = "project_employee", joinColumns = #JoinColumn(name = "project_id"), inverseJoinColumns = #JoinColumn(name = "employee_id"))
protected List<Project> projects;
Here If I am trying to map the inverse entity it says that attribute not found.
Please help me to solve this
As the message says your mappedBy value is wrong. It should be the name of the FIELD/PROPERTY on the other side of the BIDIRECTIONAL relation, that links back to this class. e.g Project.employees claims to link back via field Employee.project_id, yet that doesn't exist. Instead mappedBy should be projects. This would be found in any basic JPA docs

Can I somehow cascade.PERSIST the map key in a Map<Entity, Entity>?

The situation: I have a class with a Map like this:
#Entity
public class Bar {
#Id
#GeneratedValue
private Long id;
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "fooMap",
joinColumns = #JoinColumn(name = "One_ID", referencedColumnName = "ID") ,
inverseJoinColumns = #JoinColumn(name = "Two_ID", referencedColumnName = "ID") )
#MapKeyJoinColumn(name = "Bar")
private Map<FooOne, FooTwo> fooMap;
}
with key/value-classes like this (FooTwo looks more or less the same):
#Entity
public class FooOne {
#Id
#GeneratedValue
private Long id;
#Basic
private String name;
If I populate the map and try to persist it, I get the following exception:
UnitOfWork(117839394)--java.lang.IllegalStateException: During synchronization >a new object was found through a relationship that was not marked cascade >PERSIST: jpa.test.minimalExample.FooOne#2e4389ed.
because JPA cascades only to the target of the -toMany association which is the value entity.
Does JPA in general or EclipseLink as implementation offer any form of annotation to cascade actions to the key class of this map? What are my options here ?
I know adding a reference to FooOne in the FooTwo-class works (like this):
#Entity
public class FooTwo {
#Id
#GeneratedValue
private Long id;
#OneToOne(cascade = cascadeType.ALL)
private FooOne foo1;
}
I would rather not add any additional fields to my classes if I can avoid it.

Exception while persisting JPA object in DB having one to many relation

hi have two tables in picture table a and table b as follows :
#Entity
#Table(name = "A")
public class A implements Serializable {
#Id
#SequenceGenerator(name = "JOURNAL_CATEGORY_ID_GENERATOR", allocationSize = 1, sequenceName = "clm_jounal_category_config_seq")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "JOURNAL_CATEGORY_ID_GENERATOR")
#Column(name = "CLAIM_ID")
private String claimId;
#Column(name = "name")
private String name;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "country")
private List<ClaimDTLS> claimDetails;
}
B Primary Key:
#Embeddable
public class BPK implements Serializable {
#Column(name = "code")
private String code;
#Column(name = "CLAIM_ID")
private String claimId;
}
B Entity:
#Entity
#Table(name = "B")
public class B implements Serializable {
#EmbeddedId
protected BPK bpk;
#Column(name = "name")
private String name;
#MapsId("country_code")
#JoinColumn(name = "claimId", referencedColumnName = "claimId", insertable = false, updatable = false)
#ManyToOne
private A a;
}
when i try to persist object of A type in Db the value of table b claim id is not set and is intialized with zero.
Also primary key of table A is generated with a oracle sequence.
any help will be welcomed.
thanks in advance
Sequence values are numbers and when JPA use them as a generator it call the setter method of the entity PK. Now, you defined your PK as a string while you use a sequence and so no matching setter can be found. Change the type of you PK to be Long and things shall work