How to get an entity-related object correctly - java

I have approximately the following entity:
public class Article {
private String name;
private Long fileId;
}
As you can see, it has a field fileld that contains the id of the associated file, which is also an entity. However, the file does not know anything about the Article, so the only thing that connects them is the fileId field in the Article. Therefore, they must be explicitly linked so as not to get lost. Now to get a linked file, I have to make a separate query to the database for each Article. That is, if I want to get a list of 10 Articles, I need to make a request to the database 10 times and get the file by its id. This looks very inefficient. How can this be done better? I use jooq, so I can't use JPA, so I can't substitute a file object instead of the fileId field. Any ideas?

I'm going to make an assumption that your underlying tables are something like this:
create table file (
id bigint primary key
content blob
);
create table article (
name text,
file_id bigint references file
);
In case of which you can fetch all 10 files into memory using a single query like this:
Result<?> result =
ctx.select()
.from(ARTICLE)
.join(FILE).on(ARTICLE.FILE_ID.eq(FILE.ID))
.fetch();

Related

How do I use Jooq insert ... returning in MySQL without code generation?

I've been trying to use insert...returning in MySQL with the DSL-based table definition (I'm not using the code generation) and my returned record is always null. Based on reading, I need to specify the identify column in the table definition, but I have no idea how!
Record recordKey = create.insertInto(table("modulerecords"),
field("id"),
field("module_id"),
field("created_date"),
field("created_by"),
field("state"),
field("tag_id"),
field("start_time",Timestamp.class),
field("kill_time", Timestamp.class),
field("feed_guid")
)
.values(null, moduleId, currentTimestamp(),
userId, state, tagId,
new Timestamp(startTime),
new Timestamp(killTime), feedGuid)
.returning(field("id"))
.fetchOne();
The field "id" is auto_increment primary key in the database, but recordKey is always null.
As of jOOQ 3.14, this is possible by specifying the field's datatype as being an identity, which can be done using SQLDataType.INTEGER.identity(true).
So for example, if you had a table with an auto-generating integer id and a string name, you would call:
int id = DSL.using(connection, MYSQL_5_7)
.insertInto(
table("myTable"),
field("name", String.class))
.values("John Smith")
.returning(field("id", SQLDataType.INTEGER.identity(true)))
.fetchAny(field("id", Integer.class))
So for your example, you would do
Record recordKey = create.insertInto(table("modulerecords"),
field("id"),
field("module_id"),
field("created_date"),
field("created_by"),
field("state"),
field("tag_id"),
field("start_time",Timestamp.class),
field("kill_time", Timestamp.class),
field("feed_guid")
)
.values(null, moduleId, currentTimestamp(),
userId, state, tagId,
new Timestamp(startTime),
new Timestamp(killTime), feedGuid)
.returning(field("id", SQLDataType.INTEGER.identity(true)))
.fetchOne();
See this Github comment for more background.
It is highly recommended you use the code generator to provide all the meta information to the DSL API. You can, of course, not use the code generator and still use the internal APIs that the code generator would otherwise use. Instead of creaating your table and field references using the plain SQL API, you'd have to create a TableImpl subclass and override / implement all the relevant methods.
Or, you just use the code generator.

How to build a spring controller with datas from two tables

The problem is as following: I have to make a spring controller with a parameter ("/getDocumentInfo?uniqueDocNo=100)", but I can't get the all the datas because I can't make a proper join between them.
First table, Document, contains datas about a document and the table Email contains data about who was sent the document and what was in the email.
The first table contains the parameter uniqueDocNo and another variable that I do need, but the second table contains uniqueDocNo only as a part of a concatenated field. I tried to make some mappings myself but I'm not sure I understood how I can get all my datas and put them in the controller only with one parameter(uniqueDocNo) or even if it is possible.
Tables: Document(uniqueDocNo, seenYN, docName, crDate),
Email(emailNo, emailDate, emailTo, emailSubject, internNo).
PK are with bold and in italic is the field that is concatenated. For example: uniqueDocNo = 100, internNo = 100_other_numbers_i_dont_need.
I expect to have a mapper or something that can the datas from both tables for the uniqueDocNo, more precisely: uniqueDocNo, seenYN(from the first table) and all the datas from the second table according to the the uniqueDocNo.
Thanks in advance.

Proper way to insert record with unique attribute

I am using spring, hibernate and postgreSQL.
Let's say I have a table looking like this:
CREATE TABLE test
(
id integer NOT NULL
name character(10)
CONSTRAINT test_unique UNIQUE (id)
)
So always when I am inserting record the attribute id should be unique
I would like to know what is better way to insert new record (in my spring java app):
1) Check if record with given id exists and if it doesn't insert record, something like this:
if(testDao.find(id) == null) {
Test test = new Test(Integer id, String name);
testeDao.create(test);
}
2) Call straight create method and wait if it will throw DataAccessException...
Test test = new Test(Integer id, String name);
try{
testeDao.create(test);
}
catch(DataAccessException e){
System.out.println("Error inserting record");
}
I consider the 1st way appropriate but it means more processing for DB. What is your opinion?
Thank you in advance for any advice.
Option (2) is subject to a race condition, where a concurrent session could create the record between checking for it and inserting it. This window is longer than you might expect because the record might be already inserted by another transaction, but not yet committed.
Option (1) is better, but will result in a lot of noise in the PostgreSQL error logs.
The best way is to use PostgreSQL 9.5's INSERT ... ON CONFLICT ... support to do a reliable, race-condition-free insert-if-not-exists operation.
On older versions you can use a loop in plpgsql.
Both those options require use of native queries, of course.
Depends on the source of your ID. If you generate it yourself you can assert uniqueness and rely on catching an exception, e.g. http://docs.oracle.com/javase/1.5.0/docs/api/java/util/UUID.html
Another way would be to let Postgres generate the ID using the SERIAL data type
http://www.postgresql.org/docs/8.1/interactive/datatype.html#DATATYPE-SERIAL
If you have to take over from an untrusted source, do the prior check.

Overwrite Datastore entities in Google App Engine- Java

I have an application in which I want to overwrite an individual entity. This is how I originally create entity logs:
Entity log = new Entity("Log", "Logkey");
String property1 = req.getParameter("property1");
String property2 = req.getParameter("property2");
log.setProperty("property1", property1);
log.setProperty("property2", property2);
datastore.put(log);
Here is how entity logs are retrieved to be overwritten:
Query query = new Query("Log", "Logkey")
.setFilter(timeStampFilter);
List<Entity> logs = datastore.prepare(query).asList(FetchOptions.Builder.withLimit(1));
request.setAttribute("logs", logs);
and sent to a jsp form page as value="${log.properties.property1}" where they should be overwritten. This entry is then sent to a second servlet with the POST method and requested as parameters as in the earlier code but saved as a new entity with the same kind:
Entity edit_log = new Entity("Log", "Logkey");
String property1 = req.getParameter("property1");
String property2 = req.getParameter("property2");
edit_log.setProperty("property1", property1);
For rewriting and existing entity, after retreiving a specific log by timestamp, you can get the key of this log using getKey() method and then create an entity with this key and the new details. Now when you put this new entity to the datastore it will replace the earlier one with the same key
With the code you've written, you only have a single Log entity in your datastore with the key "Logkey" that you are constantly overwriting.
If you're using some other code to retrieve entities and rewrite them, then you'll need to show that other code. Otherwise, this question is poorly written, because the code given is already describing what you want to do (always overwrite the same entity).
If you have code elsewhere creating/saving entities, it's best to show that too.
Edit: It looks like you end up creating a nested entity with the data from the old entity in a new entity with the same key. It's far easier just to reuse the entity you received from the query.
log = logs.get(0)
log.setProperty("property1", req.getParameter("property1");
log.setProperty("property2", req.getParameter("property2");
datastore.put(log);
Furthermore, since you actually know the key ("Logkey"), you don't need to issue a datastore query, you can just fetch the entity by key - which is good because you get around eventual-consistency behavior.
If your new entity has the same key as your original one, then when you store it it will override the old entity.

<Play!> Retrieving uniquely generated ID from <JPABase> in JPA

Folks,
I am using Play 1.2.5. The database is Oracle 10g and I am using an existing table for my application.
I am generating a unique key like this:
#GeneratedValue(strategy=GenerationType.SEQUENCE)
public int transactionId;
When I use the below code, the transactionId is generated and saved successfully ib the database:
transactionDetails.save();
But I am not able to get the uniquely generated transactionId once the save operation performs successfully. The save method returns a type <JPABase>. Then how can I retrieve the transactionId after a successful save operation from the <JPABase> ?
Note: I don't want to make another DB hit for fetching the transactionId because I believe that there might be some way to retrieve it for a successful save operation.
Please let me know about this.
Thanks,
You should be able to write
TransactionDetails savedDetails = transactionDetails.save();
save() method actually is not returning JPABase, it is declared as so you will get the saved entity

Categories

Resources