In JPA how to define a table column that can store either a CLOB or a BLOB - jpa-2.0

I am defining an entity that just stores document objects for the user. Sometimes the object is a binary (BLOB) such as a PNG or JPG image, and sometimes it is character based, such as RTF text files or a MIME text/* type. All documents have a unique ID in the same name space. The properties are roughly like this:
#Id private long id;
#Column private String type;
#Lob private byte [] rawData;
Now I could just provide some accessor methods that would convert rawData from a byte [] to a String on demand, but is there a technique that avoids the frequent conversion step in the case of character data? Note that I don't want the JPA provider to do it either -- I want to use one table column to store either the character data or the binary data with minimal or no transcription overhead when it is injected into the entity instance.
I think I should be able to code a base class and two sub-classes like this:
#Entity
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name = "TYPE", discriminatorType = DiscriminatorType.STRING)
public class Document {
#Id private long id;
#Column private String type;
}
#Entity
#DiscriminatorValue("binary")
public class BinaryDocument extends Document {
#Column #Lob private byte [] binaryData;
}
#Entity
#DiscriminatorValue("text")
public class TextDocument extends Document {
#Column #Lob private String textData;
}
(omitted accessor methods for brevity)
If I understand this I would end up with a table with two #Lob columns, binaryData and textData. Is there any way to make them the same column?
Or should I care? Would the space requirement for having two columns (only one of which is used in each instance of the class) be minimal?
Or should I be taking a completely different approach? I am open to suggestion since I haven't spent much time on coding this yet.

Related

Objectify - Order by reference

is it possible in Objectify to order by a field of a referenced object?
Example:
public class Foo {
#Id private long id;
#Index Ref<AnObject> ref;
}
public class AnObject {{
#Id private long id;
#Index name;
}
Then I try to do this query and it's not working:
Query<Foo> query = ofy().load().type(Foo.class)
.limit(Constants.DATASTORE_LIMIT)
.order("ref.name");
Thanks.
I'm afraid not. This is not something supported by the datastore. It can't do joins.
There are basically two ways around that limitation:
Denormalize and put an indexed copy of the 'name' data in your Foo object. You can do this somewhat automatically with an #OnSave method. The downside is that you need to remember to update the data in both places if it changes.
Do the work of the query planner yourself. Query for the relevant AnObjects, then query for the relevant Foos.

Doctrine2 with dynamic relationships base on a value

What I'm trying to do is basically Entity A which have field type to relate with Entity B or C base on the value of field type
for example: a Product if is type drinks to be related with DrinkOptions entity, but if it's with type food to be related with FoodOptions entity
Is there any elegant solution which can work fine in such case?
This is what I thought it will work, but it doesn't..
Changing dynamically the entity A relation will not help, because it's not yet loaded and I can't see the value of field type
combine the different option entities into one, but it will be very ugly picture with 200+ properties..
define all option types in the config and then dynamically create the mapping with the loadClassMetadata, but is not so pretty also it requires a "dummy" property, getters and setters for all option types in the Entity A
A possible solutions could be to use a single table inheritance. Might not be the nicest solution but it could fit your specific need.
<?php
namespace MyProject\Model;
/**
* #Entity
* #InheritanceType("SINGLE_TABLE")
* #DiscriminatorColumn(name="discriminator", type="string")
* #DiscriminatorMap({"drink" = "DrinkOption", "food" = "FoodOption"})
*/
class Option
{
// ...
}
/**
* #Entity
*/
class FoodOption extends Option
{
// ...
}
/**
* #Entity
*/
class DrinkOption extends Option
{
// ...
}
You then could even switch the type by altering the "discriminator" column.
I think the simpliest way would be to have multiple product entities with an inheritence
Like Product (parent) -> foodProduct (child) or DrinkProduct().
This way you could have Product link to common others entities (like price or brand) and specific link for food, drinks, smokes etc...
Product
id:
type: food/drink/smoke etc..
foodproduct: one to Many nullable: FoodProduct (it's actually one to zero/one but i find it more performant)
drinkproduct: one to Many nullable: DrinkProduct
smokeproduct:one to Many nullable: SmokeProduct
FoodProduct:
id:
product_id (many to one to Product)
options one to many to foodOptions
If it still don't fit you will have to find some design pattern

Querying instances contained in a list

I have created a list (dd) which contains instances of a class. I want to be able to perform queries on some of its attributes (eg. finding the smallest numeric value), but cannot find a way to do this using the functionality of the class (I feel like going back to analysing the data by column). How do I access the values in one of the attributes when my instances are now on a list? Thanks!
Assuming you're using C# and having a class like this
class Foo
{
public double Bar { get; set; }
}
then LINQ is exactly what you are looking for
List<Foo> list = GetList();
var filtered = list.Where(p => p.Bar > 23.0);
Have a look at these examples:
https://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b

JPA deleting inverse relationship

I have been trying to delete the inverse relationship on a JPA entity, however this have not been working well. What I'm trying right now is to set the ManyToOne property to null and then saving it using the entityManager's merge method. The ManyToOne relationship is marked with the cascade all property, however in the dataBase the foreign key is not removed. How should I do this?. Thanks a lot.
It would be easier to find out what you mean, with code in question. But I will try anyway:
#Entity
public class AEntity {
#GeneratedValue (strategy = GenerationType.SEQUENCE)
#Id int id;
//Having some cascade here doesn't matter for our case
//because we now do not cascade anything, we just set this field to
//null. Cascade=REMOVE is about never meaningful (and never fully
//fully portable) in ManyToOne side:
//just think what happens to other AEntity instances that refer to
//same BEntity.
#ManyToOne
BEntity bEntity;
public void setbEntity(BEntity bEntity) {
this.bEntity = bEntity;
}
}
public class BEntity {
#GeneratedValue(strategy = GenerationType.SEQUENCE)
#Id int id;
}
In the beginning we have following data:
AEntity(id=1,bEntity_id=2)
BEntity(id=2)
Then removing connection between a and b:
AEntity oldDirty = em.find(AEntity.class, 1);
//modify A somewhere else in code
oldDirty.setbEntity(null);
//and bring changes in:
em.merge(oldDirty);
Afterwards we have:
AEntity(id=1,bEntity_id=null)
BEntity(id=2)
If BEntity also have set that contains AEntity entities (so to say bidirectional relationship), then you have to remove A from there as well, because you have to keep care about relationship by yourself. OneToMany side is one where it can make sense to cascade removal from.
Check the cascade type of the relationship on both ends. For instance, if you want to delete all the associated entities when you delete the main entity, the annotation should look like this: #ManyToOne(cascade={CascadeType.REMOVE}), and on the inverse #OneToMany(cascade={CascadeType.REMOVE})

What is the significance of specifying a relationship as 'One to One' in JPA?

i created a class
#Entity
public class **Department** implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
#OneToOne
private **Doctor** head;
.........
}
As per the spec, when an entity Department references a single entity Doctor, no other Department s can refer the same Doctor
But i could make 2 different Department s refer to the same Doctor
ie, the Doctor id in the department table is not Unique
how its possible?
The mapping only describes how your entities should be saved to/loaded from the database. It doesn't automatically insert constraints in the database schema, and does not make sure that all the data you create respects the mapping.
You must create and enable the appropriate constraints in the database schema.