Hi have the following entity on Jhipser 6
entity Proveedor {
nombre String required unique,
descripcion String required
}
And recently I have added a new relationship
relationship OneToOne {
Proveedor{user(login)} to User
}
Everything works as expected. But when I try to insert null values...
id;nombre;descripcion;user_id
1;Proveedor 1;Proveedor 1;5
2;Proveedor 2;Proveedor 2;NULL
But I get:
liquibase.exception.MigrationFailedException: Migration failed for change set config/liquibase/changelog/20210304164226_added_entity_Proveedor.xml::20210304164226-1-data::jhipster:
Reason: liquibase.exception.DatabaseException: org.h2.jdbc.JdbcBatchUpdateException:
Data conversion error converting "'' (PROVEEDOR: ""USER_ID"" BIGINT)"; SQL statement:
INSERT INTO PUBLIC.proveedor(id, nombre, descripcion, user_id) VALUES(?, ?, ?, ?) [22018-200]
I have fixed it manual adding user_id column on the liquibase file that raised the error: 20210304164226_added_entity_Proveedor.xml, on loadData the column user_id was missing.
<changeSet id="20210304164226-1-data" author="jhipster" context="faker">
<loadData
file="config/liquibase/fake-data/proveedor.csv"
separator=";"
tableName="proveedor">
<column name="id" type="numeric"/>
<column name="nombre" type="string"/>
<column name="descripcion" type="string"/>
<!-- jhipster-needle-liquibase-add-loadcolumn - JHipster (and/or extensions) can add load columns here -->
<column name="user_id" type="numeric"/>
</loadData>
</changeSet>
I'm not sure if is a jHipster issue or I have done something wrong.
It's the correct way or I have done something incorrect on the .jdl or .csv?
Your csv looks correct based on the Liquibase documentation about loadData.
Related
I have 2 modules say module 1 aand module 2 ,
module 1 is using liferay and module 2 is not using liferay.
I have a database say myDatabase.
Both module 1 and module 2 are using the same database for the read and write operations .
module 1 is using the service builder and on a particular table XYZ to insert a value it uses the below mentioned code.
XYZ = XYZLocalServiceUtil.createXYZ(0);
XYZ.setX(x);
XYZ.setY(y);
XYZ.setZ(z);
XYZ = XYZLocalServiceUtil.addXYZ(XYZ);
and the module 2 is using the query :
insert into XYZ(x,y,z) values (x,y,z);
Now the problem occurs when the module 2 inserts a record first.
After a insertion by the module 2 , when the module 1(uses service builder) inserts a record it throws the below mentioned exception.
> 06:04:02,824 ERROR [http-bio-8443-exec-38][JDBCExceptionReporter:82]
> Duplicate entry '143' for key 'PRIMARY' 06:04:02,847 ERROR
> [http-bio-8443-exec-38][ClpSerializer:3279]
> java.lang.ClassNotFoundException:
> org.hibernate.exception.ConstraintViolationException
> java.lang.ClassNotFoundException:
> org.hibernate.exception.ConstraintViolationException at
> org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1714)
> at
> org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1559)
> at java.lang.Class.forName0(Native Method) at
> java.lang.Class.forName(Class.java:278) at
> com.liferay.portal.kernel.util.ClassResolverUtil.resolve(ClassResolverUtil.java:29)
> at
> com.liferay.portal.kernel.util.ClassLoaderObjectInputStream.resolveClass(ClassLoaderObjectInputStream.java:43)
> at
> java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1861)
> at
> java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1744)
> at
> java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2033)
> at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1566)
> at
> java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2278)
> at
> java.io.ObjectInputStream.defaultReadObject(ObjectInputStream.java:556)
> at java.lang.Throwable.readObject(Throwable.java:914) at
> sun.reflect.GeneratedMethodAccessor1940.invoke(Unknown Source) at
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> at java.lang.reflect.Method.invoke(Method.java:606) at
> java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1160)
> at
> java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2169)
> at
> java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2060)
> at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1566)
> at java.io.ObjectInputStream.readObject(ObjectInputStream.java:426)
> at
> com.myproject.ClpSerializer.translateThrowable(ClpSerializer.java:3265)
> at com.myproject.XYZLocalServiceClp.addXYZ(XYZLocalServiceClp.java:1)
> at
> com.myproject.XYZLocalServiceUtil.addXYZ(XYZLocalServiceUtil.java:5)
The database has the auto_increment as 144 at that time , still it shows Duplicate entry '143' for key 'PRIMARY'.
Scenario 2 : When the module 2 inserts two records , and now when module 1 tries to insert it again throws the same excetion for 144 . And on again insert operation for 145 and on third attempt it inserts for 146 as it is the current auto increment value now.
The problem is that it is(module 1 - service builder ) is not picking up the latest auto-increment value.
How can it pick the latest auto_increment value .
here is the structure in service.xml of the module 1 :
<entity name="XYZ" local-service="true" remote-service="false" cache-enabled="false" >
<column name="xyzId" type="long" primary="true"
id-type="increment"></column>
<column name="x" type="long"></column>
<column name="y" type="long"></column>
<column name="z" type="long"></column>
</entity>
You can define id-type as identity. If you have a column having auto incrementing primary key. There are 4 different id types. Normally we use increment. But in your case you have to use identity. Hope this will help. Thanks.
<column name="id" type="Integer" primary="true" id-type="identity" />
I was facing the same problem, i had 2 servers running liferay dxp (7.0) using the same database.
Using the solution posted by Varun Arya the SQL query generated by the insert was changed. Instead of passing a defined id to the query, NULL is passed.
I had to add "AUTO_INCREMENT" to the field for it to work.
IDENTITY is a keyword specifiq of Liferay and not recognized by MYSQL.
Regards.
Also, you can create PrimaryKeys by your own using random UUIDs for example. In this case, your primary-key column wont be a Long column anymore but a Varchar column. But, previous IDs need to be migrated in that case.
In this scenario, both modules can be separated clearly since they dont rely on a incremented value.
I am using liferay service builder jar for each plugin portlet. So when i have to insert a new record. I am using below code to insert the record.
XXX xxx = XXXLocalServiceUtil.createXXX(CounterLocalServiceUtil.increment(XXX.class.getName()));
xxx.setValue(value);
XXXLocalServiceUtil.addXXX(xxx);
Each table has a primary key with auto increment. But counter local service util will calculate its own counter value. I need each insert's primary key value. But in this case if first record is insert. 1 will be insert for the record but liferay counter will return 101 or 201 according to deployment.
This works fine
XXX xxx = new XXXImpl();
xxx.setValue(value);
XXXLocalServiceUtil.addXXX(xxx);
I got the exact key as per hibernate. But i can not use this. Because i am using jar file of service builder and there is not Impl class.
Service Builder xml file:
<entity name="XXX" local-service="true"
remote-service="false">
<column name="id" type="long" id-type="increment" primary="true"></column>
<column name="value" type="String" ></column></entity>
Another approach to explain:
Hi,
I am using service builder to my all plugin portlets. And i have custom table having primary key with autoincrement.
As of now i know there are these ways to insert records to table.
XXX xxx = XXXLocalServiceUtil.createXXX(0);
xxx.setValue(value);
XXXLocalServiceUtil.addXXX(xxx);
OR
XXX xxx = XXXLocalServiceUtil.createXXX(CounterLocalServiceUtil.increment()); // Global increment
xxx.setValue(value);
XXXLocalServiceUtil.addXXX(xxx);
OR
XXX xxx = XXXLocalServiceUtil.createXXX(CounterLocalServiceUtil.increment(XXX.class.getName())); // Increment table specific
xxx.setValue(value);
XXXLocalServiceUtil.addXXX(xxx);
In first if i want to get promary key value i gets 0, second long value, third incremented value wrt table name.
I am using thid one. Now if i re-deploy the service or portlet counter value will be incresed 101,201,...
And this can be handled by setting counter.increment.xxx.Class=1 or counter.increment=1.
But i just want to get database table incremented value from "xxx". So there is any way to do this.
Like this:
XXX xxx = new XXXImpl();
xxx.setValue(value);
XXXLocalServiceUtil.addXXX(xxx);
Here i can get the value which i want from database table.
Found the solution:
XXX xxx = XXXLocalServiceUtil.createXXX(0);
xxx.setValue(value);
xxx = XXXLocalServiceUtil.addXXX(xxx);
Now we have the incremented value in xxx. We just have to re-assign the object.
Currently I am working with JDBC Spring Integration (to be very specific: <int-jdbc:stored-proc-outbound-gateway>) where the scenario is passing n-number of parameters to a stored procedure (ORACLE) and receive one return variable (with '1' or Error Message) along with n-number of CURSORS (sys_refcursor) which may have n-number of columns.
While working on this above scenario with Spring Framework I noticed the following issue(s):
My logic from front-end was, first read the 'return variable'. If that value is 1 then start reading all the CURSORS data or else through exception by redirecting user to the error page. Now, all my CURSORS were not having same number of columns as well as same length/type of data. And in middle layer I was having only one Model class to deal with all the CURSORS return elements. That was the challenge for me!
Previously I dealt with only one CURSOR. and therefore in middle layer I used Mapper class to map all CURSOR elements to my Model element's (getter and setter) to push data to the front. But then when used same concept to deal with n-number of CURSORS -that was truly a nightmare.
let me share what I did before and what I did later to resolve this situation at my end and then will draw my understanding for which will sick EXPARTS opinion at the later part of this post.
For one return variable (with '1' or Error Message) along with one CURSOR:
I had my Gateway definition as follows:
<!-- Stored Procedure Outbound-Gateway = To call a database stored procedure -->
<int-jdbc:stored-proc-outbound-gateway id="outbound-gateway-storedproc-personalinfo"
request-channel="procedureRequestChannel"
data-source="dataSource"
stored-procedure-name="pkg_personalinfo_spring.proc_personalinfo_spring"
expect-single-result="false"
ignore-column-meta-data="true">
<!-- Parameter Definitions -->
<int-jdbc:sql-parameter-definition name="firstname" direction="IN"/>
<int-jdbc:sql-parameter-definition name="lastname" direction="IN"/>
<int-jdbc:sql-parameter-definition name="p_RetVal" direction="OUT"/>
<int-jdbc:sql-parameter-definition name="get_ResultSet" type="#{T(oracle.jdbc.OracleTypes).CURSOR}" direction="OUT"/>
<!-- Parameter Mappings Before Passing & Receiving -->
<int-jdbc:parameter name="firstname" expression="payload[0]"/>
<int-jdbc:parameter name="lastname" expression="payload[1]"/>
<int-jdbc:returning-resultset name="get_ResultSet" row-mapper="com.support.PersonalinfoMapper"/>
</int-jdbc:stored-proc-outbound-gateway>
And in Mapper class I had the following simple Mapping rule:
...
PersonalInfo personalInfo = new PersonalInfo();
try{
personalInfo.setFirstname(resultSet.getString(DBConstants.FIRSTNAME));
personalInfo.setLastname(resultSet.getString(DBConstants.LASTNAME));
...
I did that because in my Model class i was having getter and setter for all CURSOR return elements.
Now, for one return variable (with '1' or Error Message) along with n-number of CURSORS:
I changed my Gateway definition as follows:
<!-- Stored Procedure Outbound-Gateway = To call a database stored procedure -->
<int-jdbc:stored-proc-outbound-gateway id="outbound-gateway-storedproc-personalinfo"
request-channel="procedureRequestChannel"
data-source="dataSource"
stored-procedure-name="pkg_personalinfo_spring.proc_personalinfo_spring"
expect-single-result="false"
ignore-column-meta-data="true">
<!-- Parameter Definitions -->
<int-jdbc:sql-parameter-definition name="firstname" direction="IN"/>
<int-jdbc:sql-parameter-definition name="lastname" direction="IN"/>
<int-jdbc:sql-parameter-definition name="p_RetVal" direction="OUT"/>
<int-jdbc:sql-parameter-definition name="get_curr_1" type="#{T(oracle.jdbc.OracleTypes).CURSOR}" direction="OUT"/>
<int-jdbc:sql-parameter-definition name="get_curr_2" type="#{T(oracle.jdbc.OracleTypes).CURSOR}" direction="OUT"/>
<!-- Parameter Mappings Before Passing & Receiving -->
<int-jdbc:parameter name="firstname" expression="payload[0]"/>
<int-jdbc:parameter name="lastname" expression="payload[1]"/>
</int-jdbc:stored-proc-outbound-gateway>
And secondly I removed the entire row mapping concept, means I didn't have any Mapper class. The only one thing I had was only one Model class with all the CURSORS element name and their getters and setters.
Also notice that in my 'Parameter Definitions', how added those two CURSORS definition but in 'Parameter Mappings Before Passing & Receiving' I have nothing now.
I ran the App without any exceptions and later through Fiddler observed the following JSON data came with RESPOND, means everything PERFECT! ;)
JSON
- {}
- get_curr_1
- -{}
- - firstname=Faisal
- - lastname=Quazi
- get_curr_2
- -{}
- - country=Bangladesh
- - capital=Dhaka
WHAT THE HACK??? Yes...I had the same feelings ;)
Now, can any one plz help to understand what is going on here. Will it be a true statement that "'int-jdbc:stored-proc-outbound-gateway' is able to MAP ur Model element(s) by itself magically???"
Is there any best practice to deal with such kind of situation(s)?
Thank u guys always :)
:-). I guess that by default Spring JDBC uses ColumnMapRowMapper.
So you end up after that gateway with Map<String, <Map<?, ?>>> or something similar. But it is Map anyway.
Since you further convert your payload to JSON and Jackson can get deal with maps prefectly, you finish with correct result.
I can debug it, of course, but deduction says that it can't be differently.
UPDATE
As I said. The answer is here JdbcTemplate#extractOutputParameters:
....
if (outParam.isResultSetSupported()) {
returnedResults.putAll(processResultSet((ResultSet) out, outParam));
}
else {
String rsName = outParam.getName();
SqlReturnResultSet rsParam = new SqlReturnResultSet(rsName, new ColumnMapRowMapper());
returnedResults.putAll(processResultSet((ResultSet) out, rsParam));
if (logger.isDebugEnabled()) {
logger.debug("Added default SqlReturnResultSet parameter named '" + rsName + "'");
}
}
....
i'm using wso2esb 4.7.0 and wso2dss 3.1.0.i wish to select some column from table.For that i have used following query in dss :
select roleid,rolename,rolecode from mrole where clientid = ? and ModifiedOn = ?
It's working fine in dss as well as esb also.Output is like :
{"roleid":"1077282521908571","rolename":"adminrole","rolecode":"adminrole"},{"roleid":"1077282521908571","rolename":"adminrole","rolecode":"adminrole"},{"roleid":"1077278842127704","rolename":"everyonerole","rolecode":"everyonerole"},{"roleid":"1077282521908571","rolename":"adminrole","rolecode":"adminrole"}
this is one case.Now in second case if i didn't got modifiedon then obvious it shows error in dss like :
Caused by: javax.xml.stream.XMLStreamException: DS Fault Message: Error in 'SQLQuery.processNormalQuery'
DS Code: DATABASE_ERROR
Source Data Service:-
Name: muser_DataService2.0
Location: /muser_DataService2.0.dbs
Description: N/A
Default Namespace: http://ws.wso2.org/dataservice
Current Request Name: Select_Role_Details_Op
Current Params: {clientid=214057357158656, modifiedon=}
Nested Exception:-
java.lang.NumberFormatException: For input string: ""
To solve that i'm using switch case in esb like :
<switch source="get-property('ModifiedOn')">
<case regex="''">
<property name="ModifiedOn" value="0" scope="default" type="STRING"/>
<log level="custom">
<property name="ModifiedOn in case of null: "
expression="get-property('ModifiedOn')"/>
</log>
</case>
</switch>
it shows warning message in esb like :
[2014-10-08 11:43:54,100] WARN - SwitchCase Provided character sequence for switch case condition is 'null'. Switch case will not be executed.
and without executing switch case it directly move forward and generate fault as well as dss shows error as above.How should i give the null condition in switch case?
use boolean xpath function to verify if your property exist :
<filter xpath="boolean(get-property('ModifiedOn'))">
<then>
...
</then>
<else>
...
</else>
</filter>
I am using with a row mapper expecting it wuold return me the list of my objects but instead it is returning me LinkedHasMap. I want resultset to be List of my mapped objects.
Any idea how can i achieve this ?
Config
<int-jdbc:stored-proc-inbound-channel-adapter
channel="eventObj"
stored-procedure-name="p_get_completed_data"
data-source="dataSource"
auto-startup="true"
id="completedEventAdpt"
ignore-column-meta-data="true"
is-function="false"
return-value-required="false">
<int:poller max-messages-per-poll="1" fixed-rate="180000"/>
<int-jdbc:returning-resultset name="mapper" row-mapper="mapper" />
</int-jdbc:stored-proc-inbound-channel-adapter>
<bean id="mapper" class="com.db.mapper.MyMapper"/>
Stored procedures can return multiple result sets, keyed by the parameter name.
In your case, you only have one result set, but it's still returned in a map.
Simply add a <transformer/> after the inbound adapter...
<transformer ... expression="payload['mapper']" />