one to many mapping - java

I have a problem of mapping some scenario into data base.Problem is something like this.
There are two entities called Employee(empID,empName) and Task(taskID,taskName).
A employee can have ZERO-OR-MORE tasks.
A task can have ZERO-OR-ONE employee.
What will be the table structure that should I follow..
I'm going to implement this scenario using spring MVC and hibernate in java.How can I fixed this issue..
Any idea?
Thanks in advance!

Looks like you may need another table called EMPLOYEE_TASKS:
ID - sequence, PK.
EMPLOYEE_ID, numeric, not null, FK to ID in the EMPLOYEE table.
TASK_ID - numeric, unique key, not null, FK to ID in the TASKS table.
Your 0-or-1 employees/task requirement is handled by the UK on TASK.TASK_ID.
Your 0-to-many tasks per employee is handled by the EMPLOYEE_ID+TASK_ID pair. Because TASK_ID is unique, this pair doesn't need to be. In the real world, I'd probably make this an index.
Now I'd use hibernate's reverse engineering tools to create annotated models. We put the primary key sequence generator specifications in the reveng.xml file.
If every task had exactly one employee, this table would not have been needed. We could add an EMPLOYEE_ID to the TASK table but two tasks would likely have no EMPLOYEE. This means we couldn't make that column a UK. So we'd have a hard time using the database to enforce the zero-or-one constraint.

Related

How to represent table with nulls in Spring Data JPA?

What should I do to represent this table in Spring Data Java Persistence Application Programming Interface (JPA)?
The table is specific because it has no primary key and every column in the table can have nulls, and it is read only.
In entity class I can not simply annotate a single column with #id because there is no column with unique values.
I can, of course, create composite virtual primary key in entity class by annotating every column with #id, and that works, but only if there are no nulls in the row. So if I select row(s) with all columns not null then this works. But if one or more columns contains null, Spring is not able to extract that row from table, and instead returns simply null for entire row rather than returning an entity object with only the appropriate field null.
Please do not say "just add id column to the table" because table is read only for us. My company was negotiating for more then a month just to get the read rights to the table! I can not simply add id field in the table.
What else can I do in this case? Other than manually executing a query and extracting the result. Can I somehow fake the id field to make Spring happy? id field is not important for our application, we will never filter the table by id, so it can be whatever makes Spring happy as far as I am concerned.
I don't think there is a way to do that.
Just get a NamedParameterJdbcTemplate injected and query away.
A central premise of JPA is that you can load data from a bunch of tables, edit the resulting object structure and JPA will take note and mirror the changes to the data in the database.
If you don't have anything to use as an id you wouldn't know which row to update. So this whole approach kinda fails to work.
You can use #EmeddedId with an ID you create. Set the ID field either #Transient or static so it won't affect persistence.
In the below example I use the UUID static method .randomUUID() to generate the ID.
So put this into your #Entity and you will get every row regardless of nulls. Inserts will work just fine too (depending on how you disambiguate your rows).
#EmbeddedId
static UUID uuid = UUID.randomUUID();

How to save additional attributes when using envers

I'm using Hibernate Envers for my revision history.
This is my table setup:
CREATE TABLE EPIC (
epicid SERIAL NOT NULL,
accountid BIGINT NOT NULL,
description TEXT NOT NULL UNIQUE,
epicowner TEXT NOT NULL,
PRIMARY KEY(epicid)
);
CREATE TABLE EPIC_AUD(
epicid BIGINT NOT NULL ,
REV BIGINT NOT NULL,
accountid BIGINT,
description TEXT,
epicowner TEXT,
REVTYPE BIGINT,
PRIMARY KEY(epicid,REV)
);
Currently when i make changes it only saves the composite primary key values and the revision type. Since i also want to log the user who deleted some entity, i want to save that value too. This is the code i'm using for deleting the entity.
#Override
public boolean deleteItem(Epic epicFromFrontend) {
transactionBegin();
Epic epicToRemove = getEntityManager().find(Epic.class, epicFromFrontend.getEpicid());
epicToRemove.setAccountid(epicFromFrontend.getAccountid());
getEntityManager().remove(epicToRemove);
return transactionEnd();
}
Actually i have 2 questions:
How to save the accountid too
Or is it maybe smarter and better to save ALL data. so i have no empty fields in my EPIC_AUD table after a delete.
It is a common practice to capture various additional pieces of information that is audit-specific during the insert, update, or delete of your domain entities.
A simple yet intrusive way is to store that state in the same structure as the entity, as suggested by Marcin H. While this approach may work, there are several problems with this approach.
Mixing Concerns
The problem here is that historical related information is now being stored right along side the domain specific data. Much like security, auditing is a cross cutting concern and thus should be treated in the same way when it comes to data structures. Additionally, as multiple audited rows in your schema are manipulated, you often represent the same user, timestamp, etc across multiple tables which lead to unnecessary schema and table bloat.
Unnecessary fields / operations for data removal
When you store fields of this calibur on the entity itself, it introduces an interesting set of requirements as a part of the entity removal process. If you want Envers to track that removal user then you either have to perform an entity update with that user prior to removal or introduce an additional column to track whether a row is soft deleted, as suggested by Marcin H.This approach means that a table will always grow indefinitely, even when delete has been removed. It could have negative impacts to long-term query performance and other various concerns. Ideally, if data is no longer relevant except from a historical purpose and no FK relationships continue to exist that must be maintained, its far better to remove the row from the non-audit table.
Rather than the above, I suggest using this strategy I posted here that describes how to leverage a custom RevisionEntity data structure with Envers, allowing you to track multiple columns of data that is pertinent to the current transaction operation.
This approach has the following added benefits:
No Envers (audit) specific code littered across your DAO methods. Your DAO methods continue to focus on the domain specific operation only, as it should be.
In situations where multiple entities are manipulated during a single transaction, you now only capture the various audit-attributes once per transaction (aka once per revision). This means if the user adds, removed, and updates various rows, they'll all be tagged once.
You now can easily track the person who performed the row deletion because the audit attributes are kept on the RevisionEntity, which will be generated for the deletion. No special operations or fields are needed to handle this case. Furthermore, you can enable storing the entity snapshot at deletion and then have access to (1) who deleted the row and (2) what the row looked like prior to the removal too.
You can add attribue record_active boolean to your table epic, as well as to table epic_aud of course.
When record_active is false it means record has been "deleted".
And never remove any record physically - it's good practice in fact :)

JPA Composite Key for one Table and a Primary Key for another Table - Possible?

Is it possible to have both a composite key and a primary key in the same Domain Model (Entity Class) so that some tables (queries) are joined using the composite key and other tables (queries) are joined using the primary key?
I'm dealing with legacy applications and I have limited access to changing the underlying database. Some of our queries are expecting a single row result but are getting many rows because of flaws in our database design. We can fix this problem by introducing a composite key to one of our Domain Models but doing so will affect many (many) other components that rely on the original primary key.
From my understand of JPA and the reading I've done so far on this matter I do not think this is possible but I thought it would be worth a shot to reach out to others who may have had a similar problem.
The table has only one primary key, so you have no options to choose which primary key to use. Also, i can't understand why you going to have differences between database original model and JPA. Actually, getting single row instead of many rows is where clause's task.
You said some of your queries fails after adding composite pk, so may be you just made your composite pk in wrong way?
Anyway, here is nice example or implementation composite pk, may be it will help you:
Mapping ManyToMany with composite Primary key and Annotation:
Maybe you should give a different look at your problem.
If your queries are returning multiple and different rows, then you should be able to resolve this using a more specific WHERE clause;
If your queries are returning multiple and equal rows, you should try the DISTINCT clause inside your query, example:
SELECT DISTINCT e FROM br.com.stackoverflow.Entity e

Ensure single vote per user, per page, in a database

I'm working on a small feature in a Java web application that very closely resembles the vote up/down feature here at stackoverflow.com. I have a database that looks like the following:
VOTE TABLE
id (bigint): surrogate primary key
question_id (bigint):: the question the vote is for
vote_type (int): whether the vote is up or down
user_id (varchar): the username of the person who the vote belongs to
I want to ensure that there is only one vote in the DB per person, per question. What is the best way to enforce this? How would enforce it with the database schema I have described above?
I am currently having problems where a user fires off two vote-up requests and the database then contains 2 'up votes' for that user, when they should only have one vote.
You can enforce is via a Primary Key or Unique index - both concepts are pretty univeresal within databases. Place it on the two columns together, Question_id and User_id. That would only permit 1 entry per user, per question. This will be enforced by the database, even if your application codes lets them vote twice, the database will throw an error on the second record attempting to be inserted. (Even if you are using transactions etc, the database will enforce it correctly.)
If you want to enforce it via database schema, the correct way would be to make (question_id, user_id) an unique key.
Only do the INSERT when user_id and question_id NOT EXISTS e.g.
INSERT INTO TABLE
-- ALL YOUR FIELDS HERE
WHERE NOT EXISTS (
SELECT * FROM TABLE WHERE
QUESTION_ID = ? AND USER_ID = ?
)
However you could make user_id and question_id the Primary Key (or another Unique key) so only one record is physically allowed.

ejb3: mapping many-to-many relationship jointable with a simple primary key

often in books, i see that when a many-to-many relationship is translated to a DB schema, the JoinTable gets a compound key consisting of the primary keys of the tables involved in many-to-many relationship.
I try to avoid compound keys completely. So i usually create a surrogate key even for the JoinTable and allow the database to fill it up by trigger or whatever feature a database has for incrementing primary keys. It just seems like a much simpler approach.
the only issue i can think is that, there are chances of duplication of foreign key pair in the JoinTable. But this can be avoided by a simple query before a row is inserted in the JoinTable.
Since books always use the compound keys approach, i wanted to know if, there are any negative effects if i use simple one column surrogate keys for the JoinTable?
In my opinion, using a single primary key is a bad idea.
First, as you said, a single primary key won't ensure unicity in the database. Sure, you can check this at runtime using a simple query, but this is costly, and if you forget just one time to do your check query, you can put your database in an inconsistent state.
Also, I think that using an additional column for the primary key is, in this case, not necessary. You don't need to identify relationships by a unique primary key, since the relationship is already defined by two unique keys: the primary keys of your two tables. In this case, you'll have unnecessary data, that will add complexity to your data model, and that you'll probably never use.
I try to avoid compound keys completely.
Huh? Why? I mean, why totally avoiding them? What's the reason behind this?
So i usually create a surrogate key even for the JoinTable and allow the database to fill it up by trigger or whatever feature a database has for incrementing primary keys. It just seems like a much simpler approach.
No offense but we don't have the same definition of simplicity then. I really don't see where it is simpler.
The only issue i can think is that, there are chances of duplication of foreign key pair in the JoinTable. But this can be avoided by a simple query before a row is inserted in the JoinTable.
First of all, don't use a SELECT to check uniqueness (you can have a race condition, a SELECT without locking the whole table won't guarantee anything), use a UNIQUE constraint, that's what UNIQUE is for.
And lets imagine one second that a SELECT would have been possible, do you really find that simpler? In general, people try to avoid hitting the database if possible. They also avoid having to do extra work.
Since books always use the compound keys approach, i wanted to know if, there are any negative effects if i use simple one column surrogate keys for the JoinTable?
So you mean something like this:
A A_B B
------- ------------------ --------
ID (PK) ID (PK), ID (PK)
A_ID (FK),
B_ID (FK),
UNIQUE(A_ID, B_ID)
Sure, you could do that (and you could even map it with JPA if you use some kind of trigger or identity column for the ID). But I don't see the point:
The above design is just not the standard way to map a (m:n) relation, it's not what people are used to find.
A_B is not really an Entity by itself (which is what the model somehow suggests, see #1).
The couple (A_ID, B_ID) is a natural candidate for the key, why not using it (and wasting space)?
The above design is not simpler, it does introduce more complexity.
To sum up, I don't see any advantage.

Categories

Resources