Database : Table and mappings for a Matrix style table - database

I am working on a Spring-MVC using Postgres application in which I am trying to do a report generation form. Now, for this, I have to save the data for the form. But, the report has this matrix kind of part, which I don't know how to realize. Sure I can do it, but I want something optimized.
As you can see from the image, on left side, there are fields and each field has different values to be inserted as indicated.
As of now, I was able to come up only one Table as Parts and its class is mentioned below. But as each variable in the class will have 6 values, it will require me to create 6 tables and have some mapping. I want to avoid that. What can I do?
#Entity
#Table(name = "containment")
public class Containment {
#Id
#Column(name="containment_id")
#GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "containment_gen")
#SequenceGenerator(name = "containment_gen",sequenceName = "containment_seq")
private Long containmentId;
#Column(name = "parts_at_plant")
private String partsAtPlant;
#Column(name = "parts_at_logistics")
private String partsAtLogistics;
}
I am creating class, not writing database-tables directly. If someone wants to see above in SQL code, I am more than happy to write it. Thank you.

Related

Objectify queries are very slow (Google Datastore)

After some refactoring, we are having issues with the objectify queries that we are using in the application. The strange thing is that even if we revert to the original code the problem stays.
When the application starts, a number of 250 books are fetched from the Datastore using Objectify. The caching is enabled and seems to be working.
The problem is that it takes around 50 - 60 seconds to get the result, and for this reason sometimes the http request is killed. We never had this issues before and we can't find an answer to it.
If I ran a query like "select * from BookEntity order by creationDate desc limit 250" in the Google Datastore console and it took 5 - 7 seconds not more.
Before the refactoring, the book entity looked something like this:
#Index
#Entity
#Cache
public class BookEntity {
#Index
public String title_name;
#Index
public String author_name;
public String isbn;
public int number_of_pages;
public Ref<PdfEntity> book_pdf;
}
Now it's like this:
#Index
#Entity
#Cache
public class BookEntity {
#Index
#AlsoLoad("title_name")
private String titleName;
#Index
#AlsoLoad("author_name")
private String authorName;
private String isbn;
#AlsoLoad("number_of_pages")
private int numberOfPages;
#AlsoLoad("book_pdf")
private Ref<PdfEntity> bookPdf;
// getters and setters for the fields because now they are private
}
Here is just an example, but in reality it has around 20 fields.
In order to migrate the schema to the field names, I ran a task in GAE which loaded and then saved again all the BookEntity entities.
This example can be extended to all the entities that are used in the application, but the book is the worst performing one. Even though nothing is changed in the query, and we are talking about a basic query which fetches the newest 250 books by creationDate, it takes a lifetime to get the actual result. Any idea how I can investigate this issues further?
Problem found. We were persisting some information in the non-args constructor of the BookEntity, so for every book fetched from the datastore 3 save operations were made for some other entities which are referred from the book.

Hibernate Annotation Exception when migrating from JBoss 5.1 to JBoss EAP 6

My understanding is that JBoss 5.1 uses Hibernate 3.4.0.GA. JBoss 6 uses Hibernate 4.2.18.Final.
I have an entity class with a #ManyToOne,#JoinTable reference which seems to run fine in JBoss 5.1. Please see the simplified class below.
#Entity
#Table(name = "[Professional Activity (Field Display Names)]")
public class ProfessionalActivity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "ID")
private Long id;
#ManyToOne
#JoinTable(name = "[Professional Activity User Relationship]",
joinColumns = #JoinColumn(name = "[Professional Activity ID]"),
inverseJoinColumns = #JoinColumn(name = "[User ID]"))
private User user;
}
Needless to say (but I'll say it anyway!), [Professional Activity User Relationship] is just a "Join Table" that maps Professional Activities to Users. Again, this is working great with old Hibernate. Is this a bug in Hibernate 4 or is there a better way to be annotating this? This is the stack trace I'm getting:
Exception in thread "main" javax.persistence.PersistenceException: [PersistenceUnit: efcEntityManagerLocal] Unable to build EntityManagerFactory
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:925)
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:900)
at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:59)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:63)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:47)
at edu.emory.first.cache.service.HibernateTest.main(HibernateTest.java:15)
Caused by: org.hibernate.AnnotationException: Cannot find the expected secondary table: no Professional Activity User Relationship available for edu.emory.first.cache.model.ProfessionalActivity
at org.hibernate.cfg.Ejb3Column.getJoin(Ejb3Column.java:372)
at org.hibernate.cfg.Ejb3Column.getTable(Ejb3Column.java:351)
at org.hibernate.cfg.AnnotationBinder.bindManyToOne(AnnotationBinder.java:2741)
at org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:1728)
at org.hibernate.cfg.AnnotationBinder.processIdPropertiesIfNotAlready(AnnotationBinder.java:895)
at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:728)
at org.hibernate.cfg.Configuration$MetadataSourceQueue.processAnnotatedClassesQueue(Configuration.java:3625)
at org.hibernate.cfg.Configuration$MetadataSourceQueue.processMetadata(Configuration.java:3579)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1381)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1786)
at org.hibernate.ejb.EntityManagerFactoryImpl.<init>(EntityManagerFactoryImpl.java:96)
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:915)
... 5 more
Update
It looks like it might be related to the fact that my backing DB is a SQLServer Database and the table I'm trying to join is required to have either brackets, back-ticks, or quotes (when I escape them with a backslash).
Basically, these three make the SQL happy but not Hibernate:
name = "\"Professional Activity User Relationship\""
name = "`Professional Activity User Relationship`"
name = "[Professional Activity User Relationship]"
I've tried changing the Dialects from Sql2008Server, Sql2012Server, etc. to no avail. I've tried NO specified dialect in the persistence.xml and that didn't seem to change anything.
Basically I see two workarounds, although I'd rather not do either.
Create a view of the offending table and make the name with no spaces so I don't have to use the characters([,`,\") which seem to be causing the issue (i.e. Professional_Activity_User_Relationship_View).
Create an entity class for the join table, add a few ManyToOne Relationships and just increase my joins at the EntityManager query level.
Neither are optimal. Is this an issue I should raise with Hibernate? Seems like even switching to 5 didn't resolve the issue.
Update 2
I have created a JIRA ticket for this: https://hibernate.atlassian.net/browse/HHH-10660

Most efficient way to do this select in JPA 2?

I have an Entity that looks like this:
#Entity
public class Relationship
{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Key key;
#Basic
private UUID from;
#Basic
private UUID to;
}
Now I can have arbitrary levels of indirection here like so:
final Relationship r0 = new Relationship(a,b);
final Relationship r1 = new Relationship(b,c);
final Relationship r2 = new Relationship(c,d);
final Relationship rN = new Relationship(d,e);
Now what I want to find out as efficiently as possible is given a give me back e where rN is N level deep.
If I was writing regular SQL I would do something like the follow pseudo code :
SELECT r.to
FROM relationship r
WHERE r.from = 'a' AND
r.to NOT IN ( SELECT r.from FROM relationship r)
The only thing I can find online is references to passing in a List as a parameter to a Criteria.Builder.In but I don't have the list, I need to use a sub-select as the list?
Also this is using the Datastore in Google App Engine, and it is restricted on some things that it supports via JPA 2.
Am I going to have to resort to the low level Datastore API?
In the datastore, there's no way to issue a single query to get 'e' from 'a'. In fact the only way to get e, is to individually query each Relationship linearly, so you'll need to do four queries.
You can pass in a list as a parameter, but that's only for an IN query. NOT IN queries are not available, and neither are JOINs.
(Aside: you could use a combination of the from and to properties to create a key, in which case you could just fetch the entity instead of query).
Usually, the GAE datastore version of doing things is to denormalize, ie write extra data that will enable your queries. (This is a pain, because it also means that when you update an entity, you need to be careful to update the denormalized data as well, and it can be hard to synchronize this - It's designed for web type traffic where reads occur much more frequently than writes.)
This is a potential solution:
#Entity
public class Relationship
{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Key key;
#Basic
private UUID from;
#Basic
private UUID to;
#ElementCollection
private Collection<UUID> reachable;
}
In this case you would simply query
WHERE from = 'a' and reachable = 'e'
Solution
Surprisingly enough this recursive method doesn't error out with a StackOverflow even with 1000 levels of indirection, at least not on my local development server.
public UUID resolve(#Nonnull final UUID uuid)
{
final EntityManager em = EMF.TRANSACTIONS_OPTIONAL.createEntityManager();
try
{
final String qs = String.format("SELECT FROM %s a WHERE a.from = :from ", Alias.class.getName());
final TypedQuery<Alias> q = em.createQuery(qs, Alias.class);
q.setParameter("from", uuid);
final Alias r;
try
{
r = q.getSingleResult();
final Key tok = KeyFactory.createKey(Alias.class.getSimpleName(), r.getTo().toString());
if (em.find(Alias.class, tok) == null)
{
return r.getTo();
}
else
{
return this.resolve(r.getTo());
}
}
catch (final NoResultException e)
{
/* this is expected when there are no more aliases */
return uuid;
}
}
finally
{
em.close();
}
}
The stress test code I had is timing out on the actual GAE Service, but I am not worried about it, I won't be creating more than one level of indirection at a time in practice. And there won't be more than a handful of indirections either, and it will all get hoisted up into Memcache in the final version anyway.

Adding a row to a table from the properties of a class

I have a class that represents the table of a db-row. Its properties are the columns of the table. I add a new row to the table with the following code:
Public Sub AddRow(oTestRow As TestRow)
Dim sql As String
With oTestRow
sql = String.Format("INSERT INTO TestTable " &
"(ArtNr, ArtName, ArtName2, IsVal, CLenght) " &
"Values ('{0}', '{1}', '{2}', {3}, {4})",
.ArtNr, .ArtName, .ArtName2, .IsVal, .CLenght)
End With
Using oConn As New OleDbConnection(m_ConnString)
oConn.Open()
Using oInsertCmd As New OleDbCommand(sql, oConn)
oInsertCmd.ExecuteNonQuery()
End Using
End Using
End Sub
That is just an example, but my classes have around 30-40 properties and this brings a very large and complex sql string.
Creating, editing or maintaining these sql strings for many classes could generate errors.
I am wondering if any compact way or method exists in order to add the whole object's istance (the properties of course) to the table "TestTable" without writing such a large sql string.
I created the TestRow in the way that its properties are exactly the columns of the table "TestTable" (with the same name). But I did not found in the ADO.NET anything that could be used.
If changing DB system is an option, you may wanna take a look at some document based no sql solution like MongoDB, CouchDB or especially for .Net RavenDB, db4o or Eloquera.
Here is a list of some of them.
for starters anything with inline queries is a bad practice (unless the need demands for e.g. you have tables defined in the db, and dont have access to the db to deploy procedures)
you have few options - for e.g. instead of handwriting the classes , use Entitiy framework a better alternative to Linq2Sql
if you want to stick with the tags in this question I would design this making the most of OO concepts. (this is a rough sketch, but I hope this helps)
public class dbObject
protected <type> ID --- This is important. if this has value, commit will assume update, otherwise an update will be performed
public property DBTableName // set the table name
public property CommitStoredprocedure // the procedure on the database that can do commit work
public property SelectStoredProcedure // the procedure used to retrieve the i
public dbObject construcor (connection string or dbcontext etc)
set dbConnection here
end constructor
public method commit
reflect on this.properties available and prepare your commit string.
if you are using storedproc ensure that you prepare named parameters and that the stored proc is defined with the same property names as your class property names. also ensure that storedproc will update if there is an ID value or insert and return a ID when the id value is not available
Create ADO.net command and execute. (this is said easy here but you need to perfect this method)
End method
end class
public class employee inherits dbObject
// employee properties here
public string name;
end employee
public class another inherits dbObject
//another properties
public bool isValid;
end department
usage:
employee e = new employee;
e.name = "John Smith";
e.commit();
console.WriteLine(e.id); // will be the id set by the commit method from the db
If you make baseclass correct (well tested) here, this is automated and you shouldnt see errors.
you will need to extend the base class to Retrieve records from the db based on an id (if you want to instantiate objects from db)

store strings of arbitrary length in Postgresql

I have a Spring application which uses JPA (Hibernate) initially created with Spring Roo. I need to store Strings with arbitrary length, so for that reason I've annotated the field with #Lob:
public class MyEntity{
#NotNull
#Size(min = 2)
#Lob
private String message;
...
}
The application works ok in localhost but I've deployed it to an external server and it a problem with encoding has appeared. For that reason I'd like to check if the data stored in the PostgreSQL database is ok or not. The application creates/updates the tables automatically. And for that field (message) it has created a column of type:
text NOT NULL
The problem is that after storing data if I browse the table or just do a SELECT of that column I can't see the text but numbers. Those numbers seems to be identifiers to "somewhere" where that information is stored.
Can anyone tell me exactly what are these identifiers and if there is any way of being able to see the stored data in a #Lob columm from a pgAdmin or a select clause?
Is there any better way to store Strings of arbitrary length in JPA?
Thanks.
I would recommend skipping the '#Lob' annotation and use columnDefinition like this:
#Column(columnDefinition="TEXT")
see if that helps viewing the data while browsing the database itself.
Use the #LOB definition, it is correct. The table is storing an OID to the catalogs -> postegreSQL-> tables -> pg_largeobject table.
The binary data is stored here efficiently and JPA will correctly get the data out and store it for you with this as an implementation detail.
Old question, but here is what I found when I encountered this:
http://www.solewing.org/blog/2015/08/hibernate-postgresql-and-lob-string/
Relevant parts below.
#Entity
#Table(name = "note")
#Access(AccessType.FIELD)
class NoteEntity {
#Id
private Long id;
#Lob
#Column(name = "note_text")
private String noteText;
public NoteEntity() { }
public NoteEntity(String noteText) { this.noteText = noteText }
}
The Hibernate PostgreSQL9Dialect stores #Lob String attribute values by explicitly creating a large object instance, and then storing the UID of the object in the column associated with attribute.
Obviously, the text of our notes isn’t really in the column. So where is it? The answer is that Hibernate explicitly created a large object for each note, and stored the UID of the object in the column. If we use some PostgreSQL large object functions, we can retrieve the text itself.
Use this to query:
SELECT id,
convert_from(loread(
lo_open(note_text::int, x'40000'::int), x'40000'::int), 'UTF-8')
AS note_text
FROM note

Resources