save XML to mysql using hibernate - java

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.

Related

CrudRepository referencing a column wrong from database

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

Persist entity using Java Hibernate API and update if already exists

Have the following table and Java Entity:
CREATE TABLE search_terms (
id int(100) NOT NULL AUTO_INCREMENT,
term varchar(255) NOT NULL DEFAULT '',
last_search_date timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
search_count int(100) NOT NULL DEFAULT '0',
user_email varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;
public class SearchTerms implements Serializable {
private Long id;
private String term;
private Timestamp lastSearchDate;
private int searchCount;
private String userEmail;
Want to persist java objects of the given type into the table above.
Example:
List<String> searchTerms = Arrays.asList("test1", "test2", "test3");
saveSearchParams(searchTerms);
If any of those terms exist in the table, I want to increment searchCount else save as a new row.
Need to use JPA.em().merge(o) etc and not have sql insert/update queries
Added the following constant on the two columns but JPA.em().merge(o) keeps inserting new rows.
#Table(name="search_terms", uniqueConstraints= { #UniqueConstraint(columnNames = {"term", "user_email"})})
saveSearchParams() {
searchTerms.forEach(o -> {
SearchTerms term = new SearchTerms();
term.setSearchCount(1);
term.setTerm((String) o);
term.setUserEmail(email);
jpaApi.em().merge(term);
});
}
Any help on or documentation is appreciated.
Merge can both update and insert, but you should check if the object exists in DB to see if you have to set the counter to one or add one to it, for this you will have to throw a query for each element.
try this:
saveSearchParams() {
searchTerms.forEach(o -> {
//search for example by id or in any other way
SearchTerms term = jpaApi.em().find(SearchTerms.class, o.getId());
if (term == null){
term = new SearchTerms();
term.setSearchCount(1);
}else{
term.setSearchCount(term.getSearchCount()+1);
}
term.setTerm((String) o);
term.setUserEmail(email);
jpaApi.em().merge(term);
});
}

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

Ways to dynamically change SQL database through JafaFx table Cell editing

My javaFx application has many tables with editable table cells to populate data from sql database.I also want to make changes in database after data editing through table cells.According to this toturial "https://docs.oracle.com/javafx/2/ui_controls/table-view.htm"
I have created my editable table cell with the following code.
item_price_col.setCellValueFactory(
new PropertyValueFactory("price")
);
item_price_col.setCellFactory(TextFieldTableCell.forTableColumn());
item_price_col.setOnEditCommit(
new EventHandler<CellEditEvent<Item, String>>() {
#Override
public void handle(CellEditEvent<Item,String> t) {
String old_price=t.getOldValue();
((Item) t.getTableView().getItems().get(
t.getTablePosition().getRow())
).setPrice(t.getNewValue());
String new_price=t.getNewValue();
System.out.println("Old Price:"+old_price);
System.out.println("New Price:"+new_price);
}
}
);
But it doesn't make any changes in database after editing.So,I think have to write update Query inside of that handle method.But I can only know old value and new value. I can't make query statement like that "update item set price=new_price where price=old_price".If I update a single price of a item to new value,every items in my item table that have the same price with my edited item will make changes to new price value.Are there any ways to solve this problem?
Here is my item table structure.
item | CREATE TABLE `item` (
`code` int(11) NOT NULL,
`name` varchar(50) DEFAULT NULL,
`price` varchar(50) NOT NULL,
`whole_sale_price` varchar(50) NOT NULL,
`orginal_price` varchar(50) DEFAULT NULL,
PRIMARY KEY (`code`),
UNIQUE KEY `code` (`code`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
Keep an id field to your item as it is given in the database.
If you have not primary or unique key in the database probably you made some architectural mistake. Anyway there is a row id specified in some database servers.
private int id; // id field for item object.
While updating include id as condition.
update sometable set price = item.getPrice() where id = item.getId();
I know sql is not well written but I hope you'll get it
And you don't have to show value of id field in your table grid.
This technique is used in most systems
EDITED 2015.12.18
You have code column in the table. Retrieve by jdbc into your item object's id field.
There is an example
http://www.tutorialspoint.com/jdbc/jdbc-update-records.htm

JPA joined column allow every value

I'm testing JPA, in a simple case File/FileVersions tables (Master/Details), with OneToMany relation, I have this problem: in FileVersions table, the field "file_id" (responsable for the relation with File table) accepts every values, not only values from File table.
How can I use the JPA mapping to limit the input in FileVersion.file_id only for values existing in File.id?
My class are File and FileVersion:
FILE CLASS
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="FILE_ID")
private Long id;
#Column(name="NAME", nullable = false, length = 30)
private String name;
//RELATIONS -------------------------------------------
#OneToMany(mappedBy="file", fetch=FetchType.EAGER)
private Collection <FileVersion> fileVersionsList;
//-----------------------------------------------------
FILEVERSION CLASS
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="VERSION_ID")
private Long id;
#Column(name="FILENAME", nullable = false, length = 255)
private String fileName;
#Column(name="NOTES", nullable = false, length = 200)
private String notes;
//RELATIONS -------------------------------------------
#ManyToOne(fetch=FetchType.EAGER)
#JoinColumn(name="FILE_ID", referencedColumnName="FILE_ID", nullable=false)
private File file;
//-----------------------------------------------------
and this is the FILEVERSION TABLE
CREATE TABLE `JPA-Support`.`FILEVERSION` (
`VERSION_ID` bigint(20) NOT NULL AUTO_INCREMENT,
`FILENAME` varchar(255) NOT NULL,
`NOTES` varchar(200) NOT NULL,
`FILE_ID` bigint(20) NOT NULL,
PRIMARY KEY (`VERSION_ID`),
KEY `FK_FILEVERSION_FILE_ID` (`FILE_ID`)
) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=latin1
Thanks for help,
I know the SQL constraint to limit the input, but it is possible to create this SQL costraint using some annotation, without writing by hand the SQL in the database?
I'm new on JPA, I was thinking that using #JoinColumn annotation, JPA could create also the costraint...
Thank you again.
At the Java level, you describe and annotate associations between classes - which and you did - and your mapping looks fine.
At the database level, if you want to restrict the possible values in the file_id column to values that are primary keys in the FILE table, you should use a foreign key constraint. To do so, you will need to use InnoDB tables. Something like that:
CREATE TABLE `JPA-Support`.`FILEVERSION` (
`VERSION_ID` bigint(20) NOT NULL AUTO_INCREMENT,
`FILENAME` varchar(255) NOT NULL,
`NOTES` varchar(200) NOT NULL,
`FILE_ID` bigint(20) NOT NULL,
PRIMARY KEY (`VERSION_ID`),
FOREIGN KEY `FK_FILEVERSION_FILE_ID` (`FILE_ID`) REFERENCES FILE(ID)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1
The table FILE also has to use InnoDB. Actually, use InnoDB tables for the tables for which you want to use referential integrity.

Categories