Storing Double.POSITIVE_INFINITY in MySQL (EJB entity/JBoss) - mysql

I have the following simple JPA entity:
#Entity
#Table( name = myentity_table )
public class MyEntity {
private double a;
private double b;
//(...)
}
a and b may be set to Double.POSITIVE_INFINITY. When I try to store entity with double set to +INF into database (MySQL) using standard entity manager I get exception:
java.sql.SQLException: 'Infinity' is not a valid numeric or approximate numeric value
As far as I know MySQL may not support NaN/-INF/+INF numbers. Is there any way to store this entity without writing HQL queries and translating +INF into null (or max double) ? Ideally, I'd like to do it via entity manager as usual.
Thanks in advance.

Entity life-cycle callback methods #PrePersist, #PreUpdate can be used here to verify the field value NAN/-INF/+INF etc & then setting the default value accordingly.
//--
#PrePersist
#PreUpdate
private void resetField() {
if(field == Double.POSITIVE_INFINITY)
field = somePredefinedValue;
}
//--

MySQL doesn't seem to support "infinity". This article writes that:
Storing and retrieving negative infinity in a MySQL database is accomplished by inserting an arbitrarily large negative number.
Same goes for positive. Other resources also use 1e500.
Instead of using infinity, I would suggest that you use Float.MAX_VALUE and Float.MIN_VALUE (or Double equivalents)
If you can't do this in your code when setting the values, do it in a #PrePersist as already suggested.

I managed this problem by adding a varchar column to store the text representation of Float.NaN, Float.POSITIVE_INFINITY and Float.NEGATIVE_INFINITY while the original column will store NULL.
Then I use the setter and the getter to do manage those two columns.
In my #Entity class
/** The value I persist. See it is a Float; */
#Column(name = "VALUE")
private Float value;
/** the 'value complement' that does the trick. */
#Column(name = "VALUE_COMPLEMENT") // You can see I've added a new column in my table (it is a varchar)
private String valueComplement;
/**
* value getter.
* If my value is null, it could mean that it is a NaN or +/- infinity.
* Then let's check the complement.
*/
public Float getValue() {
if (value == null) {
try {
return Float.parseFloat(this.valueComplement);
} catch (NumberFormatException e) {
return null;
}
} else {
return value;
}
}
/**
* value setter
* If the given value is a NaN or Inf, set this.value to null
* and this.complement to the string representation of NaN or +/- Inf.
*/
public void setValue(Float value) {
if (value != null && (value.isNaN() || value.isInfinite())) {
this.valueComplement = value.toString();
this.value = null;
} else {
this.value = value;
}
}
Result :
| ID | LABEL | VALUE | VALUE_COMPLEMENT |
| -- | --------------------- | ----- | ---------------- |
| 1 | PI | 3.14 | NULL |
| 2 | gravity acceleration | 9.81 | NULL |
| 3 | sqare root of -1 | NULL | NaN |
| 4 | log of 0 | NULL | -Infinity |

Related

Parsing variable length record to table columns where specific column is dynamic in SSIS 2016

I have a table that has 45 columns for tax values
| Tax1 | Tax2 | .......... | Tax 44 | Tax45 |
I read in a variable length positional record that can contain zero to 90 values. The record is structured so that the first 3 characters are the tax code (values 001 - 045) and the next 7 characters are the tax value:
Examples:
0010013.990140005.00
0040002.00
0150001.150320002.200410014.250420012.990430000.500440001.750450004.68
What I would like to do is, for each record:
if ISNULL(record) or LEN(record) < 10 (3 characters for the code, 7 characters for the value)
quit
else
determine the amount of 10 character sections
for each 10 character section
taxCode = SUBSTRING(record, 1, 3)
taxValue = SUBSTRING(record, 4, 10)
table.Tax(taxCode).Value = taxValue (ex: using the first example record, column Tax1 will hold a value of 0013.99, Tax14 will be 0005.00)
next section
all other Tax[n] columns will have a value of 0.00
end if
Is there a way to do this without having to create 45 variables, one for each corresponding column?
EDIT:
I apologize for the lack of clarity. I receive a flat file from our VMS database. This file has multiple record types per file (ie: IT01, IT02, IT03, IT04, IT05, IT06, IT07). Each record type is on its own line. I read this file into a staging table, which the record type from the data on the line. For example (this is the record type I am referring to in my question):
IT06404034001005.000031013.000
This gets loaded into my staging table as:
RecordType | RecordData |
------------------------------------------
IT06 | 404034001005.000031013.000
The RecordData field is then able to be broken down further as:
ItemNumber | RecordData |
-------------------------------------
404034 | 001005.000031013.000
With a little bit of up-front work, I was able to create a script task to do exactly as I needed it to.
Step 1: add a script component. set it up as a transformation
Step 2: define all of the output columns necessary (long and tedious task, but it worked)
Step 3: put the following code in the script
public override void Input0_ProcessInputRow(Input0Buffer Row){
int sizeOfDataSegment = 11; // size of single record to be parsed (item number/next price)
string recordDetail = Row.RecordDetail.ToString().Trim();
string itemNumber = recordDetail.Substring(0, 6);
//System.Windows.Forms.MessageBox.Show(String.Format("Record Detail: {0}", recordDetail));
// we need a record for every item number, regardless if there are taxes or not
Row.Company = Variables.strCompanyName;
Row.ItemNumber = itemNumber;
if (recordDetail.Length > 6){
string taxData = recordDetail.Substring(6);
if (string.IsNullOrEmpty(taxData)){
}
else{
if (taxData.Length % sizeOfDataSegment == 0){
int numberOfTaxes = taxData.Length / sizeOfDataSegment;
//System.Windows.Forms.MessageBox.Show(String.Format("Number of taxe codes: {0}", numberOfTaxes.ToString()));
int posTaxCode = 0;
for (int x = 0; x < numberOfTaxes; x++){
string taxCode = taxData.Substring(posTaxCode, 3);
string taxValue = taxData.Substring(posTaxCode + 3, 8);
string outputColumnName = "TaxOut" + Convert.ToInt32(taxCode).ToString();
//System.Windows.Forms.MessageBox.Show(String.Format("TaxCode: {0}" + Environment.NewLine + "TaxValue: {1}", taxCode, taxValue));
//using taxCode value (ie: 001), find and set the value for the corresponding table column (ie: Tax1)
//foreach (System.Reflection.PropertyInfo dataColumn in Row.GetType().GetProperties()){
foreach (System.Reflection.PropertyInfo dataColumn in Row.GetType().GetProperties()){
if (dataColumn.Name == outputColumnName){
if (Convert.ToDecimal(taxValue) < 0){
// taxValue is a negative number, and therefore a percentage value
taxValue = (Convert.ToDecimal(taxValue) * -1).ToString() + "%";
}
else{
// taxValue is a positive number, and therefore a dollar value
taxValue = "$" + Convert.ToDecimal(taxValue).ToString();
}
dataColumn.SetValue(Row, taxValue);
}
}
posTaxCode += sizeOfDataSegment;
}
}
else{
System.Windows.Forms.MessageBox.Show(String.Format("Invalid record length({0}): {1}", taxData.Length, taxData));
}
}
}
}

How to organize database columns in same order as specified in model on Hibernate? [duplicate]

This (should) be a rather simple thing to do, however I am struggling.
I want a table to be generated like this:
id
organizationNumber
name
However, when I look in the database, I see that the ordering is wrong. Does anybody know how I can force hibernate/jpa to generate the table with correct ordering?
desc Organization;
+--------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------------+--------------+------+-----+---------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | | NULL | |
| organizationNumber | varchar(255) | NO | UNI | NULL | |
+--------------------+--------------+------+-----+---------+----------------+
This is how my entity bean looks like:
#Entity
#NamedQuery(name = "allOrganizations", query = "SELECT org FROM Organization org order by name")
public class Organization {
private Long id;
private String organizationNumber;
private String name;
public Organization() {
}
public Organization(String name) {
this.name = name;
}
#Id
#GeneratedValue
public Long getId() {
return id;
}
#SuppressWarnings("unused")
private void setId(Long id) {
this.id = id;
}
#NotEmpty
#Column(unique=true, nullable=false)
public String getOrganizationNumber() {
return organizationNumber;
}
public void setOrganizationNumber(String organizationNumber) {
this.organizationNumber = organizationNumber;
}
#NotEmpty
#Column(nullable=false)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public String toString() {
return this.name + " " + this.organizationNumber;
}
}
Hibernate generates columns in alphabetical order. According to this post the reason is given as:
It is sorted to ensurce deterministic
ordering across clusters.
We can't rely on the vm to return the
methods in the same order every time
so we had to do something.
Apparently it used to be in the order of occurrence but this changed between 3.2.0 GA and 3.2.1 GA.
I also found Schema auto generation creates columns in alphabetical order for compound primary keys and this seems to be like your problem. This ticket is about the order changing in primary keys and that negatively impacts index performance.
There is no fix for this other than a workaround of naming the columns in such a way that they come out in the correct order (no, I'm not kidding).
I have the same problem. Finally, I found the solution.
Find your External Libraries about hibernate core and find the org.hibernate.cfg.PropertyContainer class and copy the content.
In your root folder create the org.hibernate.cfg package and PropertyContainer class.
Paste the org.hibernate.cfg.PropertyContainer content and replace all TreeMap to LinkedHashMap in your create PropertyContainer class.
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
// $Id$
package org.hibernate.cfg;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import javax.persistence.Access;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Transient;
import org.hibernate.AnnotationException;
import org.hibernate.MappingException;
import org.hibernate.annotations.ManyToAny;
import org.hibernate.annotations.Target;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.annotations.common.reflection.XProperty;
import org.hibernate.boot.jaxb.Origin;
import org.hibernate.boot.jaxb.SourceType;
import org.hibernate.cfg.annotations.HCANNHelper;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.StringHelper;
import org.jboss.logging.Logger;
/**
* A helper class to keep the {#code XProperty}s of a class ordered by access type.
*
* #author Hardy Ferentschik
*/
class PropertyContainer {
//
// static {
// System.setProperty("jboss.i18n.generate-proxies", "true");
// }
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, PropertyContainer.class.getName());
/**
* The class for which this container is created.
*/
private final XClass xClass;
private final XClass entityAtStake;
/**
* Holds the AccessType indicated for use at the class/container-level for cases where persistent attribute
* did not specify.
*/
private final AccessType classLevelAccessType;
private final TreeMap<String, XProperty> persistentAttributeMap;
PropertyContainer(XClass clazz, XClass entityAtStake, AccessType defaultClassLevelAccessType) {
this.xClass = clazz;
this.entityAtStake = entityAtStake;
if ( defaultClassLevelAccessType == AccessType.DEFAULT ) {
// this is effectively what the old code did when AccessType.DEFAULT was passed in
// to getProperties(AccessType) from AnnotationBinder and InheritanceState
defaultClassLevelAccessType = AccessType.PROPERTY;
}
AccessType localClassLevelAccessType = determineLocalClassDefinedAccessStrategy();
assert localClassLevelAccessType != null;
this.classLevelAccessType = localClassLevelAccessType != AccessType.DEFAULT
? localClassLevelAccessType
: defaultClassLevelAccessType;
assert classLevelAccessType == AccessType.FIELD || classLevelAccessType == AccessType.PROPERTY;
this.persistentAttributeMap = new TreeMap<String, XProperty>();
final List<XProperty> fields = xClass.getDeclaredProperties( AccessType.FIELD.getType() );
final List<XProperty> getters = xClass.getDeclaredProperties( AccessType.PROPERTY.getType() );
preFilter( fields, getters );
final Map<String,XProperty> persistentAttributesFromGetters = new HashMap<String, XProperty>();
collectPersistentAttributesUsingLocalAccessType(
persistentAttributeMap,
persistentAttributesFromGetters,
fields,
getters
);
collectPersistentAttributesUsingClassLevelAccessType(
persistentAttributeMap,
persistentAttributesFromGetters,
fields,
getters
);
}
private void preFilter(List<XProperty> fields, List<XProperty> getters) {
Iterator<XProperty> propertyIterator = fields.iterator();
while ( propertyIterator.hasNext() ) {
final XProperty property = propertyIterator.next();
if ( mustBeSkipped( property ) ) {
propertyIterator.remove();
}
}
propertyIterator = getters.iterator();
while ( propertyIterator.hasNext() ) {
final XProperty property = propertyIterator.next();
if ( mustBeSkipped( property ) ) {
propertyIterator.remove();
}
}
}
private void collectPersistentAttributesUsingLocalAccessType(
TreeMap<String, XProperty> persistentAttributeMap,
Map<String,XProperty> persistentAttributesFromGetters,
List<XProperty> fields,
List<XProperty> getters) {
// Check fields...
Iterator<XProperty> propertyIterator = fields.iterator();
while ( propertyIterator.hasNext() ) {
final XProperty xProperty = propertyIterator.next();
final Access localAccessAnnotation = xProperty.getAnnotation( Access.class );
if ( localAccessAnnotation == null
|| localAccessAnnotation.value() != javax.persistence.AccessType.FIELD ) {
continue;
}
propertyIterator.remove();
persistentAttributeMap.put( xProperty.getName(), xProperty );
}
// Check getters...
propertyIterator = getters.iterator();
while ( propertyIterator.hasNext() ) {
final XProperty xProperty = propertyIterator.next();
final Access localAccessAnnotation = xProperty.getAnnotation( Access.class );
if ( localAccessAnnotation == null
|| localAccessAnnotation.value() != javax.persistence.AccessType.PROPERTY ) {
continue;
}
propertyIterator.remove();
final String name = xProperty.getName();
// HHH-10242 detect registration of the same property getter twice - eg boolean isId() + UUID getId()
final XProperty previous = persistentAttributesFromGetters.get( name );
if ( previous != null ) {
throw new org.hibernate.boot.MappingException(
LOG.ambiguousPropertyMethods(
xClass.getName(),
HCANNHelper.annotatedElementSignature( previous ),
HCANNHelper.annotatedElementSignature( xProperty )
),
new Origin( SourceType.ANNOTATION, xClass.getName() )
);
}
persistentAttributeMap.put( name, xProperty );
persistentAttributesFromGetters.put( name, xProperty );
}
}
private void collectPersistentAttributesUsingClassLevelAccessType(
TreeMap<String, XProperty> persistentAttributeMap,
Map<String,XProperty> persistentAttributesFromGetters,
List<XProperty> fields,
List<XProperty> getters) {
if ( classLevelAccessType == AccessType.FIELD ) {
for ( XProperty field : fields ) {
if ( persistentAttributeMap.containsKey( field.getName() ) ) {
continue;
}
persistentAttributeMap.put( field.getName(), field );
}
}
else {
for ( XProperty getter : getters ) {
final String name = getter.getName();
// HHH-10242 detect registration of the same property getter twice - eg boolean isId() + UUID getId()
final XProperty previous = persistentAttributesFromGetters.get( name );
if ( previous != null ) {
throw new org.hibernate.boot.MappingException(
LOG.ambiguousPropertyMethods(
xClass.getName(),
HCANNHelper.annotatedElementSignature( previous ),
HCANNHelper.annotatedElementSignature( getter )
),
new Origin( SourceType.ANNOTATION, xClass.getName() )
);
}
if ( persistentAttributeMap.containsKey( name ) ) {
continue;
}
persistentAttributeMap.put( getter.getName(), getter );
persistentAttributesFromGetters.put( name, getter );
}
}
}
public XClass getEntityAtStake() {
return entityAtStake;
}
public XClass getDeclaringClass() {
return xClass;
}
public AccessType getClassLevelAccessType() {
return classLevelAccessType;
}
public Collection<XProperty> getProperties() {
assertTypesAreResolvable();
return Collections.unmodifiableCollection( persistentAttributeMap.values() );
}
private void assertTypesAreResolvable() {
for ( XProperty xProperty : persistentAttributeMap.values() ) {
if ( !xProperty.isTypeResolved() && !discoverTypeWithoutReflection( xProperty ) ) {
String msg = "Property " + StringHelper.qualify( xClass.getName(), xProperty.getName() ) +
" has an unbound type and no explicit target entity. Resolve this Generic usage issue" +
" or set an explicit target attribute (eg #OneToMany(target=) or use an explicit #Type";
throw new AnnotationException( msg );
}
}
}
//
// private void considerExplicitFieldAndPropertyAccess() {
// for ( XProperty property : fieldAccessMap.values() ) {
// Access access = property.getAnnotation( Access.class );
// if ( access == null ) {
// continue;
// }
//
// // see "2.3.2 Explicit Access Type" of JPA 2 spec
// // the access type for this property is explicitly set to AccessType.FIELD, hence we have to
// // use field access for this property even if the default access type for the class is AccessType.PROPERTY
// AccessType accessType = AccessType.getAccessStrategy( access.value() );
// if (accessType == AccessType.FIELD) {
// propertyAccessMap.put(property.getName(), property);
// }
// else {
// LOG.debug( "Placing #Access(AccessType.FIELD) on a field does not have any effect." );
// }
// }
//
// for ( XProperty property : propertyAccessMap.values() ) {
// Access access = property.getAnnotation( Access.class );
// if ( access == null ) {
// continue;
// }
//
// AccessType accessType = AccessType.getAccessStrategy( access.value() );
//
// // see "2.3.2 Explicit Access Type" of JPA 2 spec
// // the access type for this property is explicitly set to AccessType.PROPERTY, hence we have to
// // return use method access even if the default class access type is AccessType.FIELD
// if (accessType == AccessType.PROPERTY) {
// fieldAccessMap.put(property.getName(), property);
// }
// else {
// LOG.debug( "Placing #Access(AccessType.PROPERTY) on a field does not have any effect." );
// }
// }
// }
// /**
// * Retrieves all properties from the {#code xClass} with the specified access type. This method does not take
// * any jpa access rules/annotations into account yet.
// *
// * #param access The access type - {#code AccessType.FIELD} or {#code AccessType.Property}
// *
// * #return A maps of the properties with the given access type keyed against their property name
// */
// private TreeMap<String, XProperty> initProperties(AccessType access) {
// if ( !( AccessType.PROPERTY.equals( access ) || AccessType.FIELD.equals( access ) ) ) {
// throw new IllegalArgumentException( "Access type has to be AccessType.FIELD or AccessType.Property" );
// }
//
// //order so that property are used in the same order when binding native query
// TreeMap<String, XProperty> propertiesMap = new TreeMap<String, XProperty>();
// List<XProperty> properties = xClass.getDeclaredProperties( access.getType() );
// for ( XProperty property : properties ) {
// if ( mustBeSkipped( property ) ) {
// continue;
// }
// // HHH-10242 detect registration of the same property twice eg boolean isId() + UUID getId()
// XProperty oldProperty = propertiesMap.get( property.getName() );
// if ( oldProperty != null ) {
// throw new org.hibernate.boot.MappingException(
// LOG.ambiguousPropertyMethods(
// xClass.getName(),
// HCANNHelper.annotatedElementSignature( oldProperty ),
// HCANNHelper.annotatedElementSignature( property )
// ),
// new Origin( SourceType.ANNOTATION, xClass.getName() )
// );
// }
//
// propertiesMap.put( property.getName(), property );
// }
// return propertiesMap;
// }
private AccessType determineLocalClassDefinedAccessStrategy() {
AccessType classDefinedAccessType;
AccessType hibernateDefinedAccessType = AccessType.DEFAULT;
AccessType jpaDefinedAccessType = AccessType.DEFAULT;
org.hibernate.annotations.AccessType accessType = xClass.getAnnotation( org.hibernate.annotations.AccessType.class );
if ( accessType != null ) {
hibernateDefinedAccessType = AccessType.getAccessStrategy( accessType.value() );
}
Access access = xClass.getAnnotation( Access.class );
if ( access != null ) {
jpaDefinedAccessType = AccessType.getAccessStrategy( access.value() );
}
if ( hibernateDefinedAccessType != AccessType.DEFAULT
&& jpaDefinedAccessType != AccessType.DEFAULT
&& hibernateDefinedAccessType != jpaDefinedAccessType ) {
throw new MappingException(
"#AccessType and #Access specified with contradicting values. Use of #Access only is recommended. "
);
}
if ( hibernateDefinedAccessType != AccessType.DEFAULT ) {
classDefinedAccessType = hibernateDefinedAccessType;
}
else {
classDefinedAccessType = jpaDefinedAccessType;
}
return classDefinedAccessType;
}
private static boolean discoverTypeWithoutReflection(XProperty p) {
if ( p.isAnnotationPresent( OneToOne.class ) && !p.getAnnotation( OneToOne.class )
.targetEntity()
.equals( void.class ) ) {
return true;
}
else if ( p.isAnnotationPresent( OneToMany.class ) && !p.getAnnotation( OneToMany.class )
.targetEntity()
.equals( void.class ) ) {
return true;
}
else if ( p.isAnnotationPresent( ManyToOne.class ) && !p.getAnnotation( ManyToOne.class )
.targetEntity()
.equals( void.class ) ) {
return true;
}
else if ( p.isAnnotationPresent( ManyToMany.class ) && !p.getAnnotation( ManyToMany.class )
.targetEntity()
.equals( void.class ) ) {
return true;
}
else if ( p.isAnnotationPresent( org.hibernate.annotations.Any.class ) ) {
return true;
}
else if ( p.isAnnotationPresent( ManyToAny.class ) ) {
if ( !p.isCollection() && !p.isArray() ) {
throw new AnnotationException( "#ManyToAny used on a non collection non array property: " + p.getName() );
}
return true;
}
else if ( p.isAnnotationPresent( Type.class ) ) {
return true;
}
else if ( p.isAnnotationPresent( Target.class ) ) {
return true;
}
return false;
}
private static boolean mustBeSkipped(XProperty property) {
//TODO make those hardcoded tests more portable (through the bytecode provider?)
return property.isAnnotationPresent( Transient.class )
|| "net.sf.cglib.transform.impl.InterceptFieldCallback".equals( property.getType().getName() )
|| "org.hibernate.bytecode.internal.javassist.FieldHandler".equals( property.getType().getName() );
}
}
Fixed the Organization class.
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
#Entity
public class Organization {
#Id
#GeneratedValue
private Long id;
#Column(unique = true, nullable = false)
private String organizationNumber;
#Column(nullable = false)
private String name;
public Organization() {
}
public Organization(String name) {
this.name = name;
}
public Long getId() {
return id;
}
#SuppressWarnings("unused")
public void setId(Long id) {
this.id = id;
}
public String getOrganizationNumber() {
return organizationNumber;
}
public void setOrganizationNumber(String organizationNumber) {
this.organizationNumber = organizationNumber;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public String toString() {
return this.name + " " + this.organizationNumber;
}
}
Start the Spring Boot App. See the result in the console.
Hibernate: create table organization (id bigint not null, organization_number varchar(255) not null, name varchar(255) not null, primary key (id)) engine=InnoDB
In the database see the desc result.
mysql> desc organization;
+---------------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------------+--------------+------+-----+---------+-------+
| id | bigint(20) | NO | PRI | NULL | |
| organization_number | varchar(255) | NO | UNI | NULL | |
| name | varchar(255) | NO | | NULL | |
+---------------------+--------------+------+-----+---------+-------+
3 rows in set (0.00 sec)
Supplement on Inheritance
If you want use the inherit some parent class like Auditing class. The above answer is not enough.
You can copy InheritanceState.class like above approach and create the InheritanceState.class into org.hibernate.cfg package.
Modify the two line, just fixed the sorting.
public class InheritanceState {
// ...
private void getMappedSuperclassesTillNextEntityOrdered() {
//ordered to allow proper messages on properties subclassing
XClass currentClassInHierarchy = clazz;
InheritanceState superclassState;
do {
// mark this ↓↓↓↓↓
// classesToProcessForMappedSuperclass.add( 0, currentClassInHierarchy );
// fixed the sorting, add this ↓↓↓↓↓
classesToProcessForMappedSuperclass.add( currentClassInHierarchy );
// ...
}
// ...
}
private void addMappedSuperClassInMetadata(PersistentClass persistentClass) {
//add #MappedSuperclass in the metadata
// classes from 0 to n-1 are #MappedSuperclass and should be linked
org.hibernate.mapping.MappedSuperclass mappedSuperclass = null;
final InheritanceState superEntityState =
InheritanceState.getInheritanceStateOfSuperEntity( clazz, inheritanceStatePerClass );
PersistentClass superEntity =
superEntityState != null ?
buildingContext.getMetadataCollector().getEntityBinding( superEntityState.getClazz().getName() ) :
null;
final int lastMappedSuperclass = classesToProcessForMappedSuperclass.size() - 1;
// mark this ↓↓↓↓↓
// for ( int index = 0; index < lastMappedSuperclass; index++ ) {
// fixed the sorting, add this ↓↓↓↓↓
for ( int index = lastMappedSuperclass; index > 0; index-- ) {
// ...
}
// ...
}
}
The demo class.
#MappedSuperclass
#EntityListeners(AuditingEntityListener.class)
public abstract class AuditableEntity {
#CreatedBy
#Column(name = "created_by")
private String createdBy;
#LastModifiedBy
#Column(name = "last_modified_by")
private String lastModifiedBy;
#LastModifiedDate
#Column(name = "update_time")
private ZonedDateTime updatedTime;
#CreatedDate
#Column(name = "create_time")
private ZonedDateTime createTime;
}
#Entity
public class OrganizationAudit extends AuditableEntity {
// same field with Organization.class...
}
In console result.
create table organization_audit (id bigint not null, organization_number varchar(255) not null, name varchar(255) not null, created_by varchar(255), last_modified_by varchar(255), update_time datetime, create_time datetime, primary key (id)) engine=InnoDB
In database result.
mysql> desc organization_audit;
+---------------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------------+--------------+------+-----+---------+-------+
| id | bigint(20) | NO | PRI | NULL | |
| organization_number | varchar(255) | NO | UNI | NULL | |
| name | varchar(255) | NO | | NULL | |
| created_by | varchar(255) | YES | | NULL | |
| last_modified_by | varchar(255) | YES | | NULL | |
| update_time | datetime | YES | | NULL | |
| create_time | datetime | YES | | NULL | |
+---------------------+--------------+------+-----+---------+-------+
7 rows in set (0.00 sec)
The sample project is here.
You can set the order you want whenever you can change the internal name of the class members, since the order of the columns is taken from the field name, not from the getter, setter, or column.
Thus, if the class members are private (as desired), you should only list them (for example by prefixing them with "a_", "b_", "c_", ...) without changing either the getters, the setters, or the column names.
For example, the following class definition:
#Id
#Column(name = "parent")
UUID parent;
#Id
#Column(name = "type", length = 10)
String type;
#Id
#Column(name = "child")
UUID child;
It generates the following table:
Column | Type | Collation | Nullable | Default
-----------+-----------------------+-----------+----------+---------
child | uuid | | not null |
parent | uuid | | not null |
type | character varying(10) | | not null |
Indexes:
"...whatever..." PRIMARY KEY, btree (child, parent, type)
Which is not efficient because normally we will search by parent and type of relationship to obtain the children.
We can change the private names without affecting the rest of the implementation by doing:
#Id
#Column(name = "parent")
UUID a_parent;
#Id
#Column(name = "type", length = 10)
String b_type;
#Id
#Column(name = "child")
UUID c_child;
public UUID getParent() { return a_parent; }
public UUID getChild() { return c_child; }
public String getType() { return b_type; }
public void setParent(UUID parent) { a_parent = parent; }
public void setChild(UUID child) { c_child = child; }
public void setType(String type) { b_type = type; }
In that it has now been generated:
Column | Type | Collation | Nullable | Default
-----------+-----------------------+-----------+----------+---------
parent | uuid | | not null |
type | character varying(10) | | not null |
child | uuid | | not null |
Indexes:
"...whatever..." PRIMARY KEY, btree (parent, type, child)
Of course it is not best to depend on the internal lexicographical order of the class members but I do not see a better solution.
DataNucleus allows the extension specifying the position for schema generation, FWIW.
Just create that Table using create statement in your database and use Hibernate to insert a value into Table
Only to resolve the inheritance for the auditable class as an example,
JPA doesn't respect the alpha order, will create first the auditable columns, in this case, for the columns of the auditable class to be created last!
You need to comment #MappedSuperclass, then run in sequence with 'create', then uncomment and run with 'update' for the 'ddl-auto' option.

Grails stack overflow error when trying to serialize domain class to JSON

More beginner problems for me with Groovy/Grails.
Groovy version 2.4.8 Grails version 2.5.1
I have tried multiple ways to serialize an instance of one of my domain classes or an ArrayList of instances of that domain class.
When trying to serialize a single instance I get a stack overflow error.
The code and stack trace is shown below
def getAdvisors(String keystrokes, String firm) {
def advisors = priceBlotterService.advisorsForKeystrokes(keystrokes, "", 30)
def a1 = advisors[0]
def json = JsonOutput.toJson(a1)
}
Caused by InvocationTargetException: null
->> 198 | doFilter in grails.plugin.cache.web.filter.PageFragmentCachingFilter
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 63 | doFilter in grails.plugin.cache.web.filter.AbstractFilter
| 1145 | runWorker in java.util.concurrent.ThreadPoolExecutor
| 615 | run in java.util.concurrent.ThreadPoolExecutor$Worker
^ 745 | run . . . in java.lang.Thread
Caused by StackOverflowError: null
->> 100 | invoke in org.codehaus.groovy.reflection.CachedMethod
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 62 | getProperty in groovy.lang.MetaBeanProperty
| 42 | getValue in groovy.lang.PropertyValue
| 388 | getProperties in org.codehaus.groovy.runtime.DefaultGroovyMethods
| 290 | writeObject in groovy.json.JsonOutput
| 329 | writeArray in ''
| 286 | writeObject in ''
| 424 | writeMap in ''
| 294 | writeObject in ''
| 329 | writeArray in ''
| 286 | writeObject in ''
| 424 | writeMap in ''
Advisor, Case, and Firm Classes:
class Advisor {
String firstName
String lastName
String fullName
String city
String state
Firm firm
static belongsTo = [Case, Firm]
static hasMany = [cases:Case]
static constraints = {
}
}
class Case {
String caseCode
String internalComment
String externalComment
Date dateCreated
String createdBy
Date dateUpdated
String updatedBy
static belongsTo = [owner:User, caseStatusType:CaseStatusType]
static hasMany = [advisor:Advisor]
static mapping = {
dateCreated sqlType: "date"
dateUpdated sqlType: "date"
}
static constraints = {
dateCreated(nullabe: false)
dateUpdated(nullable: false)
}
}
class Firm {
String name
static constraints = {
}
}
Edit:
I found a fundamental problem with my domain class/table that could have something to do with this and needs to be resolved.
I try to do a simple get from the user table and I get an error message indicating there is no id field. Having a hard time figuring out what is going on. Some details are below.
line of code
User[] users = User.findAll()
error message
org.springframework.jdbc.BadSqlGrammarException: Hibernate operation: could not extract ResultSet; bad SQL grammar [n/a]; nested exception is org.postgresql.util.PSQLException: ERROR: column this_.id does not exist Position: 8
User class
class User {
String firstName
String lastName
static constraints = {
}
}
ddl for user table
CREATE TABLE "user"
(
id BIGINT DEFAULT nextval('user_id_seq'::regclass) PRIMARY KEY NOT NULL,
first_name VARCHAR(30),
last_name VARCHAR(30),
version BIGINT
);
CREATE UNIQUE INDEX user_id_uindex ON "user" (id);
Edit:
Fixed issuer with User table/class. User is a keyword in Postresql so I just refactored to EndUser.
I suspect there is some issue with the data structure you have, which is causing the JSON builder to go into an infinite loop.
You may want to review this for info on issues with dates: https://issues.apache.org/jira/browse/GROOVY-7682
This may work instead:
import grails.converters.JSON
def json = new JSON(a1)
I can't find this documented anywhere, but don't use JsonOutput for domain objects.
I just ran into a similar issue. DomainObject instances have this "neat" property called all which will return every instance of the domain object.
When JsonOutput tries to serialize your object, it uses DefaultGroovyMethods.getProperties, which includes the all property. This means that your code will cause hibernate to load EVERY copy of your Advisor class into memory.
In my case I ran out of memory. My system got stuck in garbage collection loops.
In your case, when your a1 class is being rendered, it is including the 'all' property, which is the full list of all Advisors. Each Advisor also has an "all" property so it tries to render every advisor. And so on. Eventually giving you your stack overflow.

Fetch returns only one item in collection

Table info:
The Image table contain a foreign key mediaid for its the parent table Media
----------
id | mediaid | url
========================
104 | 103 | IMG_PATH
383 | 103 | IMG_PATH
384 | 103 | IMG_PATH
395 | 103 | img_path
The Media entity holds a collection of Images :
private Set<Image> images = new HashSet<Image>(0)`;
#OneToMany(mappedBy = "media", targetEntity = Image.class ,cascade = CascadeType.ALL)
public Set<Image> getImages() {
return images;
}
Image entity snippet:
private Media media;
#ManyToOne
#JoinColumn(name = "mediaId")
public Media getMedia() {
return media;
}
I implemented the following query, that should return a Media object with a collection of all images whose fk matches its id provided.
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Media> cqObject = cb.createQuery(Media.class);
Root<Media> rootEntry = cqObject.from(Media.class);
rootEntry.fetch(Media_.images, JoinType.LEFT);
Predicate predicate = cb.equal(rootEntry.get(Media_.id), id);
cqObject.select(rootEntry).where(predicate);
Media _fetcheMedia = em.createQuery(cqObject).getSingleResult();
The collection for the Media object returned only ever contains one image item. I know for certain that database contains multiple Image items for the specified Media.
*Note Media_ is simply a metamodel class that represents the Media entity
Hibernate out for Media object with id=103
select media0_.mediaId as mediaId1_8_0_,
images1_.imageId as imageId1_6_1_,
media0_.active as active2_8_0_,
media0_.created as created3_8_0_,
media0_.description as descript4_8_0_,
media0_.listType as listType5_8_0_,
media0_.parentId as parentId6_8_0_,
media0_.propertyTypeId as property7_8_0_,
media0_.seasonId as seasonId8_8_0_,
media0_.status as status9_8_0_,
media0_.userId as userId10_8_0_,
images1_.active as active2_6_1_,
images1_.created as created3_6_1_,
images1_.imageTypeId as imageTyp5_6_1_,
images1_.imageUrl as imageUrl4_6_1_,
images1_.mediaId as mediaId6_6_1_,
images1_.mediaId as mediaId6_6_0__,
images1_.imageId as imageId1_6_0__ from media media0_
left outer join image images1_ on media0_.mediaId=images1_.mediaId where media0_.mediaId=103
It was a silly mistake on my part, I forgot to override the hashcode and equals method for the Image entity . Added them and it know works as it should.
#Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + (int) (id ^ (id >>> 32));
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
Image other = (Image) obj;
if (id != other.id)
return false;
return true;
}

Copy previous values kettle pentaho

I have an issue and i'm looping on it! :| I hope someone can help me..
So i have an input file (.xls), that is simple but there are a row (lets say its "ROW1") that is like this:
ROW1 | ROW2 | ROW3 | ROW_N
765 | 1 | AAAA-MM-DD | ...
null | 1 | AAAA-MM-DD | ...
null | 1 | AAAA-MM-DD | ...
944 | 2 | AAAA-MM-DD | ...
null | 2 | AAAA-MM-DD | ...
088 | 7 | AAAA-MM-DD | ...
555 | 2 | AAAA-MM-DD | ...
null | 2 | AAAA-MM-DD | ...
There are no stardard here, like you can see.. There are some lines null (ROW1) and in ROW2, there are equal numbers, with different association to ROW1 (like in line 5 and 6, then in line 8 and 9).
My objective is to copy and paste the values from ROW1, in the ROW1 after when is null, till isn't null. Basically is to copy form previous step, when is null...
I'm trying to use the "Formula" step, by using something like:
=IF(AND(ISBLANK([ROW1]);NOT(ISBLANK([ROW2]));ROW_n=ROW1;IF(AND(NOT(ISBLANK([ROW1]));NOT(ISBLANK([ROW2]));ROW_n=ROW1;ROW_n=""));
But nothing yet..
I've tried "Analytic Query" but nothing too..
I'm using just stream a xls file input..
Tks very much, any help is very much appreciiated!!
Best Regardsd!
Well i discover a solution, adding a "User Defined Java Class" with the code below:
import java.util.HashMap;
private FieldHelper output_field, card_field;
private RowSet out, log;
private String previou_card =null;
public boolean processRow(StepMetaInterface smi, StepDataInterface sdi) throws KettleException
{
if (first)
{
first = false;
out = findTargetRowSet("out");
output_field = get(Fields.Out, "previous_card");
} else {
Object[] r = getRow();
if (r == null) {
setOutputDone();
return false;
}
r = createOutputRow(r, data.outputRowMeta.size());
if (previous_card != null) {
output_field.setValue(r, previous_card);
}
if (card_field == null) {
card_field = get(Fields.In, "Grupo de Cartões");
}
String card = card_field.getString(r);
if (card != null && !card.isEmpty()) {
previous_card = card;
}
// Send the row on to the next step.
putRowTo(data.outputRowMeta, r, out);
}
return true;
After this i have to put a few steps but this help very much.
Thank you mates!!
Finally i got result. Please follow below steps
Below image is full transformation screen.
Data Grid Data will be like these. Sorry for that in my local i don't have Microsoft because of that i took Data Grid. Instead of Data Grid you can drag and drop Microsoft Excel Input step.
Drag and Drop one java script step and write below code.
Last step of transformation, drag and drop Select values step and select the columns.( These step is no necessary)
Final result will be like these.
Hope this helps.