I have a small project Java Spring Boot, i use Annotation to create field and Table in MySQL, i want to add some other field in a middle table "candidate_tets" to store some other field, then i create a class "CandidateTest". But when i add annotation #Id and #GeneratedValue(strategy = GenerationType.IDENTITY) in var "id", i have a problem, that the AutoIncrement in MySQL and PRIMARY KEY isn't set to column id in MySQL, i don't know the problem in here
this is my Candidate class
#Entity
#Table(name = "candidate")
#SuppressWarnings("serial")
public class Candidate implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column
private int id;
#Column
private String name;
#Column(nullable = true)
private int level; // 1 Fresher, 2 Junior, 3 Senior
#Column(unique = true)
private String phone;
#Column(unique = true)
private String email;
#Column(nullable = true)
private String position;// Vi tri ???
#Column(name = "english_mark", columnDefinition = "DOUBLE DEFAULT 0")
private Double englishMark;
#Column(name = "coding_mark", columnDefinition = "DOUBLE DEFAULT 0")
private Double codingMark;
#Column(name = "knowledge_mark", columnDefinition = "DOUBLE DEFAULT 0")
private Double knowledgeMark;
#Column(name = "date_test")
#DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss", iso = ISO.DATE_TIME)
#JsonFormat(shape=JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime dates;
#Column(name = "is_done", columnDefinition = "INT DEFAULT 0")
private int isDone;
#ManyToMany(fetch = FetchType.EAGER)
#Cascade(org.hibernate.annotations.CascadeType.SAVE_UPDATE)
#JoinTable(name = "candidate_Test", joinColumns = {#JoinColumn(name = "id_candidate")},
inverseJoinColumns = {#JoinColumn(name = "id_test")})
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
private Set<Test> tests = new HashSet<>();
#Column
private String avatar;
//Constructor , Getter and Setter ...
}
this is test class:
#Entity
#Table(name = "test")
#JsonIgnoreProperties({"hibernateLazyInitializer"})
#SuppressWarnings("serial")
public class Test implements Serializable{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column
private int id;
#Column
private int subject;
#Column
private int level;
#Column(name = "time")
#DateTimeFormat(pattern = "HH:mm:ss", iso = ISO.TIME)
#JsonFormat(shape = JsonFormat.Shape.STRING,pattern = "HH:mm:ss")
private LocalTime times;
#Column
private String name;
#Column(name = "code_test", unique = true)
#GeneratedValue(strategy = GenerationType.SEQUENCE)
private String codeTest;
#ManyToMany
#JsonIgnore
#JoinTable(name = "candidate_Test", joinColumns = {#JoinColumn(name = "id_test")}, inverseJoinColumns = {#JoinColumn(name = "id_candidate")})
private List<Candidate> candidates = new ArrayList<>();
#ManyToMany(fetch = FetchType.EAGER)
#JoinTable(name = "test_question",
joinColumns = {#JoinColumn(name = "id_test")}, inverseJoinColumns = {#JoinColumn(name = "id_question")})
private Set<Question> questions = new HashSet<>();
//Getter and Setter ...
this is candidate_test class:
#Entity
#SuppressWarnings("serial")
#Table(name = "candidate_test")
public class CandidateTest implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column
private int id;
#Column(name = "id_candidate")
private int candidateId;
#Column(name = "id_test")
private int testId;
#Column(name = "marks", columnDefinition = "DOUBLE DEFAULT 0")
private Double marks;
//Getter and Setter ....
file application.properties
spring.datasource.url = jdbc:mysql://db:3306/testingonline?zeroDateTimeBehavior=convertToNull&autoReconnect=true&useUnicode=yes&characterEncoding=UTF-8
spring.datasource.username= root
spring.datasource.password= 123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.hibernate.use-new-id-generator-mappings= false
spring.mvc.pathmatch.matching-strategy=ant-path-matcher
springdoc.api-docs.path=/api-docs
spring.mvc.pathpattern.matching-strategy=ant_path_matcher
spring.jackson.serialization.write-dates-as-timestamps=false
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect```
this is MySQL table *candidate_test* and the problem
![enter image description here](https://i.stack.imgur.com/2SWKW.png)
Can you guys give me the reason why the AutoIncrement and PRIMARY KEY is not set in this middle table
I think it is because of the Serializable interface try removing that and then re-execute it should work.
Related
I am getting Data from MySql using Spring Data JPA. I getting this error when I am passing provider as 1465 in request.
I have tried Sending Set from the request as well.
My calling code is :
offerList = blackholeDetailRepository.findByProductVMS(ProductType.VMS, blackholeID,
pricingCopyRequestBO.getProviderId().longValue(),
OfferGradeConstant.fromString(pricingCopyRequestBO.getOfferGrade()));
Code in repository is :
#Query("SELECT detail FROM #{#entityName} AS detail JOIN FETCH detail.vmsRestrictedProviders AS provider "+
"WHERE detail.product = :product " + "AND detail.master.id= :masterId "
+ "AND detail.vmsRestrictedProviders = :providerId " + "AND provider.offerGrade= :offerGrade")
Set<BlackholeDetailEntity> findByProductVMS(#Param("product") ProductType product, #Param("masterId") Long masterId,
#Param("providerId") Long providerId, #Param("offerGrade") OfferGradeConstant offerGrade);
BlackholeDetailEntity Entity is :
#Entity
#Table(name = "blackhole_detail")
#Data
#EqualsAndHashCode(callSuper = true)
public class BlackholeDetailEntity extends PolygonDetailEntity {
private static final long serialVersionUID = 1L;
#ElementCollection(fetch = FetchType.EAGER)
#CollectionTable(name = "blackhole_entity_mapping",
joinColumns = #JoinColumn(name = "detail_id", referencedColumnName = "id"))
#Column(name = "entity_id")
private Set<Integer> entities;
#Convert(converter = CsvStringSetConverter.class)
private Set<String> restrictedOffers;
#Convert(converter = CsvLongSetConverter.class)
#Column(name = "ll_me_restricted_providers", columnDefinition = "text")
private Set<Long> llMERestrictedProviders;
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL,
orphanRemoval = true, mappedBy = "blackHole")
private Set<VmsProviderRestrictionEntity> vmsRestrictedProviders;
#Column(name = "is_restrict_all")
private Boolean restrictAll;
}
VmsProviderRestrictionEntity is :
#Data
#Entity
#ToString(exclude = {"blackHole"})
#EqualsAndHashCode(exclude = "blackHole")
#Table(name = "vms_provider_blackhole_restriction")
public class VmsProviderRestrictionEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Enumerated(EnumType.STRING)
private OfferGradeConstant offerGrade;
#Convert(converter = CsvLongSetConverter.class)
#Column(name = "vms_restricted_providers", columnDefinition = "text")
private Set<Long> providerIds;
#ManyToOne
#JoinColumn(name = "blackhole_id")
private BlackholeDetailEntity blackHole;
}
PolygonDetailEntity.java
#MappedSuperclass
#Data
#ToString(exclude = {"master","masterPricing"})
#EqualsAndHashCode(callSuper = false, exclude = {"master", "masterPricing"})
public class PolygonDetailEntity extends ModifiableAuditableEntity {
private static final long serialVersionUID = -9100537914314976516L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToOne
#JoinColumn(name = "master_id")
private PolygonMasterEntity master;
#ManyToOne
#JoinColumn(name = "master_pricing_id")
private PolygonMasterPricingEntity masterPricing;
#Enumerated(EnumType.STRING)
private ProductType product;
private Integer serviceId;
#Column(columnDefinition = "text")
private String comments;
private String accessTechnology;
#Column(name = "is_active")
private Boolean active;
#Column(name = "is_deleted")
private Boolean deleted;
}
I have a entity bean with a relation #ManyToOne that is in join on one column.
#Entity
#Table(name = "work_order")
public class WorkOrder implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
#SequenceGenerator(name = "sequenceGenerator")
private Long id;
#NotNull
#Column(name = "id_order", nullable = false)
private String idOrder;
#Column(name = "description")
private String description;
#Enumerated(EnumType.STRING)
#Column(name = "status")
private StatusOrder status;
#Column(name = "creation_date")
private Instant creationDate;
#Column(name = "closing_date")
private Instant closingDate;
#Column(name = "client_id")
private Long clientId;
#ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST) #NotFound (action = NotFoundAction.IGNORE)
#Fetch(FetchMode.JOIN)
#JoinColumn(name = "account", insertable = false, updatable = false, nullable = true)
private AnagraficaClienti account;
And the second Entity
#Entity
#Table(name = "es_account")
public class AnagraficaClienti implements Serializable {
private static final long serialVersionUID = 1L;
// da rimettere a #NotNull
#Column(name = "fk_cod_azienda", nullable = true)
private String fk_cod_azienda;
#Id
#NotNull
#Column(name = "account", nullable = false)
private String account;
// da rimettere a #NotNull
#Column(name = "tipo_cli_for", nullable = true)
private String tipoClienteFornitore;
#Column(name = "tipo_account", nullable = true)
private String tipoAccount;
....
The "es_account" table has three not nullable primary key(fk_cod_azienda, account, tipo_cli_for) and the relation with the "work_order" table is by account column.
My problem is that sometimes it is possible that the user insert or update WorkOrder with a null account value and that is not avoid by AnagraficaClienti entity because it expects a non null(and not duplicate) value.
Are there any possible way to bypass the join with AnagraficaClienti when account is null?
In my point of view, #ManyToOne is violate OOP design principle due to the creation of redundant relation. Instead, i always create a #OneToMany relation with a list of related entities. To specify the relation as nullable, just add the nullable=true property in #JoinColumn. With #ManyToOne, you must specify property optional=true. Lets try and see if it works.
WorkOrder
#Entity
#Table(name = "work_order")
public class WorkOrder implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
#SequenceGenerator(name = "sequenceGenerator")
private Long id;
#NotNull
#Column(name = "id_order", nullable = false)
private String idOrder;
#Column(name = "description")
private String description;
#Enumerated(EnumType.STRING)
#Column(name = "status")
private StatusOrder status;
#Column(name = "creation_date")
private Instant creationDate;
#Column(name = "closing_date")
private Instant closingDate;
#Column(name = "client_id")
private Long clientId;
AnagraficaClienti
#Entity
#Table(name = "es_account")
public class AnagraficaClienti implements Serializable {
private static final long serialVersionUID = 1L;
// da rimettere a #NotNull
#Column(name = "fk_cod_azienda", nullable = true)
private String fk_cod_azienda;
#Id
#NotNull
#Column(name = "account", nullable = false)
private String account;
// da rimettere a #NotNull
#Column(name = "tipo_cli_for", nullable = true)
private String tipoClienteFornitore;
#Column(name = "tipo_account", nullable = true)
private String tipoAccount;
#OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE} )
#JoinColumn(name = "account", nullable = true)
private List<WorkOrder> workOrders;
When you want to insert the work order to the database:
workOrderRepository.save(workOrder);
When you want to create the relationship:
AnagraficaClienti client = anagraficaClientiRepository.findById(...);
client.getWorkOrders().add(newWorkOrder);
I am trying to parse a web request and save to database. I have 3 models and first node is virtualDocument. This is the uniq table (according to request url). VirtualRequest table has all erquest bodies and HttpHeaderList table has all thhp headers according to their virtualRequest bean id.
when I tried to save the first log I got and error like this;
org.h2.jdbc.JdbcSQLException: Referential integrity constraint violation: "FK1TW2G47F7A47580KQVMDJWGBQ: PUBLIC.T_VIRTUAL_REQUEST FOREIGN KEY(REQUEST_ID) REFERENCES PUBLIC.T_VIRTUAL_DOCUMENT(DOCUMENT_ID) (65)"; SQL statement:
insert into t_virtual_request (request_id, media_type, method_type, request_url) values (null, ?, ?, ?) [23506-192]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:345) ~[h2-1.4.192.jar:1.4.192]
here is VirtualDocument bean
#Entity
#Table(name = "t_virtual_document")
public class VirtualDocument {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "document_id")
private long documentId;
#Column(name = "real_url", unique = true)
private String realURL; //uniq
#Column(name = "virtual_url", unique = true)
private String virtualURL; //uniq
#Column(name = "simulation_mode", columnDefinition = "varchar(10) default 'STOP'")
private String simulationMode;
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "request_id")
private List<VirtualRequest> requestList;
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "response_id")
private List<VirtualResponse> responseList;
//getter setter without any annotation
}
here is VirtualRequest bean;
#Entity
#Table(name = "t_virtual_request")
public class VirtualRequest {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "request_id")
private long requestId;
#Column(name = "request_url")
private String requestURL;
#Column(name = "method_type")
private String methodType;
#Column(name = "media_type")
private String mediaType;
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "header_id")
private List<HttpHeaderList> requestHeaders;
//getter setter without any annotation
}
here is HeaderList bean;
#Entity
#Table(name = "t_http_headers")
public class HttpHeaderList {
#Id
#Column(name = "header_id")
private long headerId;
#Column(name = "header_key")
private String headerKey;
#Column(name = "header_value")
private String headerValue;
}
I think this is what you want instead:
#Entity
#Table(name = "t_virtual_document")
public class VirtualDocument {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "document_id")
private long documentId;
#Column(name = "real_url", unique = true)
private String realURL; //uniq
#Column(name = "virtual_url", unique = true)
private String virtualURL; //uniq
#Column(name = "simulation_mode", columnDefinition = "varchar(10) default 'STOP'")
private String simulationMode;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "virtualDocument")
private List<VirtualRequest> requestList;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "virtualDocument")
// Note the mappedBy parameter. This points to the property in the entity that owns the relationship (in this case the VirtualResponse).
private List<VirtualResponse> responseList;
//getter setter without any annotation
}
#Entity
#Table(name = "t_virtual_request")
public class VirtualRequest {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "request_id")
private long requestId;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "document_id")
private VirtualDocument virtualDocument;
#Column(name = "request_url")
private String requestURL;
#Column(name = "method_type")
private String methodType;
#Column(name = "media_type")
private String mediaType;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "virtualRequest")
private List<HttpHeaderList> requestHeaders;
//getter setter without any annotation
}
#Entity
#Table(name = "t_http_headers")
public class HttpHeader { /*Note this is a more appropriate name for the entity since it holds the data of a single header.*/
#Id
#Column(name = "header_id")
private long headerId;
#Column(name = "header_key")
private String headerKey;
#Column(name = "header_value")
private String headerValue;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "request_id")
private VirtualRequest virtualRequest
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "response_id")
private VirtualResponse virtualResponse;
}
Updated the answer to add mapping the headers to the request entity.
I have 4 entities: Play, Actor, Play-representation and Category.
Each play belongs to a category and play-representation associates a play with a theater and a number of actors at a given time.
Here are the entities:
#Entity
#Table(name = "category")
public class Category {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#Column(name = "name")
private String name;
#OneToMany(mappedBy="category")
private List<Play> playList = new ArrayList<Play>();
#Entity
#Table(name = "actor")
public class Actor {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private long id;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
#Column(name = "description")
private String description;
#Column(name = "profile_picture")
private String profilePicturePath;
#ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinTable(name = "play_representation_category",
joinColumns = {#JoinColumn(name = "actor_id")},
inverseJoinColumns = {#JoinColumn(name = "play_representation_id")})
private Set<PlayRepresentation> playRepresentations = new HashSet<>(0);
#Entity
#Table(name = "play")
public class Play {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#NotNull
#Column(name = "name")
private String name;
#NotNull
#Column(name = "description")
private String description;
#Column(name = "image_paths")
private String imagePaths;
#NotNull
#ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private Category category;
#Entity
#Table(name = "play_representation")
public class PlayRepresentation {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "play_id")
private Play play;
#OneToOne
#JoinColumn(name = "theater_id")
private Theater theater;
#Column(name = "date")
private Timestamp airingDate;
#ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinTable(name = "play_representation_category",
joinColumns = {#JoinColumn(name = "play_representation_id", nullable=false)},
inverseJoinColumns = {#JoinColumn(name = "actor_id", nullable=false)})
private Set<Actor> actors = new HashSet<>(0);
The issue I'm having is that hibernate is trying to find a relationship between play_representation and category! I've been trying to persist the relationship for the plays but it seems I got that wrong and can't figure out the best way to do it...It's a postgresql db by the way.
I am still learning, so if you have any other tips regarding the code I've shared, please let me know!
Edit: error is:
org.postgresql.util.PSQLException: ERROR: relation "play_representation_category" does not exist
Position: 281
I didn't need a mappedBy, it was actually a typo - I wrote play_representation_category instead of play_representation_actors. Pretty stupid, huh? At least I finally found it :)
I following have hibernate entities:
#Entity
#Table(name = "News")
public final class News implements Serializable, IEntity {
private static final long serialVersionUID = 3773281197317274020L;
#Id
#SequenceGenerator(name = "NEWS_SEQ_GEN", sequenceName = "NEWS_SEQ")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "NEWS_SEQ_GEN")
#Column(name = "NEWS_ID", precision = 0)
private Long newsId; // Primary key
#Column(name = "TITLE")
private String title;
#Column(name = "SHORT_TEXT")
private String shortText;
#Column(name = "FULL_TEXT")
private String fullText;
#Temporal(TemporalType.DATE)
#Column(name = "CREATION_DATE")
private Date creationDate;
#Temporal(TemporalType.DATE)
#Column(name = "MODIFICATION_DATE")
private Date modificationDate;
#OneToMany(cascade = CascadeType.REMOVE, orphanRemoval = true)
#JoinColumn(name = "NEWS_ID", updatable = false, referencedColumnName = "NEWS_ID")
#OrderBy("creationDate ASC")
private List<Comment> commentsList;
#ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinTable(name = "NEWS_TAG", joinColumns = { #JoinColumn(name = "NEWS_ID") }, inverseJoinColumns = { #JoinColumn(name = "TAG_ID") })
private Set<Tag> tagSet;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinTable(name = "NEWS_AUTHOR", joinColumns = { #JoinColumn(name = "NEWS_ID") }, inverseJoinColumns = { #JoinColumn(name = "AUTHOR_ID") })
private Set<Author> author;
And the second:
#SequenceGenerator(name = "COMMENTS_SEQ", sequenceName = "COMMENTS_SEQ")
#Entity
#Table(name = "Comments")
public class Comment implements Serializable, IEntity {
private static final long serialVersionUID = 3431305873409011465L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "COMMENTS_SEQ")
#Column(name = "COMMENT_ID", precision = 0)
private Long commentId; // Primary key
#Column(name = "NEWS_ID")
private Long newsId;
#NotEmpty
#NotNull
#Column(name = "COMMENT_TEXT")
private String commentText;
#Temporal(TemporalType.DATE)
#Column(name = "CREATION_DATE")
private Date creationDate;
When I'm trying to remove entity News, I get the exception ORA-02292: integrity constraint (ROOT.SYS_C007062) violated - child record found. So, if I remove the property "updatable = false" it tries to set nullable fields into property Comment. What is my mistake? Please, help.
Thanks.
Because your news records have a one to one or one to many relation with comments. You most likely did not specifcy a CACASDE ON DELETE clause while defining your table. in order to delete entity NEWS you have to make sure that all of its related comments records are deleted or are referencing another NEWS record.
basicaly the definition of the ORA 02292 exception.