JPA composite Foreign Key part of composite Primary Key unable to find ID - jpa

We have tables,
'Lin_Code_Groups' with fields,
Project_ID (PK),
CG_ID(PK),
CG_Name
Corresponding entity class,
public class Lin_Code_Groups implements Serializable {
#EmbeddedId
private LinCodeGroupPK pk;
private String CG_name;
#Embeddable
public static class LinCodeGroupPK implements Serializable {
private Integer Project_ID;
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer CG_ID;
}
#OneToMany(mappedBy = "lin_Code_Groups")
private List<Lin_CG_Params> lin_CG_Params;
}
table Lin_CG_Params with fields,
Project_ID (PK)..FK to Lin_Code_Groups,
CG_ID(PK)...FK to Lin_Code_Groups,
Param_name(PK),
Param_value
Corresponding entity class,
public class Lin_CG_Params implements Serializable {
#EmbeddedId
private LinCodeGroupParamPK pk;
private String Param_value;
#Embeddable
public static class LinCodeGroupParamPK implements Serializable {
private String Param_name;
private LinCodeGroupPK linCodeGroupPK;
}
#MapsId("linCodeGroupPK")
#ManyToOne
#JoinColumns( {
#JoinColumn(name = "Project_ID",referencedColumnName= "Project_ID"),
#JoinColumn(name = "CG_ID",referencedColumnName= "CG_ID")
})
private Lin_Code_Groups lin_Code_Groups;
}
in controller class, i am using JPA's .Save method to save the data in to the tables.
#PostMapping(value = {"/hello"}, consumes = "application/json", produces = "application/json")
public ResponseEntity<Object> saveNewCodeGroupsDetails(#RequestBody Lin_Code_Groups objLin_Code_Groups ) {
respository.save(objLin_Code_Groups);
}
but getting an error 'Unable to find Lin_CG_Params with id Lin_CG_Params.LinCodeGroupParamPK'
Can anyone is please help ?

Related

#OneToOne Composite Primary Key of Entities

I need help for this case.
I have the following entities (I removed getters/setters/hash/toString for easy reading):
#Entity
public class Company implements Serializable{
#Id
private String id;
}
#Entity
public class Document implements Serializable{
#Id
private String id;
}
#Entity
#IdClass(Inbox.PK.class)
public class Inbox implements Serializable {
#Id
#ManyToOne(fetch = FetchType.LAZY)
private Company company;
#Id
#ManyToOne(fetch = FetchType.LAZY)
private Document document;
#OneToOne(fetch = FetchType.LAZY, mappedBy = "inbox")
private Invoice invoice;
public class PK implements Serializable{
private Company company;
private Document document;
}
}
First question is, should I use Company and Document types in PK class or String and String?
And here ... the headache :
#Entity
#IdClass(Invoice.PK.class)
public class Invoice implements Serializable {
#Id
#OneToOne(fetch = FetchType.LAZY, mappedBy = "invoice")
// #MapsId // ???
#JoinColumn(name = "companyId")//, referencedColumnName = "company")// ???
#JoinColumn(name = "documentId")//, referencedColumnName = "document")// ???
// #PrimaryKeyJoinColumn // ????
private Inbox inbox;
#Data
public static class PK implements Serializable {
// private Inbox inbox; // ???
// private String company,document; // ???
// private String companyId,documentId; // ???
// private String inboxCompanyId,inboxDocumentId; // ???
}
}
The PK of the Invoice Entity is also the FK to Inbox (I would like constraints to be generated), and the PK of Inbox is composed of two Entities (Company and Document).
I prefer to use IdClass rather EmbeddedId.
How could I configure Invoice to have, at the end, (company_id,document_id) as PK AND FK to Inbox?
I saw your question posted in upwork. I think you should use string + string type fields with #Id and #Column annotations in PK class.

Spring Data JPA #OneToOne mapping is not projected

This question is already phrased as an issue here: https://github.com/spring-projects/spring-data-jpa/issues/2369 but for lack of a reaction there I am copying the contents of that issue here, hoping that somebody might find what's wrong with my code or confirm that this could be a bug:
I've set up an example project here that showcases what seems to be a bug in Spring Data projections: https://github.com/joheb-mohemian/gs-accessing-data-jpa/tree/primary-key-join-column-projection-bug/complete
I have a Customer entity that has a OneToOne mapping to an Address entity:
#Entity
public class Customer {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String firstName;
private String lastName;
#OneToOne(mappedBy = "customer", cascade = CascadeType.ALL)
#PrimaryKeyJoinColumn
private Address address;
//...
}
#Entity
public class Address {
#Id
#Column(name = "customer_id")
private Long id;
#OneToOne
#MapsId
#JoinColumn(name = "customer_id")
private Customer customer;
private String street;
//...
}
Then there are simple projection interfaces:
public interface CustomerProjection {
String getFirstName();
String getLastName();
AddressProjection getAddress();
}
public interface AddressProjection {
String getStreet();
}
But when I try to fetch a projected entity from a repository method like this one:
public interface CustomerRepository extends CrudRepository<Customer, Long> {
//...
<T> T findById(long id, Class<T> type);
}
, getAddress() on the projection will be null, whereas getAddress() when fetching the entity type is populated correctly. Of these two unit tests, only testEntityWithOneToOne()will be successful:
#BeforeEach
void setUpData() {
customer = new Customer("first", "last");
Address address = new Address(customer, "street");
customer.setAddress(address);
entityManager.persist(address);
entityManager.persist(customer);
}
#Test
void testEntityWithOneToOne() {
Customer customerEntity = customers.findById(customer.getId().longValue());
assertThat(customerEntity.getAddress()).isNotNull();
}
#Test
void testProjectionWithOneToOne() {
CustomerProjection customerProjection = customers.findById(customer.getId(), CustomerProjection.class);
assertThat(customerProjection.getAddress()).isNotNull();
}
What's the problem here?

Picketlink with custom model and long Id

I have a existing Model and want to use it with Picketlink. But I am using Long as #Id field. But Picketlink expect this to be a String field. I have found some hints to use another entity which maps to the corresponding entity of my model. But actually I don't now how to do it.
I have a base class, which all entities derive from:
#MappedSuperclass
public abstract class AbstractEntity implements Serializable, Cloneable {
#Id
#Identifier
#Column(name = "SID")
private Long sid;
#Column(name = "INSERT_TIME")
private Date insertTime;
#Column(name = "UPDATE_TIME")
private Date updateTime;
// getters and setters
}
And a derived realm entity:
#Entity
#IdentityManaged(Realm.class)
public class RealmEntity extends AbstractEntity {
#AttributeValue
private String name;
#PartitionClass
private String typeName;
#ConfigurationName
private String configurationName;
#AttributeValue
private boolean enforceSSL;
#AttributeValue
private int numberFailedLoginAttempts;
// getters and setters
}
And the mapping class for Picketlink looks as follows:
#IdentityPartition(supportedTypes = {
Application.class,
User.class,
Role.class
})
public class Realm extends AbstractPartition {
#AttributeProperty
private boolean enforceSSL;
#AttributeProperty
private int numberFailedLoginAttempts;
private Realm() {
this(null);
}
public Realm(String name) {
super(name);
}
}
The PartitionManager is defined as follows:
builder
.named("default.config")
.stores()
.jpa()
.supportType(User.class, Role.class, Application.class, Realm.class)
.supportGlobalRelationship(Grant.class, ApplicationAccess.class)
.mappedEntity(App.class, AppUserRole.class, AppRole.class, AppUser.class, UserEntity.class, RelationshipIdentityTypeEntity.class, RealmEntity.class)
.addContextInitializer((context, store) -> {
if (store instanceof JPAIdentityStore) {
if (!context.isParameterSet(JPAIdentityStore.INVOCATION_CTX_ENTITY_MANAGER)) {
context.setParameter(JPAIdentityStore.INVOCATION_CTX_ENTITY_MANAGER, entityManager);
}
}
});
When I try to create a new Realm Hibernate throws an error while trying to load the Realm because the #Id is defined as Long but the #Identifier of the Picketlink model is a String.
this.shsRealm = new Realm(REALM_SHS_NAME);
this.shsRealm.setEnforceSSL(true);
this.shsRealm.setNumberFailedLoginAttempts(3);
this.partitionManager.add(this.shsRealm);
java.lang.IllegalArgumentException: Provided id of the wrong type for class de.logsolut.common.picketlink.model.RealmEntity. Expected: class java.lang.Long, got class java.lang.String
How can I map the JPA model correctly to Picketlink?

composite primary key which contains a foreign key

I have an entity called UserWithRoles:
#Entity
#Getter
#Setter
public class UserWithRoles implements Serializable
{
#Id
#GeneratedValue( strategy = GenerationType.AUTO )
private int id;
private String name;
private String password;
#OneToMany( mappedBy = "user" )
private List<UserRole> roles;
}
A UserRole entity:
#Entity
#Getter
#Setter
#IdClass( UserRolePK.class )
#Inheritance( strategy = InheritanceType.JOINED )
#DiscriminatorColumn( name = "roleType", discriminatorType = DiscriminatorType.STRING, length = 10 )
abstract public class UserRole implements Serializable
{
#Id
// It should be mapped as a foreign PK by user.id (user field declared below)
private int userID;
#Id
private String roleType;
#ManyToOne
#JoinColumn( name="user_id", referencedColumnName = "id" )
private UserWithRoles user;
}
The primary key class UserRolePK:
#Data
public class UserRolePK implements Serializable
{
private int userID;
private String roleType;
}
I want to create a composite PK to UserRole: UserWithRoles.id + UserRole.roleType
How can I map it to the database? Should I use the UserWithRoles type in the PK class instead of the ID? Is it a good idea at all? Or I just should use normal PK to UserRole? The relation would be something like that between the ClientOrder and ClientOrdetItem entities: (ClientOrder.id + ClientOrderItem.num)
You are using Derived Identity.
You need to change UserRole to look like this:
#Entity
#Getter
#Setter
#IdClass( UserRolePK.class )
#Inheritance( strategy = InheritanceType.JOINED )
#DiscriminatorColumn( name = "roleType", discriminatorType = DiscriminatorType.STRING, length = 10 )
abstract public class UserRole implements Serializable
{
#Id
private String roleType;
#Id
#ManyToOne
#JoinColumn( name="user_id", referencedColumnName = "id" )
private UserWithRoles user;
}
That is, get rid of the userID field and add an #Id annotation to the user field.
And change UserRolePK to look like this:
#Data
public class UserRolePK implements Serializable
{
private int user;
private String roleType;
}
That is, change the name of the userID field to user, to match the name of the #Id field in UserRole (but its type must still match the type of the UserWithRoles PK field, id).
Derived identity is discussed in JPA 2.1 spec, section 2.4.1.

How to correctly do a manytomany join table in JPA?

I need 3 entities: User, Contract (which are a many to many relation) and a middle entity: UserContract (this is needed to store some fields).
What I want to know is the correct way to define the relationships between these entities in JPA/EJB 3.0 so that the operations (persist, delete, etc) are OK.
For example, I want to create a User and its contracts and persist them in a easy way.
Currently what I have is this:
In User.java:
#OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private List<UserContract> userContract;
In Contract.java:
#OneToMany(mappedBy = "contract", fetch = FetchType.LAZY)
private Collection<UserContract> userContract;
And my UserContract.java:
#Entity
public class UserContract {
#EmbeddedId
private UserContractPK userContractPK;
#ManyToOne(optional = false)
private User user;
#ManyToOne(optional = false)
private Contract contract;
And my UserContractPK:
#Embeddable
public class UserContractPK implements Serializable {
#Column(nullable = false)
private long idContract;
#Column(nullable = false)
private String email;
Is this the best way to achieve my goals?
Everything looks right. My advice is to use #MappedSuperclass on top of #EmbeddedId:
#MappedSuperclass
public abstract class ModelBaseRelationship implements Serializable {
#Embeddable
public static class Id implements Serializable {
public Long entityId1;
public Long entityId2;
#Column(name = "ENTITY1_ID")
public Long getEntityId1() {
return entityId1;
}
#Column(name = "ENTITY2_ID")
public Long getEntityId2() {
return entityId2;
}
public Id() {
}
public Id(Long entityId1, Long entityId2) {
this.entityId1 = entityId1;
this.entityId2 = entityId2;
}
}
protected Id id = new Id();
#EmbeddedId
public Id getId() {
return id;
}
protected void setId(Id theId) {
id = theId;
}
}
I omitted obvious constructors/setters for readability. Then you can define UserContract as
#Entity
#AttributeOverrides( {
#AttributeOverride(name = "entityId1", column = #Column(name = "user_id")),
#AttributeOverride(name = "entityId2", column = #Column(name = "contract_id"))
})
public class UserContract extends ModelBaseRelationship {
That way you can share primary key implementation for other many-to-many join entities like UserContract.