Stockage Double.POSITIVE_INFINITY dans MySQL (entité EJB / JBoss)
Question
Je simple entité JPA suivante:
@Entity
@Table( name = myentity_table )
public class MyEntity {
private double a;
private double b;
//(...)
}
et b peut être mis à Double.POSITIVE_INFINITY
. Lorsque je tente d'entité magasin avec double jeu à + INF dans la base de données (MySQL) en utilisant le gestionnaire de l'entité standard que je reçois exception:
java.sql.SQLException: 'Infinity' est pas une valeur numérique ou numérique approximative valide
Pour autant que je sais MySQL ne supporte pas le nombre NaN / -INF / + INF. Est-il possible de stocker cette entité sans écrire des requêtes HQL et traduction + INF en nul (ou double max)? Idéalement, je voudrais le faire via le gestionnaire d'entités comme d'habitude.
Merci à l'avance.
La solution
Entité méthodes de rappel de cycle de vie @PrePersist, @PreUpdate peuvent être utilisés ici pour vérifier la valeur du champ NAN / -INF / + INF etc et puis définir la valeur par défaut en conséquence.
//--
@PrePersist
@PreUpdate
private void resetField() {
if(field == Double.POSITIVE_INFINITY)
field = somePredefinedValue;
}
//--
Autres conseils
MySQL ne semble pas soutenir « l'infini ». les écritures de cet article que:
stockage et la récupération de l'infini négatif dans une base de données MySQL est réalisée en insérant un nombre arbitrairement grand négatif.
Même va pour le positif. Autres ressources utilisent également 1e500
.
Au lieu d'utiliser l'infini, je suggère que vous utilisez Float.MAX_VALUE
et Float.MIN_VALUE
(ou équivalents Double
)
Si vous ne pouvez pas faire cela dans votre code lorsque vous définissez les valeurs, faites-le dans un @PrePersist
comme cela a déjà suggéré.
Je géré ce problème en ajoutant une colonne varchar pour stocker la représentation textuelle de Float.NaN
, Float.POSITIVE_INFINITY
et Float.NEGATIVE_INFINITY
tandis que la colonne d'origine stockera NULL
.
Puis-je utiliser le compositeur et le getter à faire gérer ces deux colonnes.
Dans ma classe @Entity
/** 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;
}
}
Résultat:
| 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 |