I worked with postgres database, I have a Conventionnement entity with ManyToOne relationship with convention and organization, I want to create 3 primary keys convention_id, organization_id and the GeneratedValue id, i used #Embeddable like the below example, but I had the below error
Caused by: org.hibernate.annotations.common.AssertionFailure:
Declaring class is not found in the inheritance state hierarchy:
ConventionnementIdentity
and when I moved the id in Conventionnement class i had this error
ConventionnementIdentity must not have #Id properties when used as an
#EmbeddedId
#Entity
#Table(name = "conventionnement")
public class Conventionnement implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
private ConventionnementIdentity conventionnementIdentity;
#MapsId("convention_id")
#ManyToOne
private Convention convention;
#MapsId("organization_id")
#ManyToOne
private Organization organization;
//getter and setter
}
#Embeddable
public class ConventionnementIdentity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
#SequenceGenerator(name = "sequenceGenerator")
private Long id;
#Column(name = "convention_id", insertable = false, updatable = false)
private Long conventionId;
#Column(name = "organization_id", insertable = false, updatable = false)
private Long organizationId;
//getter and setter
}
You have defined an #EmbeddedId, but inside it you declare another #Id, thus the error. Make the generated id point to the correct id column in your table (below I've assumed "id" as column name):
#Embeddable
public class ConventionnementIdentity implements Serializable {
private static final long serialVersionUID = 1L;
#Column(name = "id", nullable = false)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
#SequenceGenerator(name = "sequenceGenerator", sequenceName="YOUR_DB_SEQ", allocationSize=1)
private Long id;
#Column(name = "convention_id", insertable = false, updatable = false)
private Long conventionId;
#Column(name = "organization_id", insertable = false, updatable = false)
private Long organizationId;
//getter and setter
}
Related
I am studying a training project - working with databases.
Here is a class describing the entity
#Entity
#Table(name = "pricelists", schema = "inventories")
public class PriceList {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "id_inventory", insertable = false, updatable = false)
private Long idInventory;
#ManyToOne
#JoinColumn(name = "id_inventory", nullable = false)
private Inventory inventory;
private Integer price;
}
And there are two variables that refer to the same "id_inventory" field in the database table. Is it possible to do this? Is this not a mistake?
You should leave that
#Entity
#Table(name = "pricelists", schema = "inventories")
public class PriceList {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToOne
#JoinColumn(name = "id_inventory", nullable = false)
private Inventory inventory;
private Integer price;
}
I hope that will work.
I have 2 entities:
#Entity
#Table(name = "wpf_payment_attributes")
public class WpfPaymentAttributes implements Serializable {
private static final long serialVersionUID = -2629784870868584850L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", unique = true, updatable = false, nullable = false)
private int id;
#Column(length = 32)
private Integer wpf_payment_id;
#Column(length = 255)
private String name;
....
}
Second entity:
#Entity
#Table(name = "wpf_payments")
public class WpfPayments implements Serializable {
private static final long serialVersionUID = -5740164339503774805L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", unique = true, updatable = false, nullable = false)
private int id;
#Column(length = 4)
private Integer merchant_id;
.....
}
id is generated by the DB. I use this code to insert some data:
WpfPayments obj = new WpfPayments();
obj.setReference_transaction_id(12345678);
obj.setContract_id(contract.getId());
obj.setMerchant_id(merchant.getId());
wpfPaymentsService.saveOrUpdate(obj);
WpfPaymentAttributes attibutes = new WpfPaymentAttributes();
attibutes.setName("usage");
attibutes.setValue("Test Usage");
attibutes.setWpf_payment_id(...get here some how WpfPayments table id...id);
wpfPaymentAttributesService.saveOrUpdate(attibutes);
Do you know how I can get the id from the WpfPayments object and save it using attibutes.setWpf_payment_id(...)?
You should use JoinTable attributes with a setter to the entity instead of the id of WpfPayments.
The Id of WpfPayments is generated once you call the save method on the repository of this entity, just use the result of it.
I have two classes Cards and CardBalance. In my DB sсhema table card_balance has foreign key on table cards. But in ORM I want that entity Cards has properties CardBalance, and entity CardBalance does't have propertie Cards.
I try do this in next way:
#Entity
#Table(name = "CARD_BALANCE")
public class CardBalance {
#Id
#Column(name = "BALANCE_ID")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "CARD_BALANCE_SEQ")
#SequenceGenerator(name = "CARD_BALANCE_SEQ", sequenceName = "CARD_BALANCE_SEQ")
private Long balanceId;
#Column(name="CARD_ID")
private Long cardId;
}
#Entity
#Table(name = "CARDS")
public class Cards implements Serializable {
#Id
#Column(name = "CARD_ID")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "CARDS_SEQ")
#SequenceGenerator(name = "CARDS_SEQ", sequenceName = "CARDS_SEQ")
private Long cardId;
#Column(name = "CARD_NAME", length = 30, unique = true)
private String cardName;
#Column(name="PERSON_ID")
private Long personId;
#Column(name = "CARD_KEY", nullable = false)
private long cardKey;
#OneToOne
#JoinColumn(name="TYPE_ID", nullable = false)
private TypeCard typeCard;
#OneToOne
#JoinColumn(name="CARD_ID", nullable = false)
private CardBalance cardBalance;
#OneToMany(fetch = FetchType.LAZY)
#JoinColumn(name="CARD_ID")
public Set<BalanceHist> balanceHists = new HashSet<>();
#OneToMany(fetch = FetchType.LAZY)
#JoinColumn(name="CARD_ID")
public Set<Events> events = new HashSet<>();
}
but it does't work. How I can solve this problem?
First of all, you have a mistake in your #JoinColumn, it should be:
#OneToOne
#JoinColumn(name="BALANCE_ID", nullable = false)
private CardBalance cardBalance;
I'm having two entities Car and CarDescription where CarDescription is depending on another foreign key from the table Language.
What I' trying to accomplish is to have a HashMap in Car such that whenever I'm having a Car entity-object I am able to access all descriptions from the language id.
Entity Car.java
#Entity
#Table(name = "Car")
public class Car extends AbstractTimestampEntity implements Serializable {
private static final long serialVersionUID = -5041816842632017838L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name = "ID", unique = true, nullable = false)
private Long id;
#OneToMany(mappedBy="car")
#MapKeyColumn(name = "language_ID")
// #MapKey(name = "language") // does not work either
private Map<Long, CarDescription> carDescription = new HashMap<>(0);
}
Entity CarDescription.java
#Entity
#Table( name="car_description",
uniqueConstraints = {
#UniqueConstraint(columnNames={"language_id", "name"})
}
)
public class CarDescription extends AbstractTimestampEntity implements Serializable {
private static final long serialVersionUID = 2840651722666001938L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name = "ID", unique = true, nullable = false)
private Long id;
#NotNull
#ManyToOne
private Car car;
#NotNull
#OneToOne
private Language language;
// ..
}
Entity Language.java
#Entity
public class Language implements Serializable {
private static final long serialVersionUID = 3968717758435500381L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="ID")
private Long id;
// ..
}
The problem I am having is that the mapping gives me a map from each CarDescription.id to CarDescription.
How can I accomplish a correct mapping?
In CarDescription you need to add the languageId property:
#Column(name = "language_id", insertable = false, updatable = false)
private Long languageId;
#NotNull
#OneToOne
#JoinColumn(name = "language_id")
private Language language;
public void setLanguage(Language language) {
this.languageId = language.getId();
this.language = language;
}
Then you can use it in the Car entity like this:
#OneToMany(mappedBy="car")
#MapKey(name = "languageId")
private Map<Long, CarDescription> carDescription = new HashMap<>(0);
This are my entities:
public class Account extends AbstractEntity<Long> {
#Id
#SequenceGenerator(name = "accountSequence", sequenceName = "SQ_ACCOUNTS", allocationSize = 1)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "accountSequence")
#Column(name = "ACC_ID", nullable = false)
private Long id;
...
}
public class Integration extends AbstractEntity<Long> {
#Id
#SequenceGenerator(name = "integrationSequence", sequenceName="SQ_INTEGRATIONS", allocationSize = 1)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "integrationSequence")
#Column(name = "INT_ID", nullable = false)
private Long id;
...
public void addIntegration(Integration integration) {
IntegrationAccount association = new IntegrationAccount();
// This does not help
//association.setIntAccountsPK(new IntAccountsPK(integration.getId(), this.getId()));
association.setAccount(this);
association.setIntegration(integration);
this.integrationAccounts.add(association);
integration.getIntAccountsCollection().add(association);
}
}
And this is entity for join table
#Entity
#Table(name = "INT_ACCOUNTS")
public class IntegrationAccount {
#EmbeddedId
protected IntAccountsPK intAccountsPK;
#JoinColumn(name = "ACC_ID", referencedColumnName = "ACC_ID", insertable = false, updatable = false)
#ManyToOne
private Account account;
#JoinColumn(name = "INT_ID", referencedColumnName = "INT_ID", insertable = false, updatable = false)
#ManyToOne
private Integration integration;
...
}
#Embeddable
public class IntAccountsPK implements Serializable {
#Column(name = "INT_ID", nullable = false)
private Long intId;
#Column(name = "ACC_ID", nullable = false)
private Long accId;
...
}
And when i do:
account.addIntegrations(integrations.getTarget());
account.setCustomer(customer);
accountService.save(account);
I got this in my log
Caused by: org.hibernate.id.IdentifierGenerationException: null id generated for:class com.dhl.dcc.domain.IntegrationAccount
I dont have many knowledge about this kind of mapping, can you please tell me how to improve this mapping (entity for join table have to be preserved) and how to save account with related integrations? Thanks.
I know this question has already been marked as solved but I disagree with the accepted answer. This answer modifies the datamodel by adding a useless column (the new id) in the table INT_ACCOUNTS. There is another way to solve this problem in Hibernate without modifying the datamodel :
#Entity
#Table(name = "INT_ACCOUNTS")
public class IntegrationAccount implements Serializable {
#Id
#ManyToOne
#JoinColumn(name = "INT_ID_FK")
private Integration integration;
#Id
#ManyToOne
#JoinColumn(name = "ACC_ID_FK")
private Account account;
}
#Entity
#Table(name = "INTEGRATIONS")
public class Integration {
#Id
#SequenceGenerator(name = "integrationSequence", sequenceName = "SQ_INTEGRATIONS", allocationSize = 1)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "integrationSequence")
#Column(name = "INT_ID")
private Long id;
}
#Entity
#Table(name = "ACCOUNTS")
public class Account {
#Id
#SequenceGenerator(name = "accountSequence", sequenceName = "SQ_ACCOUNTS", allocationSize = 1)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "accountSequence")
#Column(name = "ACC_ID")
private Long id;
}
You could create a ID field for your IntegrationAccount and then create a unique constraint for your two fields.
#Entity
#Table(name = "INT_ACCOUNTS",
uniqueConstraints=#UniqueConstraint(columnNames={"ACC_ID", "INT_ID"}))
public class IntegrationAccount {
#Id
private Long id;
#JoinColumn(name = "ACC_ID", referencedColumnName = "ACC_ID", insertable = false, updatable = false)
#ManyToOne
private Account account;
#JoinColumn(name = "INT_ID", referencedColumnName = "INT_ID", insertable = false, updatable = false)
#ManyToOne
private Integration integration;
...
}
Works like a charm!