Hibernate trying to alter table before creating it - java

Simple issue here: I'm running Spring Boot 2.2.5 on a mySQL database with MySQL5Dialect. Everything was peachy until I've added #ManyToOne annotation to Slide entity referencing the User entity - now Hibernate can't create tables because it creates the users table and then tries to alter slides table which it hasn't created yet. What did I do wrong?
User:
#Entity
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#ToString
#Table(name = "users")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private boolean enabled;
private String token;
private String username;
private String password;
private String role;
private String name;
private String surname;
private String email;
private boolean emailVisible;
private String phone;
private boolean phoneVisible;
private int cohortNumber;
private String company;
private String position;
private String linkedIn;
private String function;
private String bio;
private String membership;
private Date membershipSince;
private Date membershipUntil;
}
Slide:
#Entity
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#ToString(exclude = "editor")
#Table(name = "slides")
public class Slide {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private boolean visible;
private int order;
private Date edited;
#ManyToOne
#JoinColumn(name = "editor_id")
private User editor;
private String title;
private String text;
private String picture;
}
Hibernate config specifics:
spring.jpa.hibernate.ddl-auto = update
spring.datasource.initialization-mode=always
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
And the error:
Hibernate: create table users (id integer not null auto_increment, bio varchar(255), cohort_number integer not null, company varchar(255), email varchar(255), email_visible bit not null, enabled bit not null, function varchar(255), linked_in varchar(255), membership varchar(255), membership_since datetime, membership_until datetime, name varchar(255), password varchar(255), phone varchar(255), phone_visible bit not null, position varchar(255), role varchar(255), surname varchar(255), token varchar(255), username varchar(255), primary key (id)) engine=MyISAM
Hibernate: alter table slides add constraint FKobqxptfxg36ls278o63ouq369 foreign key (editor_id) references users (id)
2020-08-11 14:27:48.201 WARN 8224 --- [ restartedMain] o.h.t.s.i.ExceptionHandlerLoggedImpl : GenerationTarget encountered exception accepting command : Error executing DDL "alter table slides add constraint FKobqxptfxg36ls278o63ouq369 foreign key (editor_id) references users (id)" via JDBC Statement
...
Caused by: java.sql.SQLSyntaxErrorException: Table '32293814_alumnicemba.slides' doesn't exist

Found the problem:
private int order;
"order" is not allowed as a field name here and Hibernate was encountering an error when trying to create the slides table but not logging that error. I've renamed the field to "sorting" and it works now.

Related

Entity not creating table in DB

I'm using Spring boot, and I Run this model.
package com.example.demo.Models;
import jakarta.persistence.*;
#Entity
#Table(name = "user")
public class UserModel {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(unique = true, nullable = true)
private Long id;
private String name;
private String email;
private Integer priority;
/* Here are all the setters and getters*/
}
application.properties:
spring.datasource.url=jdbc:postgresql://localhost:5432/dbdemo
spring.datasource.username=postgres
spring.datasource.password=password
spring.jpa.hibernate.ddl-auto=update
Everything fine with Java.
Process finished with exit code 0
But in the console of my docker image of Postgres I get the following error:
ERROR: syntax error at or near "user" at character 14
STATEMENT: create table user(id bigserial not null, email varchar(255), name varchar(255), priority integer, primary key (id))
I'm not sure how to solve it, I'd appreciate any help.
create table public.user ( id serial not null,
email varchar(255),
name varchar(255),
priority integer,
primary key (id))
add the schema name before the table name
You need to specify the schema name in table and id fields like this:
#Table(name = "anomaly", schema = "schema_name")
public class Anomaly {
#Id
#SequenceGenerator(name = "id", allocationSize = 1, schema = "schema_name")
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long anomalyId;
user is a reserved word in Postgresql thats why it show an error
use a different word like "users" "usersId".

JPA Entity Creation

I have been trying to create JPA entity using schema of Mysql Sample Database , JPA tools of Eclipse JPA entites are generated using i am having for establishing entity relationship for below scenarios and tables
Employee Table : Employee tables has field reportsto which refers back to employee i.e one employee reports to another employee
Office Table: One office can have more then one Employee
Below are JPA Entities :
#Entity
#Table(name="employees")
#NamedQuery(name="Employee.findAll", query="SELECT e FROM Employee e")
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
private String email;
private String extension;
private String firstName;
private String jobTitle;
private String lastName;
//bi-directional one-to-one association to Customer
#OneToOne(mappedBy="employee")
private Customer customer;
//bi-directional many-to-one association to Office
#ManyToOne
#JoinColumn(name="officeCode", referencedColumnName="officeCode")
private Office office;
//bi-directional many-to-one association to Employee
#ManyToOne
#JoinColumn(name="reportsTo", referencedColumnName="employeeNumber")
private Employee employee;
//bi-directional many-to-one association to Employee
#OneToMany(mappedBy="employee")
private List<Employee> employees;
}
Table Description
CREATE TABLE `employees` (
`employeeNumber` int(11) NOT NULL,
`lastName` varchar(50) NOT NULL,
`firstName` varchar(50) NOT NULL,
`extension` varchar(10) NOT NULL,
`email` varchar(100) NOT NULL,
`officeCode` varchar(10) NOT NULL,
`reportsTo` int(11) DEFAULT NULL,
`jobTitle` varchar(50) NOT NULL,
PRIMARY KEY (`employeeNumber`),
KEY `reportsTo` (`reportsTo`),
KEY `officeCode` (`officeCode`),
CONSTRAINT `employees_ibfk_1` FOREIGN KEY (`reportsTo`) REFERENCES `employees` (`employeeNumber`),
CONSTRAINT `employees_ibfk_2` FOREIGN KEY (`officeCode`) REFERENCES `offices` (`officeCode`)
)
When app loads we get below error message
referencedColumnNames(employeeNumber) of com.train.model.Employee.employee referencing com.train.model.Employee not mapped to a single property
when i add field employeeNumber and generate getters and setters , i get below error
referencedColumnNames(officeCode) of com.train.model.Employee.office referencing com.train.model.Office not mapped to a single property
Office JPA Entity
#Entity
#Table(name="offices")
#NamedQuery(name="Office.findAll", query="SELECT o FROM Office o")
public class Office implements Serializable {
private static final long serialVersionUID = 1L;
private String addressLine1;
private String addressLine2;
private String city;
private String country;
private String phone;
private String postalCode;
private String state;
private String territory;
//bi-directional many-to-one association to Employee
#OneToMany(mappedBy="office")
private List<Employee> employees;
}
Table Description
CREATE TABLE `offices` (
`officeCode` varchar(10) NOT NULL,
`city` varchar(50) NOT NULL,
`phone` varchar(50) NOT NULL,
`addressLine1` varchar(50) NOT NULL,
`addressLine2` varchar(50) DEFAULT NULL,
`state` varchar(50) DEFAULT NULL,
`country` varchar(50) NOT NULL,
`postalCode` varchar(15) NOT NULL,
`territory` varchar(10) NOT NULL,
PRIMARY KEY (`officeCode`)
)
Why employee entity complains of not having officeCode and what is right entity for Employee and Office

DynamicUpdate added extra untouched column in update statement

I am facing a weird behavior using #DynamicUpdate with one of my entity. So my entity is defined like this
#Entity
#DynamicUpdate
#Table(name = "courts")
#Getter
#Setter
#Builder
#AllArgsConstructor // require for #Builder to work correctly
#NoArgsConstructor // required for hibernate mapping
public class CourtDO {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
// name is SQL keyword
#Column(name = "court_name")
private String name;
#Column
private String addressStreet;
#Column
private String addressWard;
#Column
private String addressDistrict;
#Column
private String addressCity;
#Column
private String addressCountry;
#Column
private String phoneNumber;
#Column(nullable = false)
#Convert(converter = DOTimestampConverter.class)
#CreationTimestamp
private ZonedDateTime createdAt;
#Column(nullable = false)
#Convert(converter = DOTimestampConverter.class)
#UpdateTimestamp
private ZonedDateTime updatedAt;
}
DOTimestampConverter is just a simple AttributeConverter to convert ZonedDateTime to ms for me to store in DB as number.
As you can see I marked the entity with #DynamicUpdate.
I have a small jersey REST-API which allow me to update all of the normal field beside the id and the generated date. I always check if the input is null before actually touching the setter for the field.
I see a very weird behavior with the column address_city, it would be included in every update like this even if I only touch other fields, in this case, just the name which translate to court_name because name is a reserved keyword in SQL. UPDATE Actually the problem is not with just the address_city column. Even if I ignore that column, other column would get included in the update statement.
Hibernate:
update
courts
set
address_city=?,
court_name=?,
updated_at=?
where
id=?
Where as if I only edit the address_city only then I would see it correctly
Hibernate:
update
courts
set
address_city=?,
updated_at=?
where
id=?
Did anyone face this problem before?
The stack I am using are
spring-boot 2.1.3.RELEASE
spring-boot-starter-data-jpa
postgresql 11.4
And the data schema
CREATE TABLE COURTS (
id SERIAL PRIMARY KEY,
court_name VARCHAR(20),
address_street VARCHAR(128),
address_ward VARCHAR(20),
address_district VARCHAR(20),
address_city VARCHAR(20),
address_country VARCHAR(10),
phone_number VARCHAR(20),
created_at BIGINT NOT NULL,
updated_at BIGINT NOT NULL
);
This is how update through REST-API
#Override
public Court editCourt(String courtId, CreateCourtRequest createCourtRequest) {
Optional<CourtDO> court = courtRepository.findById(NumberUtils.toLong(courtId));
return court
.map(courtDO -> editCourtInfo(courtDO, createCourtRequest))
.map(courtRepository::save)
.map(courtDOToResponseConverter::convert)
.orElse(null);
}
private CourtDO editCourtInfo(CourtDO courtDO, CreateCourtRequest createCourtRequest) {
if (StringUtils.isNotBlank(createCourtRequest.getName())) {
courtDO.setName(createCourtRequest.getName());
}
if (StringUtils.isNotBlank(createCourtRequest.getAddressStreet())) {
courtDO.setAddressStreet(createCourtRequest.getAddressStreet());
}
if (StringUtils.isNotBlank(createCourtRequest.getAddressWard())) {
courtDO.setAddressWard(createCourtRequest.getAddressWard());
}
if (StringUtils.isNotBlank(createCourtRequest.getAddressDistrict())) {
courtDO.setAddressDistrict(createCourtRequest.getAddressDistrict());
}
if (StringUtils.isNotBlank(createCourtRequest.getAddressCity())) {
courtDO.setAddressCity(createCourtRequest.getAddressCity());
}
if (StringUtils.isNotBlank(createCourtRequest.getPhoneNumber())) {
courtDO.setPhoneNumber(createCourtRequest.getPhoneNumber());
}
return courtDO;
}

MappingException with Unknown entity and #Generated Annotation

I want to set a default value for my forein key status_id.
So I created a trigger inside Oracle, which sets a default value on insert. After that, Hibernate should update the linked foreign instance.
I have following Database in Oracle:
CREATE TABLE status (
status_id NUMBER(10) NOT NULL,
name VARCHAR2(50) NOT NULL,
CONSTRAINT status_pk PRIMARY KEY (status_id)
);
CREATE TABLE customer (
customer_id NUMBER(10) NOT NULL,
street VARCHAR2(50),
zip VARCHAR2(50),
city VARCHAR2(50),
salutation VARCHAR2(50),
title VARCHAR2(50),
firstname VARCHAR2(50),
surname VARCHAR2(50),
phone VARCHAR2(50),
fax VARCHAR2(50),
email VARCHAR2(50),
type VARCHAR2(50),
status_id NUMBER(10) NOT NULL,
CONSTRAINT customer_pk PRIMARY KEY (customer_id),
CONSTRAINT customer_status_fk FOREIGN KEY (status_id) REFERENCES status(status_id)
);
INSERT INTO status (status_id, name) VALUES ('1', 'DEFAULT');
INSERT INTO status (status_id, name) VALUES ('2', 'PREMIUM');
INSERT INTO status (status_id, name) VALUES ('3', 'SUPPLIER');
I want to set status to 'DEFAULT' if not specified when inserting a new customer. So I created following Trigger:
CREATE OR REPLACE TRIGGER status_default_trigger BEFORE INSERT ON customer FOR EACH ROW BEGIN
IF :NEW.type IS NULL THEN
SELECT 'NEW' INTO :NEW.type FROM DUAL;
END IF;
IF :NEW.status_id IS NULL THEN
SELECT status_id INTO :NEW.status_id FROM status WHERE status.status_id = 1;
END IF;
END;
/
My Entities looks as follows:
Status.java:
#Data
#Entity
#Table(name = "status")
public class Status {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
private BigDecimal statusId;
#OneToMany(mappedBy = "status", fetch = FetchType.LAZY)
private List<Customer> customerList;
#Column
private String name;
}
Customer.java:
#Data
#Entity(name = "einsender")
#Table(name = "einsender")
public class Einsender {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
private BigDecimal einsenderId;
#Generated(GenerationTime.INSERT) // This fails to start Hibernate entityManager
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "status_id")
private Status status;
#Column
private String street;
#Column
private String zip;
#Column
private String city;
#Column
private String salutation;
#Column
private String title;
#Column
private String firstname;
#Column
private String surname;
#Column
private String phone;
#Column
private String fax;
#Column
private String email;
#Generated(GenerationTime.INSERT) // This works instead
#Column
private String type;
}
I expect that Customer.Status will be default Status(statusId=1,name='DEFAULT); But I get following Error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.MappingException: Unknown entity: de.example.model.Status
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1762) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:593) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
...
Caused by: org.hibernate.MappingException: Unknown entity: de.bund.bamf.vup.service.vorgang.model.Status
By the fact, the Customer.type Value will be mapped if I comment #Generated(GenerationTime.INSERT) above private Status status;

persisting a list of objects in play framework

I have a class called Device.class and i want to have a field that is a list of CommentObj.class . the problem is that this field is not persisted in database (I'm using Ebean). how is it possible to do so?
#Entity
public class Device extends Model {
#Id
public Long id;
#Constraints.MaxLength(50)
#Constraints.Required
public String serialNo;
...
public List<CommentObj> comments = new ArrayList<CommentObj>();
and
public class CommentObj extends Model {
#Id
public Long id;
#Constraints.MaxLength(50)
public String author;
#Constraints.MaxLength(500)
#Constraints.Required
public String content;
#Constraints.Required
public Date date;
public static Finder<Long, CommentObj> find = new Finder<>(Long.class, CommentObj.class);
public CommentObj(String author, String content){
this.author = author;
this.content = content;
date = new Date();
}
}
here is the structure of Device in database (according to 1.sql). there is no sign of comments field
create table device (
id bigint not null,
serial_no varchar(255),
invent_no varchar(255),
name varchar(255),
device_type_id bigint,
description varchar(2000),
cal_date timestamp,
cal_duration_in_months integer,
setup_id bigint,
manufacturer_id bigint,
constraint pk_device primary key (id))
;
Assuming you do have a device_id in your comment_obj table, you can have a unidirectional OneToMany mapping by adding the following annotations to your Device.class' comments field:
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(referencedColumnName = "id", name = "device_id")
public List<CommentObj> comments = new ArrayList<CommentObj>();

Categories

Resources