Hibernate creates only some tables - java

Hibernate hbm2ddl only creates 2 of 6 tables when the SessionFactory is creating.
Example of table that is created:
#Entity
#Table(name = "AUTHORITIES")
public class Authorities {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
#Column(name = "AUTHORITY", nullable=false)
private String authority;
#ManyToOne
#JoinColumn(name = "USERNAME", nullable=false)
private User user;
...getters, setters...
Example of table that isn't created:
#Entity
#Table(name = "EXERCISES")
public class Exercise {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
#Column(name = "NAME", nullable=false)
private String name;
#Column(name = "DESCRIPTION")
private String description;
...getters, setters...
Hibernate properties
hibernate.show_sql=true
hibernate.hbm2ddl.auto=create
hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
SQL from console:
Hibernate: drop table if exists AUTHORITIES cascade
Hibernate: drop table if exists USERS cascade
Hibernate: create table AUTHORITIES (id serial not null, AUTHORITY varchar(255) not null, USERNAME varchar(255) not null, primary key (id))
Hibernate: create table USERS (USERNAME varchar(255) not null, ENABLED boolean not null, PASSWORD varchar(255) not null, primary key (USERNAME))
Hibernate: alter table AUTHORITIES add constraint FKl8gm1dxqhdixkdsm1p7er9c21 foreign key (USERNAME) references USERS
Database is remote ElephantSQL.

Alright, as duffymo pointed, the configuration was wrong.
#Bean
public LocalSessionFactoryBean getSessionFactory() {
LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean();
Properties props = new Properties();
// Setting JDBC properties
props.put(DRIVER, env.getProperty("driver"));
props.put(URL, env.getProperty("jdbcUrl"));
props.put(USER, env.getProperty("username"));
props.put(PASS, env.getProperty("password"));
// Setting Hibernate properties
props.put(SHOW_SQL, env.getProperty("hibernate.show_sql"));
props.put(HBM2DDL_AUTO, env.getProperty("hibernate.hbm2ddl.auto"));
props.put(DIALECT, env.getProperty("hibernate.dialect"));
// Setting C3P0 properties
props.put(C3P0_MIN_SIZE, env.getProperty("hibernate.c3p0.min_size"));
props.put(C3P0_MAX_SIZE, env.getProperty("hibernate.c3p0.max_size"));
props.put(C3P0_ACQUIRE_INCREMENT, env.getProperty("hibernate.c3p0.acquire_increment"));
props.put(C3P0_TIMEOUT, env.getProperty("hibernate.c3p0.timeout"));
props.put(C3P0_MAX_STATEMENTS, env.getProperty("hibernate.c3p0.max_statements"));
factoryBean.setHibernateProperties(props);
factoryBean.setAnnotatedClasses(User.class, Authorities.class, Exercise.class, ExerciseUnit.class, Routine.class, Training.class);
return factoryBean;
I've forget to set new entities in:
factoryBean.setAnnotatedClasses(User.class, Authorities.class, Exercise.class, ExerciseUnit.class, Routine.class, Training.class);

Related

Hibernate trying to alter table before creating it

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.

integrity constraint violation: unique constraint or index violation on Foreign key HSQL

I'm testing the underlying model of a HSQL database using Hibernate/Spring Boot and I've run into an issue I cannot find a solution to.
This is my simple test, I'm trying to create a shoebox entity and save it to the database with a User object set as the FK for Owner:
#TestConfiguration
static class ShoeboxServiceTestContextConfiguration {
#Bean
public ShoeboxService shoeboxService() {
return new ShoeboxService();
}
#Bean
public UserService userService() {
return new UserService();
}
}
#Autowired
UserService users;
#Autowired
ShoeboxService shoeboxes;
#Test
public void testSave()
{
System.out.println("save");
int userId = 1;
User user = new User(userId, "Foo", "hello#world.com");
user = users.save(user);
Shoebox sb = new Shoebox(user, "Name", "Context", "Comment", false);
UUID sbId = shoeboxes.save(sb).getId();
sb = shoeboxes.findOne(sbId);
assertNotNull(sb);
assertEquals(sb.getName(), "Name");
assertEquals(sb.getContext(), "Context");
assertEquals(sb.getComment(), "Comment");
assertEquals(sb.isShare(), false);
shoeboxes.deleteById(sbId);
users.deleteById(userId);
}
However when it gets it throws a
integrity constraint violation: unique constraint or index violation; SYS_PK_10126 table: USER
exception when it tries to save the Shoebox to the DB. It successfully persist the User, and it succeeds in persisting the Shoebox object when there is no Owner FK attached to it, but crashes when the FK is supplied.
Here is my User POJO:
#Entity
#Table(name="User")
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class User implements Serializable
{
#Id
#Column(name = "ID")
private long ID;
#Column(name = "Name")
private String name;
#Column(name = "Email")
private String email;
#OneToOne(fetch = FetchType.LAZY)
private Shoebox currentlySelectedBox;
#OneToMany(fetch = FetchType.LAZY)
#JsonManagedReference(value="shoebox_owner")
private List<Shoebox> shoeboxes;
// Contructors, Getters/Setters etc.
}
And my Shoebox POJO:
#Entity
#Table(name="Shoebox")
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class Shoebox implements Serializable
{
#Id
#Column(name="ID")
UUID ID;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name="OwnerID")
#JsonBackReference(value="shoebox_owner")
User owner;
#Column(name="Name")
String name;
#Column(name="Context")
String context;
#Column(name="Comment")
String comment;
#Column(name="Shared")
boolean share;
#Column(name="CreationDate")
LocalDateTime creationDate;
// Contructors, Getters/Setters etc.
}
Here is the HSQL creation script for the DB:
CREATE MEMORY TABLE PUBLIC.SHOEBOX(ID BINARY(255) NOT NULL PRIMARY KEY,COMMENT VARCHAR(255),CONTEXT VARCHAR(255),CREATIONDATE TIMESTAMP,NAME VARCHAR(255),SHARED BOOLEAN,OWNERID BIGINT)
CREATE MEMORY TABLE PUBLIC.USER(ID BIGINT NOT NULL PRIMARY KEY,EMAIL VARCHAR(255),NAME VARCHAR(255),CURRENTLYSELECTEDBOX_ID BINARY(255),CONSTRAINT FK3T924ODM2BIK5543K0E3UEGP FOREIGN KEY(CURRENTLYSELECTEDBOX_ID) REFERENCES PUBLIC.SHOEBOX(ID))
CREATE MEMORY TABLE PUBLIC.USER_SHOEBOX(USER_ID BIGINT NOT NULL,SHOEBOXES_ID BINARY(255) NOT NULL,CONSTRAINT FK5W8WMFC5E9RMEK7VC4N76MQVQ FOREIGN KEY(SHOEBOXES_ID) REFERENCES PUBLIC.SHOEBOX(ID),CONSTRAINT FKIR9SOKRCOQ33LCQTNR0LDXO93 FOREIGN KEY(USER_ID) REFERENCES PUBLIC.SHOEBOXUSER(ID),CONSTRAINT UK_508XA86IDIHP04FQD3D6GF8D7 UNIQUE(SHOEBOXES_ID))
ALTER TABLE PUBLIC.SHOEBOX ADD CONSTRAINT FK3J9RQBYW5VQ0IRF3FWYPG7LAB FOREIGN KEY(OWNERID) REFERENCES PUBLIC.USER(ID)
Why is the exception being triggered? Is there something wrong with my annotations and PK/FK relationships between the objects?
Many Thanks.
The issue is
#ManyToOne(cascade = CascadeType.ALL)
With CascadeType.ALL, any operations will extend to the other entities. So in this case the save method is cascading on the shoebox's user attempting to save it again. Since you are using a static id of 1, it is causing a key constraint.

Bidirectional #OneToMany relation with JPA annotations doesn't seem to work

This is in reference to this answer.
Entities-
// Many to One
#Entity
#Table
public class Address {
#Id
#GeneratedValue
#Column
private int addressIdentity;
#Column
private int houseNo;
#Column
private char streetNo;
#Column
private int pincode;
#Column
private String city;
#Column
private String state;
#Column
private String country;
#ManyToOne
#JoinTable(name="PersonAddress",
joinColumns=#JoinColumn(name="addressId", insertable = false, updatable = false),
inverseJoinColumns=#JoinColumn(name="personId", insertable = false, updatable = false)
)
private Person person;
// getters and setters
One to Many
#Entity
#Table
public class Person {
#Id
#GeneratedValue
#Column
private int personId;
#Column
private String name;
#Column
private String designation;
#OneToMany
#JoinTable(name = "PersonAddress",
joinColumns = #JoinColumn(name = "personId"),
inverseJoinColumns = #JoinColumn(name = "addressId"))
private Set<Address> addSet = new HashSet<Address>();
// getters and setters
Hibernate configuration file-
<hibernate-configuration>
<session-factory name="">
<property name="hibernate.connection.driver_class">org.postgresql.Driver</property>
<property name="hibernate.connection.password">hello</property>
<property name="hibernate.connection.url">jdbc:postgresql://localhost:5432/xyz</property>
<property name="hibernate.connection.username">postgres</property>
<property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>
<property name="show_sql">true</property>
<property name="hbm2ddl.auto">create</property>
<mapping class="ManyToOne_OneToManyMappingWithJoinTable.Person" />
<mapping class="ManyToOne_OneToManyMappingWithJoinTable.Address" />
</session-factory>
</hibernate-configuration>
the persistence logic-
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
Person person1 = new Person();
person1.setName("Shahnaz Parveen");
person1.setDesignation("HouseWife");
Address address1 = new Address();
address1.setHouseNo(18);
address1.setStreetNo('E');
address1.setPincode(250002);
address1.setCity("Meerut");
address1.setState("UP");
address1.setCountry("INDIA");
address1.setPerson(person1);
Address address2 = new Address();
address2.setHouseNo(84);
address2.setStreetNo('1');
address2.setPincode(250002);
address2.setCity("Meerut");
address2.setState("UP");
address2.setCountry("INDIA");
address1.setPerson(person1);
person1.getAddSet().add(address1);
person1.getAddSet().add(address2);
session.save(address1);
session.save(address2);
session.save(person1);
session.getTransaction().commit();
session.close();
I am getting -
Jan 07, 2017 9:47:35 PM org.hibernate.action.internal.UnresolvedEntityInsertActions logCannotResolveNonNullableTransientDependencies
WARN: HHH000437: Attempting to save one or more entities that have a non-nullable association with an unsaved transient entity. The unsaved transient entity must be saved in an operation prior to saving these dependent entities.
Unsaved transient entity: ([ManyToOne_OneToManyMappingWithJoinTable.Person#0])
Dependent entities: ([[ManyToOne_OneToManyMappingWithJoinTable.Address#1]])
Non-nullable association(s): ([ManyToOne_OneToManyMappingWithJoinTable.Address.person])
Exception in thread "main" org.hibernate.TransientPropertyValueException: Not-null property references a transient value - transient instance must be saved beforeQuery current operation : ManyToOne_OneToManyMappingWithJoinTable.Address.person -> ManyToOne_OneToManyMappingWithJoinTable.Person
at org.hibernate.action.internal.UnresolvedEntityInsertActions.checkNoUnresolvedActionsAfterOperation(UnresolvedEntityInsertActions.java:122)
at org.hibernate.engine.spi.ActionQueue.checkNoUnresolvedActionsAfterOperation(ActionQueue.java:418)
at org.hibernate.internal.SessionImpl.checkNoUnresolvedActionsAfterOperation(SessionImpl.java:621)
at org.hibernate.internal.SessionImpl.fireSave(SessionImpl.java:684)
at org.hibernate.internal.SessionImpl.save(SessionImpl.java:674)
at org.hibernate.internal.SessionImpl.save(SessionImpl.java:669)
at ManyToOne_OneToManyMappingWithJoinTable.ManyToOne_OneToManyMappingWithJoinTableImpl.main(ManyToOne_OneToManyMappingWithJoinTableImpl.java:40)
It works perfect with hbms.
Please suggest.
Thanks Vlad and Neil, it works but there is a problem described below-
This is the structure which gets created with HBMs. Hence the same must be with Annotations.
CREATE TABLE person_address
(
addressid integer NOT NULL,
personid integer NOT NULL,
CONSTRAINT person_address_pkey PRIMARY KEY (addressid , personid ),
CONSTRAINT fkkpp6mysmnyiywx3q33yxr1gbe FOREIGN KEY (personid )
REFERENCES person (person_id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT fkrpk0jx2y558su288tx9kd5cs6 FOREIGN KEY (addressid )
REFERENCES address (address_id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
the moment I do -
#OneToMany(cascade = CascadeType.ALL, mappedBy = "person")
private Set<Address> addSet = new HashSet<Address>();
the join table structure is-
CREATE TABLE personaddress
(
personid integer,
addressid integer NOT NULL,
CONSTRAINT personaddress_pkey PRIMARY KEY (addressid),
CONSTRAINT fkfd5pm843bldj10y5kxwo37xge FOREIGN KEY (addressid)
REFERENCES address (addressidentity) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT fkjuwlthwsi53bpf902nnl6snxh FOREIGN KEY (personid)
REFERENCES person (personid) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
You see that the primary key is NOT a combination of addressid and personid as in HBMs. Please suggest.
You need to add a cascade on the one-to-many side:
#OneToMany(cascade = CascadeType.ALL)
Then, change the #ManyToOne side to:
#ManyToOne
#JoinTable(name="PersonAddress",
joinColumns=#JoinColumn(name="addressId"),
inverseJoinColumns=#JoinColumn(name="personId")
)
private Person person;
and the #OneToMany side to:
#OneToMany(cascade = CascadeType.ALL, mappedBy = "person")
private Set<Address> addSet = new HashSet<Address>();
To address the composite-key requirement as indicated by the question update, try mapping the join table (e.g. personaddress) as an entity, and use composite identifiers.

Hibernate + PostgreSQL + serial PK(ID) - cannot save object to DB

can sameone help me with problem with saving object to PostgreSQL databse? I use serial id and annotation #SequenceGenerator cannot get me some id from sequence, witch have been created automaticaly. (serial) The sequence is "user_id_user_sec".
I can save one entity, but second throw exception:
ERROR: ERROR: duplicate key value violates unique constraint "user_pkey"
Detail: Key (id_user)=(0) already exists.
Info: HHH000010: On release of batch it still contained JDBC statements
Severe: org.hibernate.exception.ConstraintViolationException: could not execute statement
at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelega te.java:129)
My entity, witch I can save to database:
#Entity
#Table(name = "\"User\"")
public class User implements java.io.Serializable {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator="seq")
#SequenceGenerator(name="seq", sequenceName="user_id_user_seq", allocationSize=1)
private int idUser;
#Column
private String apiKey;
#Column
private String email;
#Column
private String name;
#Column
private String password;
#Column
private boolean isAdmin;
#Column
private boolean enabled;
private Set deviceWatchedByUsers = new HashSet(0);
and getters and setters and my UserDAO's method, witch save this entity is:
public static Integer addUser(User u){
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction tx = null;
Integer userId = null;
try{
tx = session.beginTransaction();
User user = u;
userId = (Integer) session.save(user);
tx.commit();
}catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
}finally {
session.close();
}
return userId;
}
And script to create database is:
CREATE TABLE "user"
(
id_user serial NOT NULL,
api_key character varying(255),
email character varying(255) NOT NULL,
name character varying(255) NOT NULL,
password character varying(255) NOT NULL,
is_admin boolean NOT NULL,
enabled boolean NOT NULL,
CONSTRAINT user_pkey PRIMARY KEY (id_user),
CONSTRAINT user_email_key UNIQUE (email)
)
WITH (
OIDS=FALSE
);
ALTER TABLE "user"
OWNER TO postgres;
You need to change the DB table id_user to:
id_user bigint NOT NULL
You don't need the serial type, since it's Hibernate assigning the id column using a sequence call.
If you wanted to have the database in charge of assigning ids, then the SEQUENCE generator would simply compete against the database id generation strategy.
In that case you would need a "select" generator instead.

hibernate: objects created in wrong order?

I just switched from XML mapping to annotations and had to realize that my serialization class does not work any more!
I hope you can help me to find out the reason :)
I have a School class that contains an Address
#Entity
#Table(name="schools")
public class School {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name = "id")
private Long id;
#ManyToOne
#JoinColumn(name="address_id", nullable=true)
private Address address;
...
}
the Address class:
#Entity
#Table(name="addresses")
public class Address {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name = "id")
private Long id;
#Column(name="street", nullable=false, updatable=true)
private String street; // with nr
...
}
I try to serialize like this:
sessionFactory = MyFactory.getSessionFactory();
session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
School mbs = new School("interesting school");
Address a = new Address("garden street 5","12345", "somewhere");
mbs.setAddress(a);
session.save(mbs);
tx.commit();
This worked before with XML, but now doesn't..
The first Hibernate query action visible on the console is:
Hibernate: insert into schools (address_id, layout_id, name) values (?, ?, ?)
Therefore an error occurs: ERROR: Column 'address_id' cannot be null
How can I fix this?
.
Those are the tables:
CREATE TABLE schools(
id INTEGER NOT NULL AUTO_INCREMENT,
name CHAR(50),
address_id INTEGER NOT NULL,
layout_id INTEGER NOT NULL,
CONSTRAINT fk_address FOREIGN KEY (address_id) REFERENCES addresses(id),
CONSTRAINT fk_layout FOREIGN KEY (layout_id) REFERENCES layout_headers(id),
PRIMARY KEY (id)
);
CREATE TABLE addresses(
id INTEGER NOT NULL AUTO_INCREMENT,
street CHAR(55),
zip CHAR(6),
city CHAR(60),
CONSTRAINT addr_pk PRIMARY KEY (id)
);
In my hibernte.cfg.xml I have the following:
<hibernate-configuration>
<session-factory>
...
<mapping class="creator.models.school.Address" />
<mapping class="creator.models.school.Report" />
<mapping class="creator.models.school.School" />
<mapping class="creator.models.school.SchoolClass" />
...
</session-factory>
</hibernate-configuration>
You should specify cascade property of #ManyToOne annotation on address field of School class to save address before school. For example, CascadeType.ALL

Categories

Resources