Exception with Orika Mapper + Gson (JSON) + MySQL - mysql

I'm trying to implement some kind of "poll system" on my web based on Spring MVC + MySQL. The problem I'm having is that I have 2 classes I'm trying to map. One is the DTO which I use to move the data through the web, and the other one is the one I use to access the database with Hibernate. So far, so good.
The idea I'm trying to implement is having a few Lists on the DTO, transform them into a JSON and afterwards saving them on the database (as a String).
Now, in order to map these 2 objects I'm using an Orika Custom Map. The funny thing that happens to me is that I'm able to save the lists I have into the database as JSON (I'm using GSON to convert them), but when I need them back, Orika throws and exception.
I'll try now to put my code as clear as possible to see if someone can help me. As I'm telling you, when the time comes to save the data, I have no problem at all, but when I need to get it out (getting the string, parsing it to a JSON and afterwards to a List), it collapses. Any ideas?? Thanks in advance
ORIKA MAPPING
mapperFactory.classMap(EncuestaDTO.class, Encuesta.class).mapNulls(false).byDefault().customize(new CustomMapper<EncuestaDTO, Encuesta>(){
#Override
public void mapAtoB(EncuestaDTO a, Encuesta b, MappingContext context){
Type listTypeString = new TypeToken<List<String>>(){}.getType();
/************ Respuestas */
String respuestas = new Gson().toJson(a.getRespuestas(), listTypeString);
b.setRespuestas(respuestas);
}
#Override
#SuppressWarnings("unchecked")
public void mapBtoA(Encuesta b, EncuestaDTO a, MappingContext context){
Type listTypeString = new TypeToken<List<String>>(){}.getType();
/************ Respuestas */
List<String> respuestas = new Gson().fromJson(b.getRespuestas(), listTypeString);
a.setRespuestas(respuestas);
}
}).register();
Encuesta
#Id
#Column(name = "idEncuesta", unique = true, nullable = false)
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long idEncuesta;
#Column(name = "idCreador", nullable = false)
private Long idCreador;
#Column(name = "pregunta")
private String pregunta;
#Column(name = "respuestas")
private String respuestas;
#Column(name = "numRespuestas")
private Long numRespuestas;
#Column(name = "fechaCreacion")
private Date fechaCreacion;
#Column(name = "fechaFin")
private Date fechaFin;
#Column(name = "oficial")
private boolean oficial;
EncuestaDTO
private Long idEncuesta;
private Long idCreador;
private String pregunta;
private List<String> respuestas;
private Long numRespuestas;
private Date fechaCreacion;
private Date fechaFin;
private boolean oficial;
MANAGER
#Override
public void aniadirEncuesta(EncuestaDTO encuestaDTO) {
encuestaRepositorio.aniadirEncuesta(mapper.map(encuestaDTO, Encuesta.class));
}
#Override
public List<EncuestaDTO> getListaEncuestas() {
List<Encuesta> listaEncuesta = (List<Encuesta>) encuestaRepositorio.getListaEncuestas();
return mapper.mapAsList(listaEncuesta, EncuestaDTO.class); // HERE I GET THE ERROR
}
EXCEPTION
GRAVE: El Servlet.service() para el servlet [appServlet] en el contexto con ruta [/myApp] lanzó la excepción [Request processing failed; nested exception is ma.glasnost.orika.MappingException: While attempting the folling mapping:
sourceType = String
destinationType = ArrayList<String>
Error occurred: ma.glasnost.orika.MappingException: While attempting the folling mapping:
sourceType = ArrayList<String>
sourceProperty = 1(String)
destinationType = String
destinationProperty = bytes(byte[])
Error occurred: java.lang.IllegalArgumentException: Attempt was made to generate assignment/setter code for [destination.bytes(byte[])] which has no setter/assignment method] con causa raíz
java.lang.IllegalArgumentException: Attempt was made to generate assignment/setter code for [destination.bytes(byte[])] which has no setter/assignment method
at ma.glasnost.orika.impl.generator.VariableRef.assign(VariableRef.java:223)
at ma.glasnost.orika.impl.generator.specification.ObjectToObject.generateMappingCode(ObjectToObject.java:23)
at ma.glasnost.orika.impl.generator.SourceCodeContext.mapFields(SourceCodeContext.java:644)
at ma.glasnost.orika.impl.generator.MapperGenerator.generateFieldMapCode(MapperGenerator.java:252)
at ma.glasnost.orika.impl.generator.MapperGenerator.addMapMethod(MapperGenerator.java:172)
at ma.glasnost.orika.impl.generator.MapperGenerator.build(MapperGenerator.java:72)
at ma.glasnost.orika.impl.DefaultMapperFactory.buildMapper(DefaultMapperFactory.java:1046)
at ma.glasnost.orika.impl.DefaultMapperFactory.lookupMapper(DefaultMapperFactory.java:614)
at ma.glasnost.orika.impl.DefaultMapperFactory.lookupMapper(DefaultMapperFactory.java:581)
at ma.glasnost.orika.impl.MapperFacadeImpl.resolveMapper(MapperFacadeImpl.java:523)
at ma.glasnost.orika.impl.MapperFacadeImpl.resolveMappingStrategy(MapperFacadeImpl.java:203)
at ma.glasnost.orika.impl.DefaultBoundMapperFacade$BoundStrategyCache.getStrategy(DefaultBoundMapperFacade.java:253)
at ma.glasnost.orika.impl.DefaultBoundMapperFacade.map(DefaultBoundMapperFacade.java:136)
at ma.glasnost.orika.generated.Orika_Encuesta_EncuestaDTO_Mapper137715823.mapBtoA(Orika_Encuesta_EncuestaDTO_Mapper137715823.java)
at ma.glasnost.orika.impl.ReversedMapper.mapAtoB(ReversedMapper.java:65)
at ma.glasnost.orika.impl.mapping.strategy.UseCustomMapperStrategy$ForwardMapperReference.map(UseCustomMapperStrategy.java:74)
at ma.glasnost.orika.impl.mapping.strategy.UseCustomMapperStrategy.map(UseCustomMapperStrategy.java:50)
at ma.glasnost.orika.impl.MapperFacadeImpl.mapAsCollection(MapperFacadeImpl.java:633)
at ma.glasnost.orika.impl.MapperFacadeImpl.mapAsList(MapperFacadeImpl.java:386)
at ma.glasnost.orika.impl.MapperFacadeImpl.mapAsList(MapperFacadeImpl.java:716)
at ma.glasnost.orika.impl.ConfigurableMapper.mapAsList(ConfigurableMapper.java:180)
MySQL TABLE
CREATE TABLE `encuestas` (
`idEncuesta` int(11) NOT NULL AUTO_INCREMENT,
`idCreador` int(11) NOT NULL,
`pregunta` longtext,
`respuestas` longtext,
`numRespuestas` int(11) DEFAULT NULL,
`fechaCreacion` datetime DEFAULT NULL,
`fechaFin` datetime DEFAULT NULL,
`oficial` tinyint(1) DEFAULT NULL,
PRIMARY KEY (`idEncuesta`),
UNIQUE KEY `idEncuesta_UNIQUE` (`idEncuesta`),
KEY `idCreador_idx` (`idCreador`),
CONSTRAINT `idCreador` FOREIGN KEY (`idCreador`) REFERENCES `usuarios` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

OK, I finally got it. The problem was that Orika tried to map it byDefault and, afterwards, tried to do the custom mapping. That meant that it crashed as it didn't know how to map it by default.
By adding and ".exclude("respuestas")" and later on configure the mapping manually (as shown in the code), I got everything mapped just as I wanted. In terms of code, it would be like this:
mapperFactory.classMap(EncuestaDTO.class, Encuesta.class).mapNulls(false).exclude("respuestas").byDefault().customize(new CustomMapper<EncuestaDTO, Encuesta>()

Related

Spring boot/Hibernate fails creating table

I am getting this warn when I try to start my spring boot application:
2018-09-30 07:34:23.097 INFO 59360 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect
Hibernate: create table social_link (author_username varchar(255) not null, type varchar(255) not null, value varchar(255), primary key (author_username, type)) engine=MyISAM
2018-09-30 07:34:24.067 WARN 59360 --- [ main] o.h.t.s.i.ExceptionHandlerLoggedImpl : GenerationTarget encountered exception accepting command : Error executing DDL via JDBC Statement
Strange thing is that I can execute SQL statement via the SQL workbench without a problem and everything works fine after that.
Here is the entity that is responsible for that table:
#Entity
public class SocialLink {
#EmbeddedId
private SocialLinkKeyEmbeddable id = new SocialLinkKeyEmbeddable();
private String value;
#ManyToOne
#MapsId("author_username")
#JoinColumns({
#JoinColumn(name="author_username", referencedColumnName="author_username")
})
private Author author;
//Getters and setters
}
#Embeddable
public class SocialLinkKeyEmbeddable implements Serializable {
#Column(name = "author_username")
private String author_username;
private String type;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getAuthor_username() {
return author_username;
}
public void setAuthor_username(String author_username) {
this.author_username = author_username;
}
#Override
public int hashCode() {
return super.hashCode();
}
#Override
public boolean equals(Object obj) {
return super.equals(obj);
}
}
public interface SocialLinkRepository extends CrudRepository<SocialLink, SocialLinkKeyEmbeddable> {
}
The problem was with the length of the key. MySQL was pretending it is larger than 1000 bytes. It seems its a common problem with MyISAM storage engine.
In order to fix it I added:
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL55Dialect
to my applicaiton.properties and now the problem is fixed.
Was using this post as reference
#1071 - Specified key was too long; max key length is 1000 bytes
I had a similar problem caused by spring.jpa.database-platform property set to MySQL5Dialect.
Setting the property to MySQL8Dialect or removing it altogether (which enables auto-configuration) solved the problem.
I added a column length to my ID field to prevent the varchar(255) default.
#Entity
public class MyEntity {
#Id
#Column(length = 64)
private String id;
...
}
For those who are only using Hibernate (not Spring), edit the SQL dialect property from hibernate.cfg.xml file, located in src/main/resources folder.
<property name="dialect">org.hibernate.dialect.MySQL55Dialect</property>
Or remove the dialect property altogether.
Error-Caused by: java.sql.SQLSyntaxErrorException: Specified key was too long; max key length is 1000 bytes
operation perform- #Id private String userName;
Solution
step1-Go to mysql database--> step2-Go to schema setting -->step3-change Default charset to latin1--> step 4-Run on server your spring mvc program--> step 5- Finally Your table is created with #Id on String
I had the same issue. I resolved it by assigning char set to my database on creation:
CREATE DATABASE mydb DEFAULT CHARACTER SET utf8mb3;

JacksonMapping Exception :: HttpMessageNotWritableException: Could not write content: (was java.lang.NullPointerException)

Framework Spring MVC 4.x
Hibernate 4.x
Jackson 2.8
I have two columns one is publishDate and createdDate. Publish date user need to manually enter it. Created date in MySQL column has a default set as CURRENT_TIMESTAMP, so when an entry is created DB will automatically timestamp the entry.
I have a book POJO publishDate and createdDate field... publishDate can handle null data for some reason. But Timestamp field gets an exception. Why is this?
org.springframework.http.converter.HttpMessageNotWritableException: Could not
write content: (was java.lang.NullPointerException) (through reference chain:
java.util.HashMap["results"]->java.util.ArrayList[30]-
>com.app.books.Book["dateCreated"]); nested exception is
com.fasterxml.jackson.databind.JsonMappingException: (was
java.lang.NullPointerException) (through reference chain:
java.util.HashMap["results"]->java.util.ArrayList[30]-
>com.app.books.Book["dateCreated"])
I tried to suppress this by adding annotation, I tried several of them because I keep reading conflicting info on the comments section on which to use.
#JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) // but show JsonSerialize is deprecated
#JsonInclude(Include.NON_NULL)// Include can not be resolved as variable
#JsonInclude(JsonInclude.Include.NON_DEFAULT) // finally doesn't give me an error but I still get the same exception.
This is my book Class
#Entity
#Table(name="books")
#Component
public class Book implements Serializable{
/**
*
*/
private static final long serialVersionUID = -2042607611480064259L;
#Id
#GeneratedValue
private int id;
#NotBlank
private String name;
#NotBlank
#Size(min=2, max=16)
private String ispn;
#DecimalMin(value = "0.1")
private double price;
//#JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
//#JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
//#JsonIgnoreProperties(ignoreUnknown = true)
#JsonInclude(JsonInclude.Include.NON_DEFAULT)
private Timestamp dateCreated;
private Date datePublished;
Very wried... Thanks for helping..
You may have better results switching from primitives (int & double) to Java classes (Int & Double) in your Book class. See JsonMappingException (was java.lang.NullPointerException) also JSON: JsonMappingException while try to deserialize object with null values

Can not convert JSON to domain object with spring restTemplate

Actually I try to invoke a get request with the restTemplate in Spring. Debbuging my application clearly shows that the JSON is downloaded but the automatic mapping does not work. My List of domain object includes only 0 values and null values.
When I invoke the get request from the browser, I get the following response as JSON (I copied here the first two record out of the 3 192):
[{"OrderId":77862,"DateAdded":"2016-04-30T02:25:40.263","OrderItemCorpusId":"HUBW","OrderItemCorpusOriginalId":null,"OrderItemCurrency":"HUF","OrderItemExchangeRate":1.00000,"OrderItemOriginalLocation":"HU","OrderItemBuyLocation":"HU","OrderItemPrice":1337.80314,"OrderItemDiscountId":0,"OrderItemDiscountValue":"","DocumentId":25140,"Title":"Romana Gold 10. kötet","PublisherOriginalName":"Harlequin Kiadó","ISBN":"9789634073369"},{"OrderId":77864,"DateAdded":"2016-04-30T15:49:22.61","OrderItemCorpusId":"HUBW","OrderItemCorpusOriginalId":null,"OrderItemCurrency":"HUF","OrderItemExchangeRate":1.00000,"OrderItemOriginalLocation":"HU","OrderItemBuyLocation":"HU","OrderItemPrice":2748.03149,"OrderItemDiscountId":0,"OrderItemDiscountValue":"","DocumentId":25252,"Title":"Az eltűnt lány","PublisherOriginalName":"Harlequin Kiadó","ISBN":"9789634072423"}]
My POJO domain object which should keep the converted data from JSON:
#JsonIgnoreProperties(ignoreUnknown = true)
public class BandWTransaction {
private long OrderId;
private Date DateAdded;
private String OrderItemCurrency;
private double OrderItemExchangeRate;
private String OrderItemBuyLocation;
private double OrderItemPrice;
private String OrderItemDiscountValue;
private long DocumentId;
private String Title;
private String PublisherOriginalName;
private String ISBN;
//getters and setters
Finally the code snippet I use for the rest get request:
String startDate = new SimpleDateFormat("yyyy-MM-dd").format(start.getTime());
String endDate = new SimpleDateFormat("yyyy-MM-dd").format(end.getTime());
UriComponents uri = UriComponentsBuilder.newInstance().scheme("http").host("www.bookandwalk.hu")
.path("/api/AdminTransactionList").queryParam("password", "XXX")
.queryParam("begindate", startDate).queryParam("enddate", endDate).queryParam("corpusid", "HUBW")
.build().encode();
LOG.log(Level.INFO, "{0} were called as a rest call", uri.toString());
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
headers.set("User-Agent", "Anything");
HttpEntity<String> entity = new HttpEntity<String>(headers);
ResponseEntity<List<BandWTransaction>> transResponse = restTemplate.exchange(uri.toString(), HttpMethod.GET,
entity, new ParameterizedTypeReference<List<BandWTransaction>>() {
});
List<BandWTransaction> transactions = transResponse.getBody();
When I debug the app I realized that the transactions list includes objects with full of null and 0 values. More precisely, there is no and objcet within the list having other values as 0 and null in the properties.
I have also checked that spring boot automatically registered in the restTemplate.messageConverters ArrayList 9 HttpMessageConverter. The 7th element of this ArrayList is the org.springframework.http.converter.json.MappingJackson2HttpMessageConverter which supports the application/json and application/+json media types.
Any idea is appreciated to solve this problem as I am newbie in spring and in JSON mapping in general.
It seems you have a naming convention issue due to your field variables starts with a uppercase. When Jackson finds a pair getTitle/setTitleasumes that the name of this variable is title (starting with lowercase). Of course, if you change the capitalization of your variables, json properties and java variables has different names, so mapping still fails. The best solution is change your names to meet Java conventions, and use Jackson annotations to define your mappings.
#JsonProperty(value="OrderId")
private int orderId;
#JsonProperty(value="DateAdded")
private Date dateAdded;
Hope it helps.
I can suggest you to write a test and check how fasterxml ObjectMapper read a json and unmarshall json to your object:
ObjectMapper objectMapper = new ObjectMapper();
String somestring = objectMapper.readValue("somestring", String.class);
just replace String with your class and "somestring" with your json. So you check if there is problem with it.
And try to use #JsonPropery cause all this capital letters fields start with looks messy:
#JsonIgnoreProperties(ignoreUnknown = true)
public class BandWTransaction {
#JsonProperty("OrderId")
private long OrderId;
[...]
With this stuff I read json correct. You can come in from other side remove ignoring unknown properties:
#JsonIgnoreProperties(ignoreUnknown = true) //remove it and run test
public class BandWTransaction {
and you get :
(11 known properties: "dateAdded", "orderItemExchangeRate",
"documentId", "orderItemPrice", "orderId", "orderItemBuyLocation",
"orderItemDiscountValue", "orderItemCurrency", "isbn", "title",
"publisherOriginalName"])
So problem in variables naming and you can fix it with #JsonProperty

How to configure bulkloader.yaml to upload data from csv to datastore

I'm trying to upload a csv file to datastore using appcfg.py.
The command I'm using is this:
appcfg.py upload_data --application=s~hay-fe --kind=CasillaFinal --filename=CasillaFinal.csv --url=http://hay-fe.appspot.com/remote_api --config_file=bulkloader.yaml
Then I get the next error:
BadArgumentError: Expected an integer id or string name as argument 2; received None (a NoneType).
This is my CasillaFinal.csv:
http://pastebin.com/embed_js.php?i=7dp24Yn1
And this is my bulkloader.yaml:
http://pastebin.com/embed_js.php?i=iPE8PcZQ
I think the problem is with the first column (ID), because I don't have any transformation for the import, but I don't know how to do this transformation.
Here you have the java definition of the 'table':
private #Id Long id;
private Key<EntidadFederativa> claveEntidad;
private int seccion;
private String tipoCasilla;
private String domicilio;
private String ubicacion;
private String referencia;
private String latitud;
private String longitud;
private int distrito;
private int claveMunicipio;
private String municipio;
private String letraInicial;
private String letraFinal;
private String casillaEspecial;
I'm using objectify for the persistence as you can see.
By the way, I would like to know if is important the order of the columns because the order in datastore admin is not the same that in csv file. Here is the order in datastore:
id|casillaEspecial|claveEntidad|claveMunicipio|distrito|domicilio|latitud|letraFinal|letraInicial|longitud|municipio|referencia|seccion|tipoCasilla|ubicacion
whereas in csv is:
id|claveEntidad|seccion|tipoCasilla|domicilio|ubicacion|referencia|latitud|longitud|distrito|claveMunicipio|municipio|letraInicial|letraFinal|casillaEspecial
Finally, I would like to know if the order index starts at 0 or 1, because the error says that the error is in argument 2 (Expected an integer id or string name as argument 2).
I have found that it was missing the header in the csv file, when I added the header it started to work.

Can not set java.lang.Integer field id to org.hibernate.id.IdentifierGeneratorHelper

I need to store some data in a MySQL-database using Jpa 2/Hibernate 3.5.1. For legacy reasons the table I want to store data in has a compound primary key. The first part of the primary key is of type INTEGER (auto-increment-value), the second part is of type BIGINT (Long in Java-code - to be set manually before persisting).
I have implemented (example code below the stacktrace) the combined primary key via the #IdClass-Annotation, the first-key-part also has a generation strategy set: #GeneratedValue(strategy = GenerationType.IDENTITY)
When trying to persist an object with code like this
...
TestData testData = new TestData("data");
testData.setIdPartTwo(2L);
entityManager.getTransaction().begin();
entityManager.persist(testData);
entityManager.getTransaction().commit();
the following exception is thrown:
javax.persistence.PersistenceException: org.hibernate.PropertyAccessException: could not set a field value by reflection setter of org.example.persistence.TestDataId.idPartOne
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1235)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1168)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1174)
at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:674)
at org.example.persistence.PersistenceTest.shouldPersistTestData(PersistenceTest.java:45)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.testng.internal.MethodHelper.invokeMethod(MethodHelper.java:640)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:627)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:799)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1103)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:137)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:121)
at org.testng.TestRunner.runWorkers(TestRunner.java:1098)
at org.testng.TestRunner.privateRun(TestRunner.java:727)
at org.testng.TestRunner.run(TestRunner.java:581)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:315)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:310)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:272)
at org.testng.SuiteRunner.run(SuiteRunner.java:221)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:40)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:83)
at org.testng.internal.thread.ThreadUtil$CountDownLatchedRunnable.run(ThreadUtil.java:151)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)
Caused by: org.hibernate.PropertyAccessException: could not set a field value by reflection setter of org.example.persistence.TestDataId.idPartOne
at org.hibernate.property.DirectPropertyAccessor$DirectSetter.set(DirectPropertyAccessor.java:151)
at org.hibernate.mapping.Component$ValueGenerationPlan.execute(Component.java:438)
at org.hibernate.id.CompositeNestedGeneratedValueGenerator.generate(CompositeNestedGeneratedValueGenerator.java:122)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:122)
at org.hibernate.ejb.event.EJB3PersistEventListener.saveWithGeneratedId(EJB3PersistEventListener.java:69)
at org.hibernate.event.def.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:179)
at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:135)
at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:61)
at org.hibernate.impl.SessionImpl.firePersist(SessionImpl.java:800)
at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:774)
at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:778)
at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:668)
... 24 more
Caused by: java.lang.IllegalArgumentException: Can not set java.lang.Integer field org.example.persistence.TestDataId.idPartOne to org.hibernate.id.IdentifierGeneratorHelper$2
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:146)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:150)
at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:63)
at java.lang.reflect.Field.set(Field.java:657)
at org.hibernate.property.DirectPropertyAccessor$DirectSetter.set(DirectPropertyAccessor.java:139)
... 35 more
My entity-class looks like this:
#Entity
#IdClass(TestDataId.class)
public class TestData implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer idPartOne;
#Id
private Long idPartTwo;
private String data;
public TestData() {}
// getters and setters
// hashCode() and equals()
}
The combined-primary-key:
public class TestDataId implements Serializable {
private static final long serialVersionUID = 1L;
private Integer idPartOne;
private Long idPartTwo;
public TestDataId() {}
// getters and setters
// hashCode() and equals()
}
Test-Table was created with the following statement:
CREATE TABLE `testdb`.`testdata`
(`idPartOne` INTEGER NOT NULL AUTO_INCREMENT,
`idPartTwo` BIGINT(20) NOT NULL DEFAULT 0,
`data` VARCHAR(45),
PRIMARY KEY(`idPartOne`, `idPartTwo`))
ENGINE = InnoDB;
Changing the GenerationType to TABLE would make it work, but would generate idPartOne-values in steps of ~32.000. Unfortunately, another application uses this very same database-table without JPA/Hibernate and is nicely incrementing this id-part in steps of 1.
It is required that the id-generation is done in the same way no matter which application stores data into this table (that is, id incrementing of 1). What would be the best solution to achieve this? Hint, we cannot change the other application!
Any help is really appreciated.
Thx,
Markus
Does it work when you annotate the embedded id?
#Embeddable
public class TestDataId
{
#GeneratedValue(strategy = GenerationType.TABLE)
private Integer idPartOne;
private Long idPartTwo;
}
#Entity
public class TestData
{
#EmbeddedId
private TestDataId key;
private String data;
}