JDK 1.6x, Hibernate 3.2.7, Oracle 10g (ojdbc14.jar)
i have a (entity) class that contains a clob. Through a RESTful call i am passed a string that will be the content of the clob. i am having trouble stuffing the string into a clob for later persistence. here's the class....
public class MyClass implements java.io.Serializable {
private static final long serialVersionUID = 5507279748316866736L;
private long id;
private String name;
private String description;
private java.sql.Clob featuresJson;
...etc...
here's the deserialization code...
try {
String jsonStr = msoNode.path("features_json").getTextValue();
SerialClob clob = new SerialClob(jsonStr.toCharArray());
mso.setFeaturesJson(clob);
} catch (Exception e) {
log.error("MyClassDeserializer.deserialize(): Exception deserializing the features JSON." + e.getMessage());
}
after deserialization, i'm onto the Dao's merge statement...
MyClass savedOverlay = myClassDao.merge(overlay);
where "overlay" is a deserialized "MyClass" instance. at this point i can peek inside the clob and see the data -- however the returned instance has the clob field null'ed out, and the clob column in the database is null as well!
What's wrong with my deserialization code? i've tried a few other things, but get failures each and every time (at least that is consistent!)
SOLVED!
there is an annotation #Lob that needed to be specified on the column. also the same column that had been reverse-engineered to be of type java.sql.Clob needed to be changed to String.
Related
in addition to the first question with working answer
I was not able to deserialize the following
private #Serialize List<ProduktSprache> produktsprachen;
the new class looks like this stored as Blob with orginaly having two fields defined as Text:
import java.io.Serializable;
import com.googlecode.objectify.annotation.Serialize;
public class ProduktSprache implements Serializable {
private static final long serialVersionUID = 1L;
private String sprache;
private String name;
private String details;
private String detailsText; // TEXT
private String detailsTextHTML; // TEXT
It's really hard to tell what's going on here, but it sounds like you have some data that was serialized (with java serialization) into the field. To figure this out, I'd try to simplify it as much as possible.
Serialized data is written as type Blob in the entity. So the first step is to change your produktsprachen field to type Blob. Now you can load the entity and you have a byte[] of data to work with.
Next, try to decode that byte[]. Use an ObjectInputStream to read the contents and inspect what you actually have present. Whatever structure you find there is what you eventually need to use as your #Serialized field type in your Objectify entity class.
I do have a Repository
#Repository
public interface PointOfInterestRepository extends GraphRepository<Poi> {
// currently empty
}
with no custom methods defined. So I use the like of save(T... entities) which are predefined.
And I have my Poi class as follows
#NodeEntity(label = "PointOfInterest")
public class Poi {
#JsonIgnore
#GraphId
Long neo4jId;
#JsonManagedReference("node-poi")
#JsonProperty("node")
#Relationship(type = "BELONGS_TO", direction = Relationship.UNDIRECTED)
private Node node;
#JsonProperty("id")
#Property(name = "poiID")
private final String id;
#JsonProperty("uris")
#Property(name = "uris")
private final Set<URI> correspondingURIs = new HashSet<>();
/* Some more stuff I skip here*/
}
with getters for the fields.
Currently I am able to save such Pois to neo4j and retrieve them back, but when I try to work with those Nodes in the database via cypher it appears that the fields aren't mapped to neo4j properties.
I thought spring-data-neo4j would convert my class fields to neo4j graph properties. Am I wrong with that?
Note: The save calls seems to work very well. After that I can see the Nodes in the database and calling findAll() afterwards will return me all the saved Nodes (Pois) properly with all the correct values. But somehow, within the database, I cannot see any properties/fields.
The problem is the final fields. SDN would be unable to write values back to the entity when loaded from the graph because these fields are final (and SDN will use only the default no-args constructor), and as such, final fields are not supported.
Removing the final should fix this.
In an existing Java EE application there is a JPA entity which contains a string array as a field. Bad, but it is what it is. There are no annotations for it whatsoever and running the application results in Hibernate (on JBoss EAP 6.1 Alpha and MySQL 5.6) storing it as TINYBLOB. This obviously fails as soon as the string array contains more than a couple values but yet it works fine as long as the array is not too big.
Is there any way to force via JPA 2 (not Hibernate!) annotation that the field is treated as BLOB instead of TINYBLOB?
Using the following will actually create a column of type BLOB during setup but when trying to store an instance of the entity it still fails with
java.lang.ClassCastException: [Ljava.lang.String; cannot be cast to java.lang.String"
Field annotation definition:
#Lob
#Column(columnDefinition = "blob")
I think you are on a write way. To avoid ClassCastException try to add converter calss and serialize it manually. Add annotation #Convert(converter = YoursConvertor.class) and implement convertor class, something like this:
public class YoursConvertor implements AttributeConverter<String[], String> {
#Override
public String convertToDatabaseColumn(String[] meta) {
String concatString = "";
//... some concatinantion etc
return concatString;
}
#Override
public String[] convertToEntityAttribute(String dbData) {
String[] result = null;
if (dbData != null && dbData.length() > 0) {
//... unconcat
}
return result;
}
}
Maybe it must be String[], byte[] - you should try
I was unable to read the full inherited class instances as described in following URL
http://www.datanucleus.org/products/datanucleus/jdo/orm/inheritance.html
Following describes the mapping of classes.
#PersistenceCapable(detachable = "true")
#Discriminator(strategy=DiscriminatorStrategy.CLASS_NAME)
#Inheritance(strategy=InheritanceStrategy.NEW_TABLE)
public class IdeaItem {
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
#Column(jdbcType = "INTEGER", length = 11)
private long id;
#Column(name="IDEAID")
private Idea idea;
#Column(jdbcType = "INTEGER", length = 11)
private long showOrder;
}
#PersistenceCapable(detachable = "true")
#Inheritance(strategy=InheritanceStrategy.NEW_TABLE)
public class IdeaItemText extends IdeaItem {
#Column(jdbcType = "VARCHAR", length = 500)
private String text;
}
Data saving part working fine. I inserted "IdeaItemText" object and both "IdeaItem" and "IdeaItemText" tables got updated successfully.
Now I need to read Subclasses by putting "IdeaItem" as an Extent. I executed the following code.
Extent items = getPersistenceManager().getExtent(IdeaItem.class,true);
javax.jdo.Query q = getPersistenceManager().newQuery(items);
List data = (List)q.execute();
As in the JDO docs, this should return the whole object graph. But this is not returning any record. When I check the log, I found that it searching for a reacord where Discriminator Value equals to "com.mydomain.IdeaItem" which does not exists. When I removed the Discriminator annotation I got all the records in the table. Even though how I access the sub classes attributes ? Furthermore how I query subclass attributes with the base class Extent ?
So you didn't let the persistence mechanism know about the subclass (whether that is using auto-start mechanism, persistence.xml, calling pm.getExtent on the subclass, or simply instantiating the subclass.class). It can only query classes that it is "aware of"
I have an existing database that I am now connecting to using hibernate. I cannot change the data in it at the moment and have everything working apart from a single column.
I have a status column that has the values:
new
mailed
in
out
And the column is mapped as follows:
#Column(name = "STATUS", nullable = false, length = 50)
#Enumerated(EnumType.STRING)
private TeamMemberStatus status;
I would REALLY like (for application reasons) to have this column mapped as a Java Enum (TeamMemberStatus), but due to the fact that 'new' is a keyword in Java I cannot have that as an enum member.
If I have the enum contstants NEW, MAILED, IN and OUT hibernate fails as inside EnumType it does a Enum.valueOf().
Is there any way for me to map this to my Enum without having to write a complex UserType?
-- added content
My Enum like this:
public enum TeamMemberStatus {
NEW, MAILED, IN, OUT
}
is a valid Java enum, but not matching the case of the database. If I change it to match the database like:
public enum TeamMemberStatus {
new, mailed, in, out
}
It won't compile as 'new' is a Java reserved word.
If you can use a SQL UPPER statement at database, It will work without using any UserType
UPDATE
Well, It can not be The nicest solution but it solves what you want
#Entity
public class WrapperEntity {
private TeamMemberStatus memberStatus;
#Transient
private TeamMemberStatus getMemberStatus() {
return this.memberStatus;
}
public void setMemberStatus(TeamMemberStatus memberStatus) {
this.memberStatus = memberStatus;
}
#Column(name="STATUS", nullable=false, length=50)
public String getMemberStatusAsString() {
return memberStatus.name().toLowerCase();
}
public void setMemberStatusAsString(String memberStatus) {
this.setsetMemberStatus(TeamMemberStatus.valueOf(memberStatus.toUpperCase()));
}
}
If your Database values are "new", "mailed", "in" and "out" then your Enum need exactly the same names. - I believe that the problem is, that your Enums are in capital letters but your data base values not.