I have problem with cascade save of related entities. My UserEntity is related "one to many" with RegistrationTokenEntity. When I try to save this entities cascaded I get exception. Here is code:
UserEntity:
#Entity
#Table(name = "user", schema = "", catalog = "myDatabase")
public class UserEntity {
private int userId;
private String login;
// Some other fields
private Set<RegistrationTokenEntity> registrationTokenEntities = new HashSet<RegistrationTokenEntity>(0);
#OneToMany(fetch = FetchType.LAZY, mappedBy = "userId", cascade = CascadeType.ALL)
public Set<RegistrationTokenEntity> getRegistrationTokenEntities() {
return registrationTokenEntities;
}
public void setRegistrationTokenEntities(Set<RegistrationTokenEntity> registrationTokenEntities) {
this.registrationTokenEntities = registrationTokenEntities;
}
#Id
#Column(name = "user_id")
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
// Some other setters and getters
}
RegistrationTokenEntity:
#Entity
#Table(name = "registration_token", schema = "", catalog = "myDatabase")
public class RegistrationTokenEntity {
private int registrationTokenId;
private UserEntity userId;
// Some other fields
#Id
#Column(name = "registration_token_id")
public int getRegistrationTokenId() {
return registrationTokenId;
}
public void setRegistrationTokenId(int registrationTokenId) {
this.registrationTokenId = registrationTokenId;
}
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "user_id", nullable = false)
public UserEntity getUserId() {
return userId;
}
public void setUserId(UserEntity userId) {
this.userId = userId;
}
// Some others setters and getters
}
Here is how I save:
private void addNewUser(SignupForm homepageForm, PasswordEncoder passwordEncoder) {
UserEntity userEntity = new UserEntity(homepageForm);
RegistrationTokenEntity registrationTokenEntity = new RegistrationTokenEntity();
registrationTokenEntity.setConfirmed((byte)0);
UUID token = UUID.randomUUID();
registrationTokenEntity.setToken(token.toString());
registrationTokenEntity.setUserId(userEntity);
userEntity.getRegistrationTokenEntities().add(registrationTokenEntity);
userRepository.saveAndFlush(userEntity);
}
Here is my database SQL related to user and registerToken tables:
CREATE TABLE IF NOT EXISTS `myDatabase`.`user` (
`user_id` INT NOT NULL AUTO_INCREMENT,
`login` VARCHAR(30) NOT NULL,
// Some other fields
PRIMARY KEY (`user_id`),
UNIQUE INDEX `login_UNIQUE` (`login` ASC),
UNIQUE INDEX `username_UNIQUE` (`username` ASC),
UNIQUE INDEX `email_UNIQUE` (`email` ASC))
ENGINE = InnoDB;
CREATE TABLE IF NOT EXISTS `myDatabase`.`registration_token` (
`registration_token_id` INT NOT NULL AUTO_INCREMENT,
`user_id` INT NOT NULL,
// Some other fields
PRIMARY KEY (`registration_token_id`, `user_id`),
INDEX `fk_registration_token_user1_idx` (`user_id` ASC),
CONSTRAINT `fk_registration_token_user1`
FOREIGN KEY (`user_id`)
REFERENCES `myDatabase`.`user` (`user_id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
On output I get:
07-Jun-2015 21:07:25.257 WARN [http-apr-8080-exec-38] org.hibernate.engine.jdbc.spi.SqlExceptionHelper.logExceptions SQL Error: 1452, SQLState: 23000
07-Jun-2015 21:07:25.257 ERROR [http-apr-8080-exec-38] org.hibernate.engine.jdbc.spi.SqlExceptionHelper.logExceptions Cannot add or update a child row: a foreign key constraint fails (`myDatabase`.`registration_token`, CONSTRAINT `fk_registration_token_user1` FOREIGN KEY (`user_id`) REFERENCES `user` (`user_id`) ON DELETE NO ACTION ON UPDATE NO ACTION)
07-Jun-2015 21:07:25.260 INFO [http-apr-8080-exec-38] org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl.release HHH000010: On release of batch it still contained JDBC statements
07-Jun-2015 21:07:25.262 WARN [http-apr-8080-exec-38] org.hibernate.engine.jdbc.spi.SqlExceptionHelper$StandardWarningHandler.logWarning SQL Warning Code: 1452, SQLState: 23000
07-Jun-2015 21:07:25.262 WARN [http-apr-8080-exec-38] org.hibernate.engine.jdbc.spi.SqlExceptionHelper$StandardWarningHandler.logWarning Cannot add or update a child row: a foreign key constraint fails (`myDatabase`.`registration_token`, CONSTRAINT `fk_registration_token_user1` FOREIGN KEY (`user_id`) REFERENCES `user` (`user_id`) ON DELETE NO ACTION ON UPDATE NO ACTION)
And here is root exceptions stack:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
org.hibernate.exception.ConstraintViolationException: could not execute statement
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`myDatabase`.`registration_token`, CONSTRAINT `fk_registration_token_user1` FOREIGN KEY (`user_id`) REFERENCES `user` (`user_id`) ON DELETE NO ACTION ON UPDATE NO ACTION)
Have you any idea what I'm doing wrong?
I got this!
I had to add generated value strategy to my #Id like this:
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "user_id")
public int getUserId() {
return userId;
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "registration_token_id")
public int getRegistrationTokenId() {
return registrationTokenId;
}
Related
I want to add a new Ticket to my SQL Database.
Ticket has 2 PK: event and code;
I created Entitys with Composite Keys and want to execute POST requests. I always get "Column 'seller' cannot be null". Anyone here knows how to work with Java Persistence and so on?
I tried it with IdClass and Embeddable but I get errors for both. It's just the inserting of a new Object in the Database. GET Requests work fine...
I tried different annotations but for now nothing worked. I probably don't really understand the concept of Java Persistence, but I also dont have to time to go trough it the whole way. So of it's obvious, please explain a little what it does... Thanks in advance!
My Entities:
Event.java
#Entity
#Table(name="events")
#NamedQuery(name="Event.findAll", query="SELECT e FROM Event e")
public class Event implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private long id;
private String category;
private String city;
#Temporal(TemporalType.DATE)
private Date date;
#Column(name="image_path")
private String imagePath;
private String name;
private String venue;
//bi-directional one-to-many association to Ticket
#OneToMany(mappedBy="eventBean")
#JsonManagedReference(value="eventBean")
private List<Ticket> tickets;
public Event() {
}
Ticket.java
#Entity
#Table(name="tickets")
#IdClass(TicketPK.class)
//#NamedQuery(name="Ticket.findAll", query="SELECT t FROM Ticket t")
public class Ticket implements Serializable{
private static final long serialVersionUID = 1L;
#Id
private long code;
#Id
private long event;
private float price;
private String type;
//#Column(insertable=false, updatable=false)
//private long event;
//bi-directional many-to-one association to Event
//One Event can have many tickets
#ManyToOne(fetch = FetchType.EAGER)
#JsonBackReference(value="eventBean")
#JoinColumn(name="event",nullable = false,insertable=false,updatable=false)
private Event eventBean;
//bi-directional many-to-one association to User
//One User can have many tickets
#ManyToOne(fetch = FetchType.LAZY)
#JsonBackReference(value="seller")
#JoinColumn(name="seller", referencedColumnName = "alias")
private User user;
public Ticket() {
}
public Ticket(long event, float price, Event eventBean, User user) {
this.event = event;
this.price = price;
this.eventBean = eventBean;
this.user = user;
}
//getters and setters
public class TicketPK implements Serializable {
//default serial version id, required for serializable classes.
private static final long serialVersionUID = 1L;
//#Basic
//#GeneratedValue(strategy = GenerationType.AUTO)
//#Column(name="code", nullable=false)
private long code;
//#Basic
//#Column(name="event",insertable=false)
private long event;
public TicketPK() {
}
public TicketPK(long code, long event) {
this.code = code;
this.event = event;
}
//getters and setters
public boolean equals(Object other) {
if (this.equals(other)) {
return true;
}
if (!(other instanceof TicketPK)) {
return false;
}
TicketPK castOther = (TicketPK)other;
return
(this.code == castOther.code)
&& (this.event == castOther.event);
}
public int hashCode() {
final int prime = 31;
int hash = 17;
hash = hash * prime + ((int) (this.code ^ (this.code >>> 32)));
hash = hash * prime + ((int) (this.event ^ (this.event >>> 32)));
return hash;
}
}
User.java
#Entity
#Table(name="users")
#NamedQuery(name="User.findAll", query="SELECT u FROM User u")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private String alias;
private String address;
#Column(name="admin_status")
private byte adminStatus;
private String name;
private String password;
#Column(name="phone_number")
private int phoneNumber;
//bi-directional one-to-many association to Ticket
//One User can have many Tickets
#OneToMany(mappedBy="user")
#JsonManagedReference(value="seller")
private List<Ticket> tickets;
public User() {
}
DAO
TicketDAO
public interface TicketDAO extends CrudRepository<Ticket, TicketPK>{
public List<Ticket> findAll();
}
Controller
#Controller
#CrossOrigin
public class MyController {
#Autowired
TicketDAO daoticket;
/****************** OPERATIONS ON Tickets ************************************/
#RequestMapping(value="/tickets", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Ticket> createTicket(#RequestBody Ticket ticket) {
ResponseEntity<Ticket> response;
Ticket newTicket = daoticket.save(ticket);
if (newTicket == null) {
response = new ResponseEntity<>(HttpStatus.NOT_MODIFIED);
} else {
response = new ResponseEntity<>(newTicket, HttpStatus.CREATED);
}
return response;
}
}
SQL Database
CREATE DATABASE IF NOT EXISTS `BD89_03_ticketsell`;
USE `BD89_03_ticketsell`;
DROP TABLE IF EXISTS `TICKETS`;
DROP TABLE IF EXISTS `EVENTS`;
DROP TABLE IF EXISTS `USERS`;
CREATE TABLE `users` (
`name` varchar(100),
`alias` varchar(100) NOT NULL UNIQUE,
`password` varchar(100) NOT NULL,
`address` varchar(100),
`phone_number` int(10),
`admin_status` boolean NOT NULL,
PRIMARY KEY(`alias`)
);
CREATE TABLE `events`(
`id` bigint NOT NULL UNIQUE AUTO_INCREMENT,
`name` varchar(100) NOT NULL,
`category` varchar(100) NOT NULL,
`date` date NOT NULL,
`city`varchar(100) NOT NULL,
`venue` varchar(100) NOT NULL,
`image_path` varchar(300) NOT NULL,
PRIMARY KEY(`id`)
);
CREATE TABLE `tickets`(
`code` bigint NOT NULL,
`event` bigint NOT NULL,
`type` varchar(100),
`price` FLOAT(10,2) NOT NULL,
`seller` varchar(100) NOT NULL,
PRIMARY KEY(`code`, `event`),
FOREIGN KEY(`seller`) REFERENCES `users`(`alias`),
FOREIGN KEY(`event`) REFERENCES `events`(`id`)
);
INSERT INTO events (`name`, `category`, `date`, `city`, `venue`, `image_path`)
VALUES ('Cut Cupy', 'indie dance', '2024-01-22', 'Madrid', 'La Riviera', 'images/CUT-COPY2.png'),
('Dub Inc Tour 2022', 'reggae', '2021-05-03', 'Madrid', 'Sala Sol', 'images/DUB-INC-TOUR.jpg'),
('Kodaline', 'folk', '2022-03-15', 'Sevilla', 'Tablao el gitanillo', 'images/Kodaline.png');
INSERT INTO users (`name`,`alias`,`password`,`address`,`phone_number`, `admin_status`)
VALUES ('pepe', 'pepe', 'password', '17 Calle', '628791051', TRUE),
('pepe2', 'pepe2', 'password', '0 Calle', '628791052', FALSE),
('elisa', 'elisacool', 'contraseña', '3 Calle', '628791053', FALSE);
INSERT INTO tickets (`code`,`event`,`type`,`price`,`seller`)
VALUES ('1234', '1', 'palco', '17.5', 'pepe'),
('666666', '3', 'silla', '20', 'elisacool'),
('666666', '1', 'anfiteatro', '12', 'pepe2'),
('222222', '2', 'palco 3', '21.47', 'elisacool'),
('444666', '3', 'plató', '5', 'pepe'),
('111111', '2', 'palco 2', '40.99', 'elisacool');
Console Error
2022-12-06 15:52:46.186 WARN 9656 --- [io-10303-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 1048, SQLState: 23000
2022-12-06 15:52:46.186 ERROR 9656 --- [io-10303-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper : Column 'seller' cannot be null
2022-12-06 15:52:46.186 INFO 9656 --- [io-10303-exec-2] o.h.e.j.b.internal.AbstractBatchImpl : HHH000010: On release of batch it still contained JDBC statements
2022-12-06 15:52:46.199 ERROR 9656 --- [io-10303-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause
java.sql.SQLIntegrityConstraintViolationException: Column 'seller' cannot be null
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:117) ~[mysql-connector-j-8.0.31.jar:8.0.31]
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122) ~[mysql-connector-j-8.0.31.jar:8.0.31]
at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:916) ~[mysql-connector-j-8.0.31.jar:8.0.31]
.
.
.
I have two entity class as below -
public class Parent {
#Id
private Integer parentId;
private String name;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "parent", cascade = CascadeType.ALL)
private List<Child> children;
}
public class Child {
#Id
private Integer childId;
private String name;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "parentId", insertable = false, updatable = true, nullable = false)
private Parent parent;
}
#RestController
public class ParentController {
#Autowired
private ParentRepo repo;
#GetMapping("/parent")
public void get() {
Child c1 = Child.builder().childId(1).name("s1").build();
Child c2 = Child.builder().childId(2).name("s2").build();
List<Child> children = new ArrayList<>();
children.add(c1);
children.add(c2);
Parent parent = Parent.builder().parentId(1).name("PARENT")
.children(children)
.build();
Parent savedParent = repo.save(parent);
}
}
Tables -
CREATE TABLE public.parent
(
parent_id integer NOT NULL,
name character varying(255) COLLATE pg_catalog."default",
CONSTRAINT parent_pkey PRIMARY KEY (parent_id)
)WITH (
OIDS = FALSE
)
TABLESPACE pg_default;
CREATE TABLE public.child
(
child_id integer NOT NULL,
name character varying(255) COLLATE pg_catalog."default",
parent_id integer NOT NULL,
CONSTRAINT child_pkey PRIMARY KEY (child_id),
CONSTRAINT fk7dag1cncltpyhoc2mbwka356h FOREIGN KEY (parent_id)
REFERENCES public.parent (parent_id) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE NO ACTION
)
WITH (
OIDS = FALSE
)
TABLESPACE pg_default;
I'm getting error while persisting child record.
Error -
Hibernate:
insert
into
child
(name, child_id)
values
(?, ?)
2022-07-19 23:12:31.727 WARN 20940 --- [nio-8080-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 0, SQLState: 23502
2022-07-19 23:12:31.727 ERROR 20940 --- [nio-8080-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper : ERROR: null value in column "parent_id" violates not-null constraint
Detail: Failing row contains (1, s1, null).
2022-07-19 23:12:31.728 INFO 20940 --- [nio-8080-exec-2] o.h.e.j.b.internal.AbstractBatchImpl : HHH000010: On release of batch it still contained JDBC statements
2022-07-19 23:12:31.754 ERROR 20940 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [parent_id]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause
org.postgresql.util.PSQLException: ERROR: null value in column "parent_id" violates not-null constraint
Detail: Failing row contains (1, s1, null).
Not sure how hibernate will pick and assign the foreign key to child.
You have to set the bidirectional relationship first
public class Parent {
#Id
private Integer parentId;
private String name;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "parent", cascade = CascadeType.ALL)
private List<Child> children;
public void addChild(Child child) {
this.children.add(child);
child.setParent(this);
}
}
and add the children via that method.
I get this error when requesting service line:
List<Order> orders = ordersRepository.getByCustomerId(id);
Error:
org.springframework.dao.InvalidDataAccessApiUsageException: Parameter value [5] did not match expected type [nz.webshop.models.Customer.Customers (n/a)]; nested exception is java.lang.IllegalArgumentException: Parameter value [5] did not match expected type [nz.webshop.models.Customer.Customers (n/a)]
Repository:
public interface OrdersRepository extends JpaRepository<Order, Integer> {
List <Order> getByCustomerId(Integer customerId);
}
Entities:
#EntityA:
#Table(name = "orders")
public class Order {
#ManyToOne(targetEntity=Customers.class)
#JoinColumn (name = "customer_id", referencedColumnName="customer_id")
private Integer customerId;
...getters/setters
#EntityB:
#Table (name ="customer")
public class Customers {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name = "customer_id")
private Integer customerId;
#OneToMany(targetEntity = Order.class, mappedBy = "customerId")
private List<Order> Order;
...getters/setters
Where tables are like this:
CREATE TABLE orders
(
order_id INT AUTO_INCREMENT PRIMARY KEY,
customer_id INT,
FOREIGN KEY (customer_id) REFERENCES customer (customer_id)
);
CREATE TABLE customer
(
customer_id INT AUTO_INCREMENT PRIMARY KEY,
first_name VARCHAR(50) ,
last_name VARCHAR(50)
);
Update:
I changed EntityA as follows:
#EntityA:
#Table(name = "orders")
public class Order {
#Column(name = "customer_id")
private Integer customerId;
#ManyToOne(targetEntity=Customers.class)
private Customer customer;
...getters/setters
But then when requesting the same service line new error: org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet. Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'order0_.customer_customer_id' in 'field list'.
Where is the problem could be?
It looks like the Order.customerId property is not set up correctly. You're requesting that ManyToOne find Customer models based on their IDs, but then you're loading the models as Integers. Try this instead:
#ManyToOne
#JoinColumn(name = "customer_id", referencedColumnName="customer_id")
private Customer customer;
Let me know if this works, and if not, we can troubleshoot some more.
I try to Connect Pizzas and Ingredients in a n:m relation while all Pizzas have Ingredients as an Attribute List of Ingredients. But in the Relationstable when I create a new Pizza and try to commit there is an Error with the PizzaID in the Relationtable.
The relational Table:
CREATE TABLE `Pizza_Ingredience_Relation` (
`PizzaID` int(11) NOT NULL,
`IngredientID` int(11) NOT NULL,
`Amount` int(11) NOT NULL,
`Volume_Unit` varchar(1) NOT NULL,
PRIMARY KEY (`PizzaID`,`IngredientID`),
KEY `FKc58en2gx5a8n1swmu9tda345` (`IngredientID`),
CONSTRAINT `FK_IngredienceId` FOREIGN KEY (`IngredientID`) REFERENCES `Zutatenliste` (`ID`),
CONSTRAINT `FKc58en2gx5a8n1swmu9tda345` FOREIGN KEY (`IngredientID`) REFERENCES `Zutatenliste` (`ID`),
CONSTRAINT `FKhghfxg8raskdydyu8o8msxtfn` FOREIGN KEY (`PizzaID`) REFERENCES `Pizza` (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
The Ingredient Table:
CREATE TABLE `Zutatenliste` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`Name` varchar(20) NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
The Pizza Table:
CREATE TABLE `Pizza` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`Name` varchar(20) NOT NULL,
`PreisKlein` double NOT NULL,
`PreisMittel` double NOT NULL,
`PreisGroß` double NOT NULL,
`PreisFamilie` double NOT NULL,
PRIMARY KEY (`ID`),
UNIQUE KEY `ID` (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
I have two hibernate Entitites, one is a Pizza Entitiy and one the Ingredient Entitiy:
package Model.PizzenDB.SQLConnectionClasses.MySQL;
import Model.PizzenDB.Pizza;
import org.hibernate.annotations.CollectionId;
import org.hibernate.annotations.Where;
import javax.persistence.*;
import java.util.LinkedList;
import java.util.Set;
#Entity
#Table(name = "Pizza")
public class MySQLPizzaHibernateEntity {
#Id
#Column(name = "ID")
private int id;
#Column(name = "Name")
private String name;
#Column(name = "PreisKlein")
private double smallPrice;
#Column(name = "PreisMittel")
private double middlePrice;
#Column(name = "PreisGroß")
private double bigPrice;
#Column(name = "PreisFamilie")
private double familyPrice;
#ManyToMany(cascade = { CascadeType.ALL })
#JoinTable(
name = "Pizza_Ingredience_Relation",
joinColumns = { #JoinColumn(name = "PizzaID", referencedColumnName = "ID") },
inverseJoinColumns = { #JoinColumn(name = "IngredientID") }
)
private Set<MySQLIngredientWithAmountHibernateEntity> ingredience;
public MySQLPizzaHibernateEntity(String name, double smallPrice, double middlePrice, double bigPrice, double familyPrice) {
this.name = name;
this.smallPrice = smallPrice;
this.middlePrice = middlePrice;
this.bigPrice = bigPrice;
this.familyPrice = familyPrice;
}
public MySQLPizzaHibernateEntity() {
}
}
#Entity
#Table(name = "Zutatenliste")
#SecondaryTable(name = "Pizza_Ingredience_Relation", pkJoinColumns = #PrimaryKeyJoinColumn(name = "IngredientID", referencedColumnName = "ID"))
public class MySQLIngredientWithAmountHibernateEntity {
#Id
#Column(name = "ID")
private int id;
#Column(name = "Name")
private String name;
#Column(table = "Pizza_Ingredience_Relation", name="Amount")
private int amount;
#Column(table = "Pizza_Ingredience_Relation", name = "Volume_Unit")
private char unit;
public MySQLIngredientWithAmountHibernateEntity(String name) {
this.name = name;
}
public MySQLIngredientWithAmountHibernateEntity() {
this("");
}
}
I get the following error message:
20:41:45 [main] [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] ERROR - Field 'PizzaID' doesn't have a default value
20:41:45 [main] [org.hibernate.internal.ExceptionMapperStandardImpl] ERROR - HHH000346: Error during managed flush [org.hibernate.exception.GenericJDBCException: could not execute statement]
I'm not sure what is wrong in detail I guess it has todo with the PizzaID Foreign Key and that it isn't set properly.
For many to many relationship, you are using middle table with extra columns and you need Embeddable key for that which would comprise of Pizza and Ingredient object (names shortened). Something like:
#Embeddable
public class PizzaIngredientPk {
private MySQLPizzaHibernateEntity pizza;
private MySQLIngredientWithAmountHibernateEntity ingredient;
#ManyToOne
public MySQLPizzaHibernateEntity getPizza() {
return pizza;
}
public void setPizza(MySQLPizzaHibernateEntity pizza) {
this.pizza = pizza;
}
#ManyToOne
public MySQLIngredientWithAmountHibernateEntity getIngredient() {
return ingredient;
}
public void setIngredientID(MySQLIngredientWithAmountHibernateEntity ingredient) {
this.ingredient = ingredient;
}
}
Then this would act as Embedded Key in MySQLIngredientWithAmountHibernateEntity as
#EmbeddedId
PizzaIngredientPk pk = new PizzaIngredientPk();
But this won't work with Secondarytable which is used for one-to-one relationship. #SecondaryTable requires mapping to be with a primary key but in this case Embedded ID would become PK. In fact, you have flaw in your design. You are trying to make one side of your many to many relationship as one-to-one.
As per JPA docs There must be only one EmbeddedId annotation and no Id annotation when the EmbeddedId annotation is used.
Try to specify to Hibernate automatically produce primary keys. Put this annotation above your Id fields and re-create your database.
#GeneratedValue(strategy = GenerationType.IDENTITY)
See: https://thoughts-on-java.org/hibernate-tips-use-auto-incremented-column-primary-key/
I want to map a existing database (we can't change for now) to Hibernate entities.
But my mapping seems to have a problem with a transitive mapped composite keys I can't overcome.
FluidSampleLabel has FluidSample as foreign key and as part of its own composite primary key. Hibernate seems to ignore the columns/embedded id mapped by the embedded foreign key entity FluidSample in FluidSampleLabel.
Test-Project on Github:
https://github.com/burka/hibernate-transitive-compkey-problem.git
org.hibernate.AnnotationException: A Foreign key refering compkey_problem.model.FluidSample from compkey_problem.model.FluidSampleLabel has the wrong number of column. should be 1
Without #ManyToOne annotated named columns on embedded fks I get the following error:
Caused by: org.hibernate.MappingException: Foreign key (FK246FD874D0837E3B:fluid_sample_label [sample])) must have same number of columns as the referenced primary key (fluid_sample [sampleGroup,pre_post])
create sequence sample_group_seq start 10000;
create table sample_group (
sample_group_id int primary key,
payload varchar(200)
);
create table fluid_sample (
sample_group_id int not null,
pre_post varchar(20) not null check ( pre_post in ( 'PRE', 'POST') ),
amount number(20,10) not null,
primary key ( sample_group_id, pre_post ),
constraint fk_fluid_sample_group foreign key ( sample_group_id ) references sample_group ( sample_group_id )
);
create table fluid_sample_label (
sample_group_id int,
pre_post varchar(20) not null check ( pre_post in ( 'PRE', 'POST') ),
label varchar(200) not null,
primary key ( sample_group_id, pre_post, label ),
constraint fk_fluid_label_fluid foreign key ( sample_group_id, pre_post ) references fluid_sample ( sample_group_id, pre_post )
);
#Entity
#SequenceGenerator(name = "sampleGroupSequence", sequenceName = "sample_group_seq", allocationSize = 1)
#Table(name = "sample_group")
public class SampleGroup
{
#Id
#GeneratedValue(generator = "sampleGroupSequence", strategy = GenerationType.SEQUENCE)
#Column(name = "sample_group_id")
private Integer sampleGroupId;
#OneToMany(mappedBy = "sampleGroup")
private List<FluidSample> fluidSamples = new ArrayList<>();
#Column(name = "payload")
private String payload;
public SampleGroup()
{
}
public FluidSample addNewPreFluidSample()
{
FluidSample sample = new FluidSample(this, PrePost.PRE);
this.fluidSamples.add(sample);
return sample;
}
}
#Entity
#Table(name = "fluid_sample")
public class FluidSample
{
#Id
#ManyToOne
#JoinColumn(name = "sample_group_id")
private SampleGroup sampleGroup;
#Id
#Column(name = "pre_post")
#Enumerated(EnumType.STRING)
private PrePost prePost;
#OneToMany(mappedBy = "sample")
private List<FluidSampleLabel> labels = new ArrayList<>();
#Column(name = "amount")
private BigDecimal amount;
#SuppressWarnings("unused")
private FluidSample()
{
}
public FluidSample(SampleGroup sampleGroup, PrePost prePost)
{
this.sampleGroup = sampleGroup;
this.prePost = prePost;
}
public FluidSampleLabel addNewLabel(String value)
{
FluidSampleLabel label = new FluidSampleLabel(this, value);
this.labels.add(label);
return label;
}
}
#Entity
#Table(name = "fluid_sample_label")
public class FluidSampleLabel
{
#Id
#ManyToOne
#JoinColumns({ #JoinColumn(name = "sample_group_id"), #JoinColumn(name = "pre_post")})
private FluidSample sample;
#Id
private String value;
#SuppressWarnings("unused")
private FluidSampleLabel()
{
}
FluidSampleLabel(FluidSample sample, String value)
{
this.sample = sample;
this.value = value;
}
public String getValue()
{
return this.value;
}
}
public enum PrePost
{
PRE, POST;
}