Basically I want to refer the start city and end city to Bay object. Which is already created.
Table got crated .....But I can find only one bay field. And while saving
19:14:52,723 DEBUG [SqlExceptionHelper] could not execute statement [n/a]
org.postgresql.util.PSQLException: ERROR: null value in column "bay" violates not-null constraint
Detail: Failing row contains (3, 0, null, null, null, null).
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2270)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1998)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:255)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:570)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:420)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:366)
at org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:102)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:186)
Generated Table :
CREATE TABLE iot.vehicle
(
vehicle_id integer NOT NULL,
cost bigint,
endtime timestamp without time zone,
satrttime timestamp without time zone,
vehicletype integer,
bay integer NOT NULL,enter code here
CONSTRAINT vehicle_pkey PRIMARY KEY (vehicle_id),
CONSTRAINT fk_1w93t3827hqk1dji0s585ocf1 FOREIGN KEY (bay)
REFERENCES iot.bay (bay_id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
}
public class Vehicle {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name = "VEHICLE_ID")
private int vehicleId;
#ManyToOne(cascade = CascadeType.ALL, fetch=FetchType.EAGER)
#JoinColumn(name="BAY", nullable = false, insertable = false, updatable = false)
private Bay startCity;
#ManyToOne(cascade = CascadeType.ALL, fetch=FetchType.EAGER)
#JoinColumn(name="BAY", nullable = false, insertable = false, updatable = false)
private Bay endCity;
#Column(name = "SATRTTIME")
private Date startTime;
#Column(name = "ENDTIME")
private Date endTime;
#Column(name = "COST")
private long cost;
#Column(name = "VEHICLETYPE")
private TranportType vehicleType;
}
public class Bay {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name = "BAY_ID")
private int bayId;
#Column(name = "COUNTRY", nullable = false)
String country;
#Column(name = "CITINAME", nullable = false)
String citiName;
#Column(name = "BAYTYPE")
TranportType bayType;
//getters/setters
}
When you persist Vehicle, you obviously don't set the bay value (startCity and endCity).
And don't give them the same name:
#JoinColumn(name="...") //<- change name attribute here
Related
I am creating entity relationships in Spring Boot data JPA. Since those tables being legacy I am not able to modify or add columns. Issue is I am getting error if point part of embedded Id.
My entity classes looks like below:
Class Customer {
#EmbededId
private CustomerPk id;
#Column("NAME")
private String name;
#OneToMany(fetch=FetchType.LAZY, cascade=CascadeType.ALL, mappedBy="customerDetails")
private List<Purchase> purchaseDetails;
...
}
#Embeddable
Class CustomerPk {
#Column("CUSTOMER_ID")
private String customerId
#Column("PURCHASE_ID")
private String productId;
#Column("PURCHASE_DATE")
private String date;
}
Purchase Entity looks like below:
Class Purchase {
#EmbededId
private PurchasePK id;
#Column("TRANSACTION_NAME")
private String transactionName;
#ManyToOne(fetch=FetchType.LAZY, cascade=CascadeType.ALL)
#JoinColumns({
#JoinColumn(name="CUSTOMER_ID" referencedColumnName="CUSTOMER_ID")
#JoinColumn(name="PURCHASE_ID" referencedColumnName="PURCHASE_ID")
)}
private Customer customerDetails;
...
}
#Embeddable
Class PurchasePK {
#Column("CUSTOMER_ID")
private String customerId
#Column("PURCHASE_ID")
private String productId;
#Column("TRANSACTION_DATE")
private String date;
}
With above structure I am getting org.hibernate.AnnotationException: referencedColumnNames(CUSTOMER_ID, PURCHASE_ID) of Purchase.customerDetails referencing Customer not mapped to a single property.
If I remove date property from CustomerPK, I am able to make the server up. But with current requirement I need date to be part of the CustomerPK class.
I think if I use part of the composite key as Join Columns I am getting this error.
Working version:
#Entity
public class Customer {
#EmbeddedId
private CustomerPk id;
#Column(name = "NAME")
private String name;
#OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "customerDetails")
private List<Purchase> purchaseDetails;
}
#Embeddable
public class CustomerPk implements Serializable {
#Column(name = "CUSTOMER_ID")
private String customerId;
#Column(name = "PURCHASE_ID")
private String productId;
#Column(name = "PURCHASE_DATE")
private String date;
}
#Entity
public class Purchase {
#EmbeddedId
private PurchasePK id;
#Column(name = "TRANSACTION_NAME")
private String transactionName;
#ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumns({
#JoinColumn(name = "CUSTOMER_ID", referencedColumnName = "CUSTOMER_ID", insertable = false, updatable = false),
#JoinColumn(name = "PURCHASE_ID", referencedColumnName = "PURCHASE_ID", insertable = false, updatable = false),
#JoinColumn(name = "PURCHASE_DATE", referencedColumnName = "PURCHASE_DATE", insertable = false, updatable = false)
})
private Customer customerDetails;
}
#Embeddable
public class PurchasePK implements Serializable {
#Column(name = "CUSTOMER_ID")
private String customerId;
#Column(name = "PURCHASE_ID")
private String productId;
#Column(name = "TRANSACTION_DATE")
private String date;
}
Conclusion:
The provided information from #Ray was valid, you missed adding the required join columns to represent the full entity relation, regarding your note for the same #Ray point, yes you are right both columns usage is different but also both columns have their own name which it will not override any row value on runtime.
The result of the above tables and representation is as follows:
create table customer
(
customer_id varchar(255) not null,
purchase_date varchar(255) not null,
purchase_id varchar(255) not null,
name varchar(255),
primary key (customer_id, purchase_date, purchase_id)
);
create table purchase
(
customer_id varchar(255) not null,
transaction_date varchar(255) not null,
purchase_id varchar(255) not null,
transaction_name varchar(255),
purchase_date varchar(255),
primary key (customer_id, transaction_date, purchase_id)
);
alter table purchase
add constraint FK6rkrb8rq8x56kai7g5gm32d1y foreign key (customer_id, purchase_date, purchase_id) references customer;
I have this table and, as the code shows, I have marked columns "cnpj, product, proposalNumber" as a unique composed constraint:
#Table(name = "Proposal", uniqueConstraints = {#UniqueConstraint(columnNames = {"cnpj", "product", "proposalNumber"})})
public class Proposal {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", unique = true, updatable = false, insertable = false)
#JsonProperty("id")
private Long id;
#JsonProperty("cnpj")
#Column(name = "cnpj", nullable = false, length = 14)
private String cnpj;
#JsonProperty("proposalNumber")
#Column(name = "proposalNumber", nullable = false)
private String proposalNumber;
#JsonProperty("product")
#Column(name = "product", nullable = false, length = 100)
private String product;
#JsonProperty("price")
#Column(name = "price", nullable = false)
private BigDecimal price;
#JsonProperty("dueDate")
#Column(name = "dueDate", nullable = false)
private String dueDate;
#JsonProperty("qtyLife")
#Column(name = "qtyLife", nullable = false)
private Integer qtyLife;
#JsonIgnore
#Column(name = "active", nullable = false)
private Boolean active = true;
...
But, checking the DDL or DUMP ain't no unique information...
CREATE TABLE `proposal` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`active` bit(1) NOT NULL,
`cnpj` varchar(14) NOT NULL,
`due_date` varchar(255) NOT NULL,
`price` decimal(19,2) NOT NULL,
`product` varchar(100) NOT NULL,
`proposal_number` varchar(255) NOT NULL,
`qty_life` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
In addition to this, writing #Column(unique = true) on the column does not solve the problem either, it creates the unique constraint in the database but only referencing that single column, not the composition (cnpj, product and proposalNumber).
Any tips?
The problem is solved: nothing wrong with my solution, but I had to change my spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect to spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
I am trying to do one to many association by a non primary key of the parent. I am using JPA 2.1 with hibernate. I have found several similar questions. But i think my case is a bit different.
I have two table :
ProfileBasic and Phonenumber.
#Entity
public class ProfileBasic {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "profile_id")
private Long id;
//....some columns.
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
#JoinColumn(name = "profile_id")
private List<PhoneNumber> phone_number;
// getters-setters
}
public class PhoneNumber implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
// getters-setters and other columns
}
Database tables :
CREATE TABLE `profilebasic` (
`profile_id` bigint(20) NOT NULL,
`available` varchar(255) DEFAULT NULL,
`birth_date` varchar(255) DEFAULT NULL,
`blood_Group` varchar(255) DEFAULT NULL,
`care_of` varchar(255) DEFAULT NULL,
`email` varchar(255) DEFAULT NULL,
`gender` varchar(255) DEFAULT NULL,
`marital_status` varchar(255) DEFAULT NULL,
`name` varchar(255) DEFAULT NULL,
`profession` varchar(255) DEFAULT NULL,
`religion` varchar(255) DEFAULT NULL,
`user_id` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Indexes for table `profilebasic`
--
ALTER TABLE `profilebasic`
ADD PRIMARY KEY (`profile_id`);
CREATE TABLE `phonenumber` (
`id` bigint(20) NOT NULL,
`number` varchar(255) DEFAULT NULL,
`profile_id` bigint(20) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Indexes for table `phonenumber`
--
ALTER TABLE `phonenumber`
ADD PRIMARY KEY (`id`),
ADD KEY `FK8sfxu3ejjpklkd3njt3767ape` (`profile_id`);
--
-- Constraints for table `phonenumber`
--
ALTER TABLE `phonenumber`
ADD CONSTRAINT `FK8sfxu3ejjpklkd3njt3767ape` FOREIGN KEY (`profile_id`) REFERENCES `profilebasic` (`profile_id`);
I have other tables and have made several views from those tables, where some cases profile_id is the Primary Key on those view. I have done successfully one to many association from views, where primary key is profile_id. But i have a view, where profile_id is not PK, as a result in time of fetching, it is generating right query but with wrong value.
Hibernate: select phone_numb0_.profile_id as profile_3_18_0_, phone_numb0_.id as id1_18_0_, phone_numb0_.id as id1_18_1_, phone_numb0_.number as number2_18_1_ from PhoneNumber phone_numb0_ where phone_numb0_.profile_id=?
2020-08-23 04:00:48.396 TRACE 9292 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [BIGINT] - [21451]
Here parameter [1] as [BIGINT] - [21451] is the wrong value : PK of the view, where right value will be 1134. But as i told earlier, this is working where the primary key of the view is profile_id.
I have seen several questions in stackoverflow. Now i want to know : is there any way by which i can associate the phone number by one-to-many, where profile_id is not PK. If it is not possible, i have to read the phone number for each row of the views.
View Entity :
#Entity
#Table(name = "donner_assing_show")
public class DonnerAssingShow implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#Column(name = "donner_assingment_id")
private long donnerAssingmentId;
#Size(max = 255)
#Column(name = "agent_id")
private String agentId;
#Size(max = 255)
#Column(name = "donner_id")
private String donnerId;
#Size(max = 255)
#Column(name = "assing_date")
private String assingDate;
#Lob
#Size(max = 2147483647)
#Column(name = "assing_note")
private String assingNote;
#Size(max = 255)
#Column(name = "need_date")
private String needDate;
#Size(max = 255)
#Column(name = "post_id")
private String postId;
#Size(max = 255)
#Column(name = "blood_manage_status")
private String bloodManageStatus;
#Basic(optional = false)
#NotNull
#Column(name = "profile_id")
private long profileId;
#Size(max = 255)
#Column(name = "available")
private String available;
#Size(max = 255)
#Column(name = "birth_date")
private String birthDate;
#Size(max = 255)
#Column(name = "blood_Group")
private String bloodGroup;
#Size(max = 255)
#Column(name = "care_of")
private String careOf;
// #Pattern(regexp="[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?", message="Invalid email")//if the field contains email address consider using this annotation to enforce field validation
#Size(max = 255)
#Column(name = "email")
private String email;
#Size(max = 255)
#Column(name = "gender")
private String gender;
#Size(max = 255)
#Column(name = "marital_status")
private String maritalStatus;
#Size(max = 255)
#Column(name = "name")
private String name;
#Size(max = 255)
#Column(name = "profession")
private String profession;
#Size(max = 255)
#Column(name = "religion")
private String religion;
#Size(max = 255)
#Column(name = "user_id")
private String userId;
#OneToMany
// #OneToMany(fetch = FetchType.EAGER)
#LazyCollection(LazyCollectionOption.FALSE)
#JoinColumn(name = "profile_id")
private List<PhoneNumber> phone_number;
// #OneToMany
#OneToMany(fetch = FetchType.EAGER)
// #LazyCollection(LazyCollectionOption.FALSE)
#JoinColumn(name = "profile_id")
private List<Address> addressList;
// constructor-getter/setters
}
GitHub Link of the project where stacked
Unit Test of the code
Dump Data of the project
The join column is not required to be part of the primary key, or using the same column name in both tables. You can specify which column you want to join by using "referenceColumnName".
#Entity
public class ProfileBasic
{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "profile_id")
private Long id;
//....some columns.
#OneToMany(cascade = CascadeType.ALL, mappedBy = "profile", orphanRemoval = true)
private List<PhoneNumber> phone_number;
// getters-setters
}
public class PhoneNumber implements Serializable
{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name = "profile_id")
#JoinColumn(name = "profile_id", referencedColumnName = "profile_id", nullable = false)
private ProfileBasic profile;
// getters-setters
}
You should correct your mapping in this way:
#Entity
public class ProfileBasic {
//....some columns.
#OneToMany(cascade = CascadeType.ALL, mappedBy = "profile", orphanRemoval = true)
private List<PhoneNumber> phoneNumbers;
}
#Entity
public class PhoneNumber implements Serializable {
// getters-setters and other columns
#ManyToOne
#JoinColumn(name = "profile_id", nullable = false)
private ProfileBasic profile;
}
Comments:
The #JoinColumn annotation should be used on side that owns foreign key column (this is PhoneNumber in your case).
It is not necessary to use the referencedColumnName when the FK refereed to the PK column.
It is good to follow java naming conventions. So, it is better to use phoneNumbers as a property name instead of phone_number.
I trying to map my class to database,the class reference to itself by "id_comment_parent", but when running a test, I get the following error:
Caused by: org.hibernate.AnnotationException: A Foreign key refering com.ecommerce.entities.Comment from com.ecommerce.entities.Comment has the wrong number of column. should be 2
at org.hibernate.cfg.annotations.TableBinder.bindFk(TableBinder.java:646) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
at org.hibernate.cfg.ToOneFkSecondPass.doSecondPass(ToOneFkSecondPass.java:102) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processEndOfQueue(InFlightMetadataCollectorImpl.java:1814) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
these is my classe:
#Entity
#Table(name = "comment", catalog = "Ecommerce_db")
public class Comment implements Serializable {
#EmbeddedId
#AttributeOverrides({
#AttributeOverride(name = "idComment", column = #Column(name = "id_comment", nullable = false)),
#AttributeOverride(name = "idCommentParent", column = #Column(name = "id_comment_parent", nullable = false)) })
private CommentId id;
#Column(name = "id_user", nullable = false)
private long idUser;
#Column(name = "comment", length = 65535)
private String comment_1;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "id_comment_parent", nullable = false, insertable = false, updatable = false)
private Comment comment;
}
anyone have any idea?
Looks like CommentId that represents de Primary Key of Commenthas more that one column. So the ForeignKey must have more than one JoinColumn too.
Besides, it seems that you are mixing the fields of your primary key and your foreign key, as you have id_comment_parent in both primary key and foreign key.
You actually have comment entities with the same id_comment but with different id_comment_parent? It that's not the case, I think that a more coherent mapping would be that id_comment is the primary key, and id_comment_parent is the foreing key. Something like this:
#Entity
#Table(name = "comment", catalog = "Ecommerce_db")
public class Comment implements Serializable {
#Id
#Column(name = "id_comment", nullable = false)
private Long id;
#Column(name = "id_user", nullable = false)
private long idUser;
#Column(name = "comment", length = 65535)
private String comment_1;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "id_comment_parent")
private Comment parent;
}
I want to use custom sequence(orderId_seq) while saving my entity instead of default one(hibernate_sequence) in postgres-9.5.
My entity is :
#Entity
#Table(name="orders")
public class Order {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "orderId_generator")
#SequenceGenerator(name="orderId_generator", sequenceName = "orderId_seq")
#Column(updatable = false, nullable = false)
private Long orderId;
#Column(columnDefinition = "uuid",nullable = false)
#Type(type="pg-uuid")
private UUID userId;
private String comments;
private String assignedTo;
#Enumerated(EnumType.STRING)
#Column(nullable = false)
private OrderStatus status;
#Column(nullable = false, updatable = false, insertable = false,
columnDefinition = "TIMESTAMP with time zone DEFAULT CURRENT_TIMESTAMP")
private Timestamp orderedDate;
//getters and setters
when I save this entity to the database. It is generating some random number for orderId instead of using orderId_seq.
When I check the order entity in debug mode before saving it is null but after saving it is creating some random number not even using hibernate_sequence.
And when I use show_sql=true option in hibernate it is even showing the following statement in the console :
Hibernate:
select
nextval ('orderId_seq')
How can I resolve this issue?