I have two entities which is giving me error on creation of datasource
Entity1
#NoArgsConstructor
#Entity
#Table(name = "person_details")
public class PersonDetails {
#Id
private String pid;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
#Column(name = "exist_flag")
private String existFlag;
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinColumn(name = "pid", nullable = false)
private List<AddressDetails> addressDetails;
}
Entity 2 | EDIT 1
#Data
#NoArgsConstructor
#Entity
#Table(name = "address_details")
public class AddressDetails {
private String street;
#Column(name = "address_exist_flag")
private String addressExistFlag;
#ToString.Exclude
#EqualsAndHashCode.Exclude
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "pid", insertable = false, updatable = false)
private PersonDetails personDetails;
}
Getting error as below:
I am getting error as "No identifier specified for entity: AddressDetails".
How to resolve in such case? Can we use spring data jpa having OneToMany mapping in such case where one entity do not have primary key ?
The error you are getting is because you are using the same column name for 2 different columns.
#Id
private String pid;
and
#JoinColumn(name = "pid"
means that you want both your id column and your foreign key column to be named "pid", hence the error. I would suggest using a name like "addressDetailsFk" for the JoinColumn attribute.
Related
Using Hibernate, I have created two entities - Employee and EmployeeDetails. Since EmployeeDetails cannot exist without a corresponding entry in Employee, I figured I don't need an extra ID for EmployeeDetails, but could instead use the ID of the Employee entity. Here is how I have implemented this idea:
Employee-Entity:
#Entity
#Table(name = "employees")
#Data
public class Employee {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "employee_id")
private Long id;
#Column(name = "first_name", nullable = false)
private String firstName;
#Column(name = "last_name", nullable = false)
private String lastName;
#OneToOne(cascade = CascadeType.ALL)
EmployeeDetails employeeDetails;
}
Employee-Details-Entity:
#Entity
#Table(name = "employee_details")
#Data
public class EmployeeDetails {
#Id
private Long id;
#Column(name = "address")
private String address;
#Column(name = "e_mail", nullable = false)
private String eMail;
#Column(name = "phone")
private String phone;
#MapsId
#OneToOne(mappedBy = "employeeDetails", cascade = CascadeType.ALL)
#JoinColumn(name = "employee_id")
private Employee employee;
}
By adding the #MapsId annotation to the employee-variable inside EmployeeDetails, I should be assigning the primary key of the Employee-entity to the Id-column of EmployeeDetails.
In a second step, I have written some data into both of my tables.
employee table in MySQL database:
employee_id first_name last_name employee_details_employee_id
1 John Smith null
2 Jennifer Adams null
The last column was somehow generated by Hibernate. I don't understand why. It appears to be some column for identification, but I don't need it.
employee_details table in MySQL database:
employee_id address e_mail phone
1 null john.smith#gmail.com null
2 null jennifer.adams#gmail.com null
I have only assigned an e-mail to the employees. Surprisingly, there is no employee-entry in this database table. I don't really need it anyways, but I was expecting it. So yeah, I think I am doing something terribly wrong and would really appreciate some help.
Change mappedBy side, here useful links
https://vladmihalcea.com/change-one-to-one-primary-key-column-jpa-hibernate/
https://vladmihalcea.com/the-best-way-to-map-a-onetoone-relationship-with-jpa-and-hibernate/
https://javabydeveloper.com/one-one-bidirectional-association/
#Entity
#Table(name = "employees")
#Data
public class Employee {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "employee_id")
private Long id;
#Column(name = "first_name", nullable = false)
private String firstName;
#Column(name = "last_name", nullable = false)
private String lastName;
#OneToOne(mappedBy = "employee", cascade = CascadeType.ALL)
EmployeeDetails employeeDetails;
}
Entity
#Table(name = "employee_details")
#Data
public class EmployeeDetails {
#Id
private Long id;
#Column(name = "address")
private String address;
#Column(name = "e_mail", nullable = false)
private String eMail;
#Column(name = "phone")
private String phone;
#MapsId
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "employee_id")
private Employee employee;
}
#MapId is not a popular solution in work with Hibernate.
Maybe in your case, #Embeddable will be a better option?
If I understand correctly, EmployeeDetails cannot exist without correlated Employee. So, EmployeeDetails could be a field in Employee as an embeddable field:
#Entity
#Table(name = "employees")
#Data
public class Employee {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "employee_id")
private Long id;
#Column(name = "first_name", nullable = false)
private String firstName;
#Column(name = "last_name", nullable = false)
private String lastName;
#Embedded
EmployeeDetails employeeDetails;
}
Then EmployeeDetails doesn't need ID and relation with the employee:
#Embeddable
public class EmployeeDetails {
#Column(name = "address")
private String address;
#Column(name = "e_mail", nullable = false)
private String eMail;
#Column(name = "phone")
private String phone;
}
As you can see, now in the database it's only one table employees, but in our hibernate model, we have two separated objects. Probably you don't need EmployeeDetails without Employee entity, so there is more efficient construction.
If you really need a separated table for EmployeeDetails with relation to Employee I recommend creating standard one-to-one mapping instead of #MapId construction.
I would like to ignore #OnetoMany field in my entity. fetch data need to get actual fields but don't want to fire query to dependent table. But deleting data from parent table needs deletion from dependent table
I have tried #Transient that ignores but the delete is also being ignored. Is there any other option to tell JPA not to fetch data from childs table when i call the parent entity?
#Entity
Table(name = "User")
public class UserEntity implements Serializable {
#Id
#Column(name = "id")
private int id;
#Column(name = "SERIAL", unique = true, nullable = false)
private String serial;
#OneToMany(mappedBy = "serialBySerialId", cascade = CascadeType.ALL)
private Set<UserActionEntity> userActionsById;
}
#Table(name = "user_action")
public class UserActionEntity implements Serializable {
#Id
#Column(name = "id")
private int id;
#Column(name = "action")
private String action;
#ManyToOne
#JoinColumn(name = "USER_ID", referencedColumnName = "ID", nullable = false)
private UserEntity userByUserId;
If you don't want to fire query to dependent table, you can use (fetch = FetchType.LAZY) on UserActionEntity property.
#OneToMany(mappedBy = "serialBySerialId", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Set<UserActionEntity> userActionsById;
i have two tables Person and PersonType and there is a relation "ManyToMany" between these tables. During loading my application i am getting all the PersonTypes, but when i create new Person, i have an exception
org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "person_type_person_type_name_key"
Detail: Key (person_type_name)=(TYPE1) already exists.
person_type_person_type_name_key is my table where i should store the relations between Person and PersonType. When i create a new Person i DO NOT want to insert into PersonType table because the person type already exists. What should i do, not to insert into DB ? I am using personService.save(person); which is trying to insert also in person_type table into DB.
#Table(name = "person")
public class Person {
#Id
#Column(name = "id")
#GeneratedValue(generator = "person_id_seq")
#SequenceGenerator(sequenceName = "person_id_seq", name = "person_id_seq", schema = "manager", allocationSize = 1, initialValue = 1)
private Integer id;
#Column(name = "name")
private String name;
#Column(name = "password")
private String password;
#ManyToMany(cascade = {CascadeType.ALL})
#JoinTable(
name = "person_person_types",
joinColumns = #JoinColumn(name = "person_fk"),
inverseJoinColumns = #JoinColumn(name = "person_type_fk"))
private List<PersonType> personTypes;
}
#Entity
#Table(name = "person_type")
public class PersonType {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Column(name = "person_type_name", unique=true)
private String personType;
#ManyToMany(mappedBy = "personTypes", cascade = {CascadeType.ALL})
private Set<Person> persons;
}```
Maybe the problem is with inserting the PersonType. Ensure that you put PersonType with the same ID and same name into the DB. Also change CascadeType.ALL to be CascadeType.MERGE
The "TypeMismatchException: Provided id of the wrong type" error thrown when tried to merge detached entity. It works if the object wasn't detached. It also works if ids aren't #EmbeddedId.
A sample repo can be found here https://github.com/joes-code/hibernate-map
// Asset.java
#Entity
#Table(name = "asset")
public class Asset {
#EmbeddedId
private AssetId id;
#Column(name = "asset_cost"
private BigDecimal price;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "asset_id", referencedColumnName = "asset_id", nullable = false, insertable = false, updatable = false, foreignKey = #ForeignKey(ConstraintMode.NO_CONSTRAINT))
private AssetDetail assetDetail;
}
// AssetId.java
#Embeddable
public class AssetId {
#Column(name = "asset_id", nullable = false)
private Integer assetId;
}
// AssetDetail.java
#Entity
#Table(name = "asset_detail")
public class AssetDetail {
#EmbeddedId
private AssetDetailId id;
#Column(name = "description", length = 35)
private String description;
}
// AssetDetailId.java
#Embeddable
public class AssetDetailId {
#Column(name = "asset_id", nullable = false)
private Integer assetId;
}
I'm using Hibernate 5.4.3.Final
Any ideas what I did wrong? It seems that Hibernate is assuming Asset and AssetDetail share the same Id class?
I'm having trouble getting a composite primary key and foreign keys working in JPA 2/Hibernate. I'm trying to create a simple scenario with countries and provinces:
Country Entity:
#Entity
#Table(name = "country")
public class Country extends DomainObjectBase implements Serializable {
#Id
#Basic(optional = false)
#Column(name = "code")
private String code;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "country")
private List<Province> provinces;
}
Province Primary Key:
#Embeddable
public class ProvincePK implements Serializable {
#Basic(optional = false)
#Column(name = "code")
private String code;
#Basic(optional = false)
#Column(name = "country_code")
private String countryCode;
}
Province Entity:
#Entity
#Table(name = "province")
public class Province extends DomainObjectBase implements Serializable {
#EmbeddedId
protected ProvincePK provincePK;
#MapsId("country_code")
#JoinColumn(name = "country_code", referencedColumnName = "code", insertable = false, updatable = false)
#ManyToOne(optional = false)
private Country country;
}
This create the correct tables for me with one exception:
Country Table:
code PK
...
Province Table
code PK FK - This is where the problem is its creating a foreign key reference to the country table's code column
country_code FK This is the only foreign key reference I want
...
How do I map my entities/composite key for hibernate to generate the schema I want? Right now I can't insert any data into province because its expecting that country contains the province code!
Thanks for any help.
Try this. I've found that it works for me when I work with data models like this.
#Entity
#Table(name = "province")
#IdClass(ProvincePK.class)
public class Province extends DomainObjectBase implements Serializable {
#Id
#Basic(optional = false)
#Column(name = "code")
private String code;
#Id
#Basic(optional = false, insertable = false, updatable = false)
#Column(name = "country_code")
private String countryCode;
#JoinColumn(name = "country_code", referencedColumnName = "code")
#ManyToOne
private Country country;
}
#MapsID argument must match to the name of attribute in ProvincePK class. #JoinColumn should be marked insertable=true,updatable=true, then it works. Here is the code -
#Entity
#Table(name = "province")
public class Province implements Serializable {
#EmbeddedId
protected ProvincePK provincePK;
#MapsId(value = "country_code")
#JoinColumn(name = "country_code", referencedColumnName = "code")
#ManyToOne(optional = false)
private Country country;
}
#Embeddable
public class ProvincePK implements Serializable {
#Basic(optional = false)
#Column(name = "code")
private String code;
#Basic(optional = false)
#Column(name = "country_code")
private String country_code;
}
#Entity
#Table(name = "country")
public class Country implements Serializable {
#Id
#Basic(optional = false)
#Column(name = "code")
private String code;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "country")
private List<Province> provinces;
}
Hope it helps.