Hibernate: Storing an fixed length array in one database table row - mysql

I have been trying to find a solution to store a fixed length array as a property of an object using hibernate in the same DB table as the object not using a BLOB for the array.
I currently have a class ProductionQCSession which looks like
#Entity
public class ProductionQCSession extends IdEntity {
private Long id;
private Float velocity;
private Float velocityTarget;
private Float[] velocityProfile;
public ProductionQCSession() {
}
#Id #GeneratedValue(strategy=GenerationType.AUTO)
#Override
public Long getId() {
return id;
}
#SuppressWarnings("unused")
public void setId(Long id) {
this.id = id;
}
#Basic
public Float getVelocity() {
return velocity;
}
public void setVelocity(Float velocity) {
this.velocity = velocity;
}
#Basic
public Float[] getVelocityProfile() {
return velocityProfile;
}
public void setVelocityProfile(Float[] velocityProfile) {
this.velocityProfile = velocityProfile;
}
}
Ideally I would like the DB structure to be
id|velocity|VPValue0|VPValue1|VPValue2|VPValue3|...
21| 2.1| 0.1| 0.2| -0.1| 0.3|...
I know with a high certainty that we always have 15 items in the velocityProfile array and those values as just as much properties of the object as any other property therefore I think it makes sense to add them to the database table schema, if it's possible. I would prefer to have it this way as it would be easy to get a overview of the data just doing a raw table print.
The current code just stores the array data as a BLOB.
I have looked http://ndpsoftware.com/HibernateMappingCheatSheet.html mapping cheat sheet, but could not seem to find any good solution.
I'm I just trying to do something nobody else would do?

Essentially, you're trying to have a multi-value field, which is not a relational database concept. A normalized solution would put those into a child table, which Hibernate would let you access directly from the parent row (and return it as a collection).
If you are adamant that it should be in a single table, then you'll need to create 15 individual columns....and hope that in the future you don't suddenly need 16.

The solution ended up being using the standardised method of using a child table even though it makes the data analysis slightly more complicated. The following code was used.
#ElementCollection
#CollectionTable(name ="QCVelocityProfile")
public List<Float> getVelocityProfile() {
return velocityProfile;
}
public void setVelocityProfile(List<Float> velocityProfile) {
this.velocityProfile = velocityProfile;
}

Related

How to read csv data one by one and pass it in multiple testNG tests

I need to insert a data multiple times in an web application. I am using selenium with testNG along with data driven framework.
I am using CSV file for reading the the input values.
Please find the sample code below.
public class TestData
{
private static String firstName;
public static String lastName;
#BeforeClass
public void beforeClass() throws IOException
{
reader = new CSVReader(new FileReader(fileName));
while((record = reader.readNext()) != null)
{
firstName = record[0];
lastName = record[1];
}
}
#Test
public void test1()
{
driver.findElement(By.id(id)).sendKeys(firstName);
driver.findElement(By.id(id)).click();
and so on....
}
#Test
public void test2()
{
driver.findElement(By.id(id)).sendKeys(lastName);
driver.findElement(By.id(id)).click();
and so on....
}
}
Here, I need to insert 3 records, but when I use the above code, only the 3rd record gets inserted.
Kindly help me to fix this issue.
Sample Input File
What you need here is a Factory powered by a DataProvider. The Factory would produce test class instances (A test class here is basically a regular class that contains one or more #Test methods housed in it). The data provider would basically feed the factory method with the data required to instantiate the test class.
Now your #Test methods would basically work with the data members in the instances to run its logic.
Here's a simple sample that shows this in action.
import org.assertj.core.api.Assertions;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Factory;
import org.testng.annotations.Test;
public class TestClassSample {
private String firstName;
private String lastName;
#Factory(dataProvider = "dp")
public TestClassSample(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
#DataProvider(name = "dp")
public static Object[][] getData() {
//feel free to replace this with the logic that reads up a csv file (using CSVReader)
// and then translates it to a 2D array.
return new Object[][]{
{"Mohan", "Kumar"},
{"Kane", "Williams"},
{"Mark", "Henry"}
};
}
#Test
public void test1() {
Assertions.assertThat(this.firstName).isNotEmpty();
}
#Test
public void test2() {
Assertions.assertThat(this.lastName).isNotEmpty();
}
}
As per the data given by you , the while loop ends at the third record of CSV file. In each iteration your variables "firstName" and "lastName" are overwritten.
When the loop breaks , the variables store the lastly written values. So , use a better data structure for storing all values. I recommend map.
You can further club all the test cases in a single method , use invocationcount attribute in #Test annotation to repeat the execution for each entry from map. Add one more method with #BeforeTest for increment to next keyset in map.

Jackson handling of remaining fields

I wonder if this is possible.
I have a huge json file to parse and modify.
But not all fields are interresting to me : I wan't to map only fields I'm interrested in, modify them then save the whole json with all fields I didn't care left unchanged.
Then suppose I have lot of properties and only one I'm interrested in named "MyProp", I tried something like
public class MyMapper extends HashMap {
private String myProp;
public void setMyProp(String myProp) {
this.myProp = myProp;
}
public String getMyProp() {
return myProp;
}
}
But the property "MyProp" is always null (until I remove "extends HashMap").
Instead all goes in the map.
Wouldn't be useful (or is it already possible ?) to be able to mix concrete fields with maps to work with known fields without loosing unknowns ?
And it would be better to did not extend HashMap but instead having a field to hold all unknown fields like this :
public class MyMapper {
private String myProp;
private Map remaining = new HashMap();
public void setMyProp(String myProp) {
this.myProp = myProp;
}
public String getMyProp() {
return myProp;
}
#JsonRemaining
public Map getRemaining() {
return remaining;
}
}
How would you do in this case ?
Seems like #JsonAnySetter and #JsonAnyGetter annotations might help. All irrelecant proerpties get stuffed into one Map and then the map contents get dumped back to json
See how-to guide here
http://vincentdevillers.blogspot.co.il/2013/08/how-to-map-unknown-json-properties-with.html

Queue Abstract Data Type - Float Elements

How would you design a queue abstract data type for float elements in C (or any preferred language), with operations for enqueue, dequeue, and empty? The dequeue operation should remove the element and returns its value.
Using Java, I came up with a quick and dirty solution as follows:
public class QueueOps {
private ArrayList<Float> queueReference;
public QueueOps(){
queueReference = new ArrayList<Float>();
}
public void enqueue(float number){
queueReference.add(number);
}
public float dequeue(){
float number = queueReference.get(0);
queueReference.remove(0);
queueReference.trimToSize();
return number;
}
public void empty(){
queueReference.clear();
}
}

Generic Singleton and share data between pages

To share data (complexe data ) between pages in my windows phone 8 application I want to implement a singleton, but I want it to be generic, is it possible? I suppose that it creates a new instance for each type isn't it?
public sealed class NavigationContextService<T>
{
private static readonly NavigationContextService<T> instance = new NavigationContextService<T>();
private NavigationContextService()
{
}
public static NavigationContextService<T> Instance
{
get
{
return instance;
}
}
public List<T> ShareList { get; set; }
public T ShareData { get; set; }
}
It is creating a new instance for every type, because it is generic - you want it to be like this (if you start with generics, take a look at some tutorials, blogs or MSDN - you will easily find many in the internet).
It is still a singleton. When you use
NavigationContextService<string>.Instance.ShareList.Add("Text");
then you have one Instance for type string. Generics helps a lot when you want to create same methods/classes that differ in type.
On the other hand if you want to create Singleton that will hold different types then you can for example modify your class to be non Generic like this:
public sealed class NavigationContextServiceNonGeneric
{
private static readonly NavigationContextServiceNonGeneric instance = new NavigationContextServiceNonGeneric();
private NavigationContextServiceNonGeneric() { ShareList = new List<object>(); }
public static NavigationContextServiceNonGeneric Instance
{ get { return instance; } }
public List<object> ShareList { get; set; }
public object ShareData { get; set; }
}
As you can see in the code above I haven't defined the 'exact' type of shared data - it is object type. Then you can easily hold most of data with it:
NavigationContextServiceNonGeneric.Instance.ShareList.Add("Text");
NavigationContextServiceNonGeneric.Instance.ShareList.Add(3);
NavigationContextServiceNonGeneric.Instance.ShareList.Add(3.0f);
It is singleton, which can hold different types of shared data. BUT it has also disavantages - the main is that you have to remember what type of data you hold and in what order. In my opinion Generic version is better because of that fact.
Everything depends on the purpose of your code. There may be easier and better ways that those two approaches.
As for the Page Navigation, you can for example try to use a method from this article - you extend Navigation service to pass the object:
public static class Extensions
{
private static object Data;
public static void Navigate(this NavigationService navigationService, Uri source, object data)
{
Data = data;
navigationService.Navigate(source);
}
public static object GetNavigationData(this NavigationService service) { return Data; }
}
Then you use it:
NavigationService.Navigate(yourUri, DataToPass);
After Navigation you can get your data:
string myTextData = NavigationService.GetNavigationData() as string;
This method has to disadvantages: it is not type-safe and your data won't be preserved in Tombstone mode.
As for the second disadvantage you can easily use PhoneApplicationService.State Property for the purpose of Page Navigation - it is a dictionary (which is preserved while tombstoning):
PhoneApplicationService.Current.State.Add("data", yourData);
Then when you want to get your data:
yourDataType yourData = PhoneApplicationService.Current.State["data"] as yourDataType;
There are also more ways in which you can pass the data.

The most efficient way to store photo reference in a database

I'm currently looking to store approximately 3.5 million photo's from approximately 100/200k users. I'm only using a mysql database on aws. My question is in regards to the most efficient way to store the photo reference. I'm only aware of two ways and I'm looking for an expert opinion.
Choice A
A user table with a photo_url column, in that column I would build a comma separated list of photo's that both maintain the name and sort order. The business logic would handle extracting the path from the photo name and append photo size. The downside is the processing expense.
Database example
"0ea102, e435b9, etc"
Business logic would build the following urls from photo name
/0e/a1/02.jpg
/0e/a1/02_thumb.jpg
/e4/35/b9.jpg
/e4/35/b9_thumb.jpg
Choice B - Relational Table joined on user table with the following fields. I'm just concerned I may have potential database performance issues.
pk
user_id
photo_url_800
photo_url_150
photo_url_45
order
Does anybody have any suggestions on the better solution?
The best and most common answer would be: choice B - Relational Table joined on user table with the following fields.
id
order
user_id
desc
photo_url_800
photo_url_150
photo_url_45
date_uploaded
Or a hybrid, wherein, you store the file names individually and add the photo directory with your business logic layer.
My analysis, your first option is a bad practice. Comma separated fields are not advisable for database. It would be difficult for you to update these fields and add description on it.
Regarding the table optimization, you might want to see these articles:
Optimizing MyISAM Queries
Optimizing InnoDB Queries
Here is an example of my final solution using the hibernate ORM, Christian Mark, and my hybrid solution.
#Entity
public class Photo extends StatefulEntity {
private static final String FILE_EXTENSION_JPEG = ".jpg";
private static final String ROOT_PHOTO_URL = "/photo/";
private static final String PHOTO_SIZE_800 = "_800";
private static final String PHOTO_SIZE_150 = "_150";
private static final String PHOTO_SIZE_100 = "_100";
private static final String PHOTO_SIZE_50 = "_50";
#ManyToOne
#JoinColumn(name = "profile_id", nullable = false)
private Profile profile;
//Example "a1d2b0" which will later get parsed into "/photo/a1/d2/b0_size.jpg"
//using the generatePhotoUrl business logic below.
#Column(nullable = false, length = 6)
private String fileName;
private boolean temp;
#Column(nullable = false)
private int orderBy;
#Temporal(TemporalType.TIMESTAMP)
private Date dateUploaded;
public Profile getProfile() {
return profile;
}
public void setProfile(Profile profile) {
this.profile = profile;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public Date getDateUploaded() {
return dateUploaded;
}
public void setDateUploaded(Date dateUploaded) {
this.dateUploaded = dateUploaded;
}
public boolean isTemp() {
return temp;
}
public void setTemp(boolean temp) {
this.temp = temp;
}
public int getOrderBy() {
return orderBy;
}
public void setOrderBy(int orderBy) {
this.orderBy = orderBy;
}
public String getPhotoSize800() {
return generatePhotoURL(PHOTO_SIZE_800);
}
public String getPhotoSize150() {
return generatePhotoURL(PHOTO_SIZE_150);
}
public String getPhotoSize100() {
return generatePhotoURL(PHOTO_SIZE_100);
}
public String getPhotoSize50() {
return generatePhotoURL(PHOTO_SIZE_50);
}
private String generatePhotoURL(String photoSize) {
String firstDir = getFileName().substring(0, 2);
String secondDir = getFileName().substring(2, 4);
String photoName = getFileName().substring(4, 6);
StringBuilder sb = new StringBuilder();
sb.append(ROOT_PHOTO_URL);
sb.append("/");
sb.append(firstDir);
sb.append("/");
sb.append(secondDir);
sb.append("/");
sb.append(photoName);
sb.append(photoSize);
sb.append(FILE_EXTENSION_JPEG);
return sb.toString();
}
}