CrudRepository referencing a column wrong from database - java

I am trying to retrieve a list from a crudRepository by doing a .findAll() request and then pass it onto a html which lists them in a table. It retrieves the data fine except for the Dates which gives me a strange error. I am using Postgresql.
My create table sql:
--Table:conference_table
CREATE TABLE conference_table (
conference_id SERIAL NOT NULL,
user_id INT NOT NULL,
name VARCHAR(32),
description VARCHAR(255),
startConference DATE,
endConference DATE,
PRIMARY KEY (conference_id),
FOREIGN KEY (user_id) REFERENCES user_table(user_id)
);
In my conference.java I have:
#Column(name = "startConference")
private Date startConference;
#Column(name = "endConference")
private Date endConference;
In my controller class I have the method:
#GetMapping(path="/configure")
public String showConfigurePage(Model model){
List<Conference> conferenceList = conferenceRepository.findAll(); // This gives me the error
model.addAttribute("conferenceList", conferenceList);
return "configure";
}
Error:
org.postgresql.util.PSQLException: ERROR: column conference0_.end_conference does not exist
Hint: Perhaps you meant to reference the column "conference0_.endconference".
Any ideas why this might be happening? I can provide further info if I missed any.

What you see is correct behavior: The default strategy for #Column(name="endConference") is end_conference.
You can add below config to application.properties to follow PhysicalNamingStrategy:
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
Check this and this for more info.
References:
SO Answer
SO Answer

Related

Hibernate ignoring changes in schema.sql

I'm developing an application with Spring Boot and hibernate, which connects to a postgres instance running in docker. When I first created my schema.sql, it looked like this:
CREATE TABLE groups(
group_id varchar(255) PRIMARY KEY,
group_desc varchar(255),
group_name varchar(255)
);
The table created successfully, however I soon realized 255 is too short for my purposes and changed my schema to the following:
CREATE TABLE groups(
group_id text PRIMARY KEY,
group_desc text,
group_name text
);
However, the database keeps reverting to the original data types. I've tried dropping the table, however when the Spring app runs and it gets created again as varchar(255) instead of text. How do I force hibernate to use the updated schema?
I've tried changing the spring.jpa.hibernate.ddl-auto property to create and update, and tried changing the fields to other datatypes, including other lengths of varchar. Nothing has worked so far. Even deleting schema.sql seemingly has no effect.
My application.properties looks like this:
spring.jpa.database=POSTGRESQL
spring.datasource.platform=postgres
spring.datasource.url=jdbc:postgresql://localhost:5432/postgres
spring.datasource.username=<redacted>
spring.datasource.password=<redacted>
spring.jpa.show-sql=true
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
The Text datatype is not a Varchar but a CLOB.
Check your Groups class. I guess the name and desc attributes are String and the default related db type is then VARCHAR(255). Thus, if you generate your schema from your entity, String always become VARCHAR(255)
If you want to use Text, your field should be annotated with #Lob
public class Groups {
#Lob
#Column(name = "group_desc")
private String desc
#Lob
#Column(name = "group_name")
private String name
}
This being stated, I think you should change your java/db model because having a Lob/Text type as primary/foreign key frightens me a little (even if I never tried)
CREATE TABLE groups(
group_id bigint PRIMARY KEY,
group_code text NOT NULL UNIQUE,
group_desc text,
group_name text
);
public class Groups {
#Id
#Column(name = "group_id")
private Long id;
#Lob
#Column(name = "group_code", nullable = false, unique = true)
private String code;
#Lob
#Column(name = "group_desc")
private String desc;
#Lob
#Column(name = "group_name")
private String name;
}
NB : I usually don't generate the schema from entities so I instead use the code below to map a db text field to entity attribute :
#Column(name = "group_desc", columnDefinition = "CLOB")
private String desc;
But I am not sure if this is handled correctly to generate the schema

Error inserting a new entity into the database because it conflicts with a duplicate key value

Im trying to create CRUD test to show my JPA program works but it is giving me strange error when i create a new entity and commit it to the database.
The Table supplier have only one contraint and that is a unique index that is autogenerated.
i will post the classes first then what i tried to do with them
Here is the SQL for the table and contraints
-- DDL for Table SUPPLIER
CREATE TABLE SUPPLIER
( SUPPLIERID INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY,
COMPANYNAME VARCHAR(40),
CONTACTNAME VARCHAR(30),
CONTACTTITLE VARCHAR(30),
ADDRESS VARCHAR(60),
CITY VARCHAR(15),
POSTALCODE VARCHAR(10),
COUNTRY VARCHAR(15),
PHONE VARCHAR(24),
FAX VARCHAR(24)
);
-- Constraints for Table SUPPLIER
ALTER TABLE SUPPLIER ALTER SUPPLIERID NOT NULL;
ALTER TABLE SUPPLIER ALTER COMPANYNAME NOT NULL;
ALTER TABLE SUPPLIER ADD CONSTRAINT PK_SUPPLIER PRIMARY KEY (SUPPLIERID);
This is my suppliers Primary key:
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "SUPPLIERID")
private Integer supplierid;
So first i create the entity and add it to my entitymanager
Supplier sup = new Supplier("Test","Test","Test","Test","Test","Test","Test","Test","Test");
em.persist(p);
Then i save it
public void Save() {
em.getTransaction().begin();
em.getTransaction().commit();
}
And then i get the error below even thought the only constraint that can be broken is 2 identical pk but those are auto generated.
I know that my setup works because my 2 other tests ( inserting other new entities works fine).
I also close and reopen connection between each test.
[EL Warning]: 2014-09-09 17:17:33.67--UnitOfWork(1407675409)--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.1.v20130918-f2b9fc5): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLIntegrityConstraintViolationException: The statement was aborted because it would have caused a duplicate key value in a unique or primary key constraint or unique index identified by 'PK_SUPPLIER' defined on 'SUPPLIER'.
Error Code: -20001
Call: INSERT INTO SUPPLIER (ADDRESS, CITY, COMPANYNAME, CONTACTNAME, CONTACTTITLE, COUNTRY, FAX, PHONE, POSTALCODE) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
bind => [9 parameters bound]
Query: InsertObjectQuery(Peristency.Supplier[ supplierid=null ])
The save method irritates me a little. Like it is written above, it performs an empty transaction, doesn't it? Shouldn't it be something like this:
public void Save() {
...
em.getTransaction().begin();
...
Supplier sup = new Supplier("Test","Test","Test","Test","Test","Test","Test","Test","Test");
em.persist(p);
...
em.getTransaction().commit();
...
}
Could it be, that the coding for the question has been shortened too much, thus scrumbling the picture? Could you provide us please with the complete coding from starting the whole transaction until committing?
I remember once a while, I had a similar problem. Main point was, that I tried to persist twice in one transaction - and that was not possible - complaining about a duplicated key problem. May be that this is a hint for your case.
Okay after alot of Wall to face action i have found the cause of my problem
If you try to commit(entitymanager.getTransaction.commit()) a entity with a null pk to the database it wont work even if the database is supposed to provide the id.
What i had to do everytime i need a new object in a state where it can be saved to the db
public void addEmployee(Employee p) {
em.getTransaction().begin();
em.persist(p);
//Doesn't have an id
System.out.println(p.getEmployeeid());
em.flush();
//now it has an id!
System.out.println(p.getEmployeeid());
em.getTransaction().commit();
}
Then later i can merge and commit at my leasure but i feel like i made a ineffecient solution with the database transaction i have.

save XML to mysql using hibernate

I want to save an XML file into LONGTEXT field mysql through hibernate. I'm a bit new to hibernate and really appropriate your advice.
mysql table was created.
CREATE TABLE testdata (
TD_ID INT(11) NOT NULL AUTO_INCREMENT,
XML_VAL LONGTEXT NULL,
PRIMARY KEY (TD_ID)
Hibernate entity is also created.
#Lob
#Column(name="XML_VAL")
public String getXmlVal() {
return xmlVal;
}
public void setXmlVal(String xmlVal) {
this.xmlVal = xmlVal;
}
No need to use #Lob.
#Column(name = "XML_VAL", length = 65535)
You define the length of your text which needs to be inserted.

Getting foreign key and refering table name of particular database table from metadata DatabaseMetaData using JAVA class

I am writing java class to get all connection database objects(tables). I have used
rs = meta.getExportedKeys(conn.getCatalog(), null, "account_adjustment");
while (rs.next()) {
String fkTableName = rs.getString("FKTABLE_NAME");
String fkColumnName = rs.getString("FKCOLUMN_NAME");
int fkSequence = rs.getInt("KEY_SEQ");
}
which is giving parent table and it's column linked this asked table(account_adjustment)
and also I tried
rs1 = meta.getImportedKeys(conn.getCatalog(), null, "account_adjustment");
while (rs1.next()) {
String fkTableName = rs1.getString("FKTABLE_NAME");
String fkColumnName = rs1.getString("FKCOLUMN_NAME");
int fkSequence = rs1.getInt("KEY_SEQ");
}
which is giving current table(account_adjustment) table and it's foreign key column name
but I want table name with which this foreign key is linked
I have got solution bt in other way not using java,, instead of getting values using java i executed query to 'information_schema' (which is there by default in MySQL) database and 'REFERENTIAL_CONSTRAINTS' table to get all reference of respective tables of required database

Hibernate Duplicate entry '7090' for key 'PRIMARY'

Im getting following error when the application tries to insert a record row in the db.
SQL Error: 1062, SQLState: 23000
ERROR org.hibernate.util.JDBCExceptionReporter - Duplicate entry '7089' for key 'PRIMARY'
ERROR org.hibernate.event.def.AbstractFlushingEventListener - Could not synchronize database state with session
Caused by: java.sql.BatchUpdateException: Duplicate entry '7090' for key 'PRIMARY'
at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1269)
at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:955)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:48)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:242)
The definition is
#Id
#Column(name = "CST_CUSTOMER_ID_PK")
#GenericGenerator(name = "generator", strategy = "increment")
#GeneratedValue(generator = "generator")
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
The part at which the error occurs is :
savedCustomer = customerDao.save(customer);
mtmrsLogger.debug("saved customer id:" + savedCustomer.getId());
/**
* Updating Customer Trans Table
*/
updateCustomerTransForMakerChecker(customer, customerform.getAuditDetails());
/**
* Updating Customer Audit
*/
updateCustomerAuditForMakerChecker(customer, customerform.getAuditDetails());
//status=1;
//Add customer ewallet account
updateCustomerInWalletBalance(customer, customerform.getAuditDetails());
//send sms to customer
smsManager.sendSMSToCUCustomer(customer.getMobileno(), userBean);
}
mtmrsLogger.exiting("CustomerManagerImpl", "addCustomer");
My log shows, program has reached ' Exiting Class: CustomerManagerImpl Method: addCustomer' this part. Im saving the customer ,im setting the same entry in other two tables. The primary key of customer table is foreigh key in other two tables. Im lost please help.
CREATE TABLE `CST_CUSTOMER_INFO` (
`CST_CUSTOMER_ID_PK` bigint(11) NOT NULL AUTO_INCREMENT,
`CST_MOBILE` varchar(30) DEFAULT NULL,
`CST_FIRST_NAME` varchar(50) DEFAULT NULL,
`CST_LAST_NAME` varchar(150) NOT NULL,
`CST_MIDDLE_NAME` varchar(50) DEFAULT NULL,
PRIMARY KEY (`CST_CUSTOMER_ID_PK`)
) ENGINE=InnoDB AUTO_INCREMENT=4103 DEFAULT CHARSET=latin1
Im getting error occassionally in production , but in local its ok..
As table is being modified by more than one application, use of #GenericGenerator(name = "generator", strategy = "increment") will result in ambiguity.
Explanation
Strategy increment : It generates identifiers of type long, short or
int that are unique only when no other process is inserting data into
the same table. It should not be used in the clustered environment.
So you should rethink what strategy is to be used to generate id's. Using sequence or native strategy can resolve your problem.
Replace
`CST_CUSTOMER_ID_PK` bigint(11) NOT NULL AUTO_INCREMENT,
with
`CST_CUSTOMER_ID_PK` bigint(11) NOT NULL,
You are incrementing the id using hibernate/java, no need to make the DBMS increment it also.

Categories