How to Spring JPA save String array data to database using hibernate - spring

I'm new to Spring. Try to save following model to mysql using JPA
#Table(name = "PRODUCTORDER")
public class Order extends AbstractPersistable<Long> {
#Length(min = 4, max = 30)
private String name;
#Length(min = 4, max = 50)
private String address;
#NotEmpty
private String[] items; // error for this
// only items setter and getter shown
public String[] getItems() {
return items;
}
public void setItems(String[] items) {
this.items = items;
}
}
I have a table in mySQL as :-
CREATE TABLE PRODUCTORDER (
id int(6) NOT NULL AUTO_INCREMENT,
name varchar(30) NOT NULL,
address varchar(50) NOT NULL,
items varchar(50) not null,
PRIMARY KEY(id)
)
ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
When I tried to save data I get this error:-
org.springframework.orm.jpa.JpaSystemException:
org.hibernate.exception.GenericJDBCException: Incorrect string value: '\xAC\xED
\x00\x05ur...' for column 'items' at row 1; nested exception is
javax.persistence.PersistenceException:org.hibernate.exception.GenericJDBCException:
Incorrect string value: '\xAC\xED\x00\x05ur...' for column 'items' at row 1

Related

Unable to persist an object in mariadb, Caused by: org.mariadb.jdbc.internal.util.dao.QueryException: You have an error in your SQL syntax;

I am trying to persist an object using the entity manager in a springboot application.
but I am getting the below exception
Caused by: java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'interval, last_updated) values ('5MIN', '2023-02-01 00:56:16')' at line 1
Query is : insert into cms_kpi_config (interval, last_updated) values ('5MIN', '2023-02-01 00:56:16.0')
at org.mariadb.jdbc.internal.util.ExceptionMapper.get(ExceptionMapper.java:125)
at org.mariadb.jdbc.internal.util.ExceptionMapper.throwException(ExceptionMapper.java:69)
at org.mariadb.jdbc.MariaDbStatement.executeQueryEpilog(MariaDbStatement.java:242)
at org.mariadb.jdbc.MariaDbClientPreparedStatement.executeInternal(MariaDbClientPreparedStatement.java:210)
at org.mariadb.jdbc.MariaDbClientPreparedStatement.executeUpdate(MariaDbClientPreparedStatement.java:186)
at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeUpdate(NewProxyPreparedStatement.java:384)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:204)
... 223 more
Caused by: org.mariadb.jdbc.internal.util.dao.QueryException: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'interval, last_updated) values ('5MIN', '2023-02-01 00:56:16')' at line 1
Query is : insert into cms_kpi_config (interval, last_updated) values ('5MIN', '2023-02-01 00:56:16.0')
at org.mariadb.jdbc.internal.protocol.AbstractQueryProtocol.getResult(AbstractQueryProtocol.java:939)
at org.mariadb.jdbc.internal.protocol.AbstractQueryProtocol.executeQueries(AbstractQueryProtocol.java:775)
at org.mariadb.jdbc.MariaDbClientPreparedStatement.executeInternal(MariaDbClientPreparedStatement.java:201)
... 226 more
I don't seem to understand what the problem is.
here is my table definition
CREATE TABLE IF NOT EXISTS `cms_kpi_config` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`interval` enum('5MIN','30MIN','60MIN') NOT NULL DEFAULT '5MIN',
`last_updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
here is my Entity
#Entity
#Table(name = "cms_kpi_config")
#JsonInclude(JsonInclude.Include.NON_NULL)
public class CmsKPIConfig {
private Integer id;
private String interval;
private Date lastUpdated;
#Id
#Column(name = "id", nullable = false, unique = true)
#GeneratedValue(strategy = GenerationType.IDENTITY)
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
#Column(name = "interval", nullable = false)
#NotNull
public String getInterval() {
return interval;
}
public void setInterval(String interval) {
this.interval = interval;
}
#Column(name = "last_updated")
#JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
public Date getLastUpdated() {
return lastUpdated;
}
public void setLastUpdated(Date lastUpdated) {
this.lastUpdated = lastUpdated;
}
}
In my Dao service class, I'm using entitymanager as below.
private EntityManager manager;
this.manager.persist(obj);
Please help

Primary key violation when inserting child entity

DB Schema (H2 database):
create table book (
id_book bigint auto_increment not null primary key,
title varchar(255) not null,
id_author bigint not null,
id_genre bigint not null
);
create table comment (
id_comment bigint auto_increment not null primary key,
id_book bigint not null,
comment_text varchar(255) not null
);
Domain classes:
public class Book {
#Id
#Column("id_book")
private Long id;
private String title;
#Column("id_author")
AggregateReference<Author, Long> author;
#Column("id_genre")
AggregateReference<Genre, Long> genre;
#MappedCollection(idColumn = "id_book", keyColumn = "id_comment")
List<Comment> comments = new ArrayList<>();
public void addComment(String commentText) {
comments.add(new Comment(commentText));
}
//getters and setters
}
public class Comment {
#Column("id_comment")
private Long id;
#Column("comment_text")
private String text;
public Comment(String text) {
this.text = text;
}
public Comment() {
}
//getters and setters
}
I have the problem when I add a comment to the book.
```java
#Override
#Transactional
public String addComment(long bookId, String commentText) {
var book = bookRepository.findById(bookId);
return book.map(b -> {
b.addComment(commentText);
b = bookRepository.save(b);
return bookConverter.convertToString(b);
}).orElse("Book not found!");
}
It generates SQL like this...
Executing SQL batch update [INSERT INTO "COMMENT" ("comment_text", "id_book", "id_comment") VALUES (?, ?, ?)]
... adds values for id_comment field like 0, 1, 2, 3 and these values intersect with existing ones. So I get Primary Key Violation. Why it adds id_comment field to the INSERT expression?
Why it adds id_comment field to the INSERT expression?
Because you told it to.
The following annotation tells Spring Data JDBC to store the index of the list in the id_comment column.
#MappedCollection(idColumn = "id_book", keyColumn = "id_comment")
Your data model is missing a column for the list index. Add that column and use it as keyColumn in the #MappedCollection annotation

spring sql Invalid column name

getting
com.microsoft.sqlserver.jdbc.SQLServerException: Invalid column name
'partnerIdPartner'.
application.properties:
spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
Table creation:
CREATE TABLE [partnersystem] (
[idPartnerSystem] INT IDENTITY(1,1) ,
[partner_idPartner] INT NOT NULL DEFAULT NULL ,
[Name] NVARCHAR(45) NULL DEFAULT NULL ,
[Domain] NVARCHAR(45) NULL DEFAULT NULL ,
[Code] NVARCHAR(45) NULL DEFAULT NULL ,
[PartnerSystem_idSystem] INT NOT NULL DEFAULT NULL ,
[UpdateUser] NVARCHAR(45) NULL DEFAULT NULL ,
[UpdateDT] DATETIME NULL DEFAULT NULL ,
CONSTRAINT [partnersystem_PRIMARY] PRIMARY KEY CLUSTERED ([idPartnerSystem]), CONSTRAINT [partnersystem_fk_PartnerSystem_partner] FOREIGN KEY ("partner_idPartner") REFERENCES "partner" ( "idPartner" ) ON UPDATE NO ACTION ON DELETE NO ACTION, CONSTRAINT [partnersystem_fk_PartnerSystem_System] FOREIGN KEY ("PartnerSystem_idSystem") REFERENCES "system" ( "idSystem" ) ON UPDATE NO ACTION ON DELETE NO ACTION);
CREATE INDEX [partnersystem_fk_PartnerSystem_partner] ON [partnersystem] ([partner_idPartner]);
CREATE INDEX [partnersystem_fk_PartnerSystem_System] ON [partnersystem] ([PartnerSystem_idSystem]);
JPA Entity:
#Entity
#Table(name = "partnersystem")
public class PartnerSystem {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "idPartnerSystem")
private int idPartnerSystem;
#Column(name = "partner_idPartner" )
private int partnerIdPartner;
#Column(name = "Name")
private String name;
#Column(name = "Domain" )
private String domain;
#Column(name = "Code" )
private String code;
#Column(name = "PartnerSystem_idSystem" )
private int partnerSystemIdSystem;
#Column(name = "UpdateUser" )
private String updateUser;
my repository:
#Repository
public interface PartnerSystemRepository extends JpaRepository<PartnerSystem,
Integer>{
public PartnerSystem findByPartnerIdPartner(int partnerIdPartner);
}
executing simple query throws an error.
public List<Object[]> findAllPartnerSystem(int id) {
String test =
"SELECT idPartnerSystem, partnerIdPartner, name, domain, code, partnerSystemId" +
" FROM PartnerSystem " +
"WHERE partnerIdPartner = ?"
;
Query query = em.createNativeQuery(test);
query.setParameter(1, id);
List<Object[]> results = query.getResultList();
for (Object[] row : results) {
}
return results;
}
In native queries you have to use the column name not the property name:
"SELECT idPartnerSystem, partner_idPartner, name, domain, code, PartnerSystem_idSystem" +
" FROM partnersystem " +
"WHERE partner_idPartner=
But I suggest using JPQL queries and not native queries.

Spring - Hibernate ManyToMany in Restful app

i have my spring app running with two entities Article and Category.
I integrated RestResponses and it works all fine. Next i added a ManyToMany Relationship to these entities and my rest responses return 404.
I will show you my configuration:
DROP TABLE IF EXISTS `articles`;
create table `articles` (
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1;
DROP TABLE IF EXISTS `categories`;
create table `categories` (
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1;
DROP TABLE IF EXISTS `categories_articles`;
CREATE TABLE IF NOT EXISTS `categories_articles` (
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`categoryID` int(11) UNSIGNED NOT NULL,
`articleID` int(11) UNSIGNED NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `categoryArticleID` (`categoryID`, `articleID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1;
ALTER TABLE `categories_articles`
ADD CONSTRAINT `categories_articles_fk_1` FOREIGN KEY (`categoryID`) REFERENCES `categories` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `categories_articles_fk_2` FOREIGN KEY (`articleID`) REFERENCES `articles` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
Article.java:
#Entity
#Table(name = "articles")
public class Article {
#Id
#Column(name="id")
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
#Column(name="name")
private String name;
private List<Category> categories = new ArrayList<Category>();
public Article() {
}
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
#ManyToMany(mappedBy = "articles")
public List<Category> getCategories() {
return categories;
}
public void setCategories(List<Category> categories) {
this.categories = categories;
}
}
Category.java:
#Entity
#Table(name = "categories")
public class Category {
#Id
#Column(name="id")
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
#Column(name="name")
private String name;
private List<Article> articles = new ArrayList<Article>();
public Category() {
}
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(
name = "categories_articles",
joinColumns = #JoinColumn(name = "categoryID", referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(name = "articleID", referencedColumnName = "id"))
public List<Article> getArticles() {
return articles;
}
public void setArticles(List<Article> articles) {
this.articles = articles;
}
}
And my RestController:
#GetMapping("/rest/categories")
public RestResponse<Category> list() {
List<Category> data = categoryService.list();
RestResponse<Category> restResponse = new RestResponse<Category>(true, data.size(), data);
return restResponse;
}
where RestResponse is just a simple PoJo:
public class RestResponse<T> {
private Boolean success;
private Integer count;
private List<T> data;
public RestResponse(Boolean success, Integer count, List<T> data) {
this.success = success;
this.count = count;
this.data = data;
}
// getters and setters
}
Sooo, as soon as i comment the many-to-many part and load my app, it all works fine.. but when i uncomment the many-to-many part, i get 404..
I have no idea why, could anybody help me with this issue?
thanks and greetings!

extra NULL item in spring-jpa one-to-many list attribute

spring-jpa with hibernate and mysql 5.7 (dependency managed by spring platform-bom-1.1.4.RELEASE)
Entity class:
#Entity
#Table(name = "activity")
public class ActivityEntity
{
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Integer id;
// optional
#Column(name="project_id")
private Integer projectId;
#OneToOne(fetch=FetchType.EAGER)
#JoinColumn(name="container_id")
private ActivityEntity container;
#OneToMany(mappedBy="container", cascade={CascadeType.ALL}, fetch=FetchType.EAGER)
#OrderColumn(name="order")
private List<ActivityEntity> activities;
private String name;
private String description;
...
}
DAO class:
public interface IActivityDao extends JpaRepository<ActivityEntity, Integer>
{
List<ActivityEntity> findByContainerId(int containerId);
}
Database table:
CREATE TABLE `activity` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`project_id` bigint(20) DEFAULT NULL,
`container_id` bigint(20) DEFAULT NULL,
`name` varchar(128) NOT NULL,
`description` varchar(256) DEFAULT NULL,
`type` varchar(32) NOT NULL,
`mode` varchar(32) NOT NULL,
`tag` varchar(32) DEFAULT NULL,
`script` longtext,
`order` int(11) DEFAULT '1',
`created_user_id` varchar(45) DEFAULT NULL,
`created_date` datetime DEFAULT NULL,
`updated_user_id` varchar(45) DEFAULT NULL,
`updated_date` datetime DEFAULT NULL,
`projectId` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `container_id` (`container_id`),
CONSTRAINT `fk_container_id` FOREIGN KEY (`container_id`) REFERENCES `activity` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=214 DEFAULT CHARSET=utf8;
Database table content:
Unit Test Code:
public class ActivityDaoTest extends AbstractDaoTest
{
#Resource
private IActivityDao activityDao;
#Test
public void testFindOne() throws Exception {
ActivityEntity activity = activityDao.findOne(210);
ActivityEntity root = activity.getContainer();
int level = 0;
printActivity(activity, level);
Assert.assertNotNull(activity);
if (root != null) {
level = 0;
printActivity(root, level);
}
}
...
}
In the above test code, root.getActivities() and activity.getActivities() return 5 and 4 items respectively, with the first item to be null.
Do I miss something in the entity? Thanks for help.
I'll answer my won question (posted too early):
Remove the order attribute from the Entity
The value of the order column in the table starts from 0 (the NULL item is for the index of 0 in the list)
That solves my problem.

Resources