Here are the tables that I'm working with. There is a User table that has some predefined columns ('name' in the example below) and an Extra Attributes table that used for making schema extension possible. The Extra Attributes table stores values for any new extended attributes as key-value pairs('title' and 'mobile' are the extra attributes in the example below) and the 'user' column is used for joining with the main User table. This arrangement generally works well for most operations, but I am not able to think of a way to sort on any of the extra attributes for the Users.
User Table:
---------------
id name
==============
1 jon
2 harry
Extra attributes table:
--------------------------------
user attr_key attr_value
================================
1 title engineer
1 mobile 111-2222-4444
2 title manager
2 mobile 111-0000-5555
Result of joining the two tables above(few columns intentionally skipped):
--------------------------------------------
id name attr_key attr_value
============================================
1 jon title engineer
1 jon mobile 111-2222-4444
2 harry title manager
2 harry mobile 111-0000-5555
I'm using hibernate for ORM. Here are the entity classes:
#Entity
public class User {
private Long id;
private String name;
private Set<ExtraAttributes> extraAttributes;
public String getName() {}
#OneToMany(mappedBy="user",fetch=FetchType.EAGER)
public Set<ExtraAttributes> getExtraAttributes() {}
...
}
#Entity
public class ExtraAttribute {
private Long id;
private String attrKey;
private String attrValue;
private User user;
...
#ManyToOne(optional = false)
public User getUser() {}
...
}
I want to be able to sort the results by attr_value corresponding to a specific attr_key, say 'title'. The problem is that if I order the results by attr_value then all the attr_values will be considered, while I want to order by only the attr_values that correspond to a specific attr_key - 'title'. I thought of ordering both by attr_key as well as attr_value but this doesn't seem to solve the problem either.
Related
I have two tables, one named "Category" and the other "Rule" that are related logically with One to One relationship using a field (code) different than the Primary Key (PK) of table and not phisically managed with a Foreign Key (FK):
CATEGORY
ID (PK) NUMBER
COD_RULE VARCHAR
NAME VARCHAR
.....
RULE
ID (PK) NUMBER
CODE VARCHAR
TYPE VARCHAR
.....
I haven't on Rule table FK to category ID but only unique constraint (the relation is 1 to 1)
Implemented in this way in JPA
public Category implement Serializable {
#Id
#Column (name="ID")
private Long id;
#NotNull
#OneToOne(cascade=CascadeType.ALL)
#JoinColumn(name="CODE_RULE" referencedColumnName="CODE", nullable=false)
private Rule;
#Column (name="NAME")
private String name;
//Getter and Setter methods
.......
}
public Rule implement Serializable {
#Id
#Column (name="ID")
private Long id;
#NotNull
#Column (name="CODE")
private String code;
#Column (name="TYPE")
private String type;
//Getter and Setter methods
.......
}
I need to:
When retrieve Categories obtain also all informations of associated Rule
SELECT c.*, r.type FROM Category c LEFT OUTER JOIN Rule r WHERE c.CODE_RULE = r.CODE
When edit Category maintain aligned CODE_RULE with CODE, so If I change CODE_RULE I would yo change automatically the CODE on Rule
UPDATE Category SET COD_RULE='5A', NAME='Test' WHERE ID=1
UPDATE Rule SET CODE='5A' WHERE CODE='AB'
I see on the specification that:
There are three cases for one-to-one associations: either the
associated entities share the same primary keys values, a foreign key
is held by one of the entities (note that this FK column in the
database should be constrained unique to simulate one-to-one
multiplicity), or a association table is used to store the link
between the 2 entities (a unique constraint has to be defined on each
fk to ensure the one to one multiplicity).
But with this implementation satisfy point 1. But not the point 2.
Suppose that I've already created Category (on ID = 1) and associated rule, when I edit category (having CODE_RULE = CODE = "AB") and change the code to "5A":
#PersistentContext
private EntityManager em;
.......
Category cat = em.find(Category.class, 1L);
cat.setName("Test");
cat.getRule().setCode("5A");
em.merge(cat);
I see that the code has been updated on Rule but not in Category:
BEFORE EDIT
Category (ID, COD_RULE, NAME) --> (1, AB, First Category)
Rule (ID, CODE, TYPE) --> (10, AB, C)
AFTER EDIT
Category (ID, COD_RULE, NAME)--> (1, AB, Test)
Rule (ID, CODE, TYPE) --> (10, 5A, C)
How can I do this work in JPA?
Is this type of operation supported in the JPA specification?
Is there an alternative (i.e. I have to merge before Rule and then Category)?
From your datamodel, it looks more like a Many To One relationship between Category and Rule, given in your data model only restrict each Category can refer to [0..1] Rule, but not restricting how many Categories that a Rule can be referred by.
Based on your comment, it seems that you can change the data model. Normally if it is a ~ToOne relationship, you should have the referring side referring as FK, which looks like this:
(Tables)
CATEGORY (
CATEGORY_ID NUMBER PK,
CATEGORY_CODE VARCHAR, // Unqiue
RULE_ID NUMBER FK to RULE,
... (Don't refer by RULE_CODE!!)
)
RULE (
RULE_ID NUMBER PK,
RULE_CODE VARCHAR, // unique, can be updated
...
)
Entity should look like
class Category {
#Id #Column(name="CATEGORY_ID)
Long id;
#ManyToOne // or #OneToOne if you really insist
#JoinColumn(name="RULE_ID)
Rule rule;
)
(class Rule is straight-forward, I will skip)
The HQL you mentioned should be
// When retrieving Category together with Rule
from Category c join fetch c.rule
for Point 2, as you mentioned in comment, you are trying to align Rule's code with Category's code, when Category's code is updated. This should be implemented as:
class Category {
//.....
public void setCode(String code) {
this.code = code;
this.rule.setCode(code);
}
//....
)
Base on personal experience, when using JPA, life will be much easier to drive data model base on domain model design. It should save a lot of problem caused by "data-model that looks tolerable".
I'm having trouble using hibernate to persist a simple java object containing just a list of phrases in the form of strings.
To store this in a MySql database I have two tables:
phrase_list - columns:
group_id, phrase_id, list_position (which together make up the primary key; also there is a foreign key constraint on phrase_id from the phrase table)
phrase - columns: phrase_id, phrase (phrase is a varchar with a unique index)
I would like to simply be able to annotate the object containing the list of phrases in order to persist it, but nothing I've tried has worked, I've tried examples and variations of using #ElementCollection and #OneToMany with another Entity representing the phrase, but no matter what I try I can't seem to get this to work.
For example a phrase list: {"a","b","b"} would be stored as:
**(phrase table)** **(phrase_list table)**
phrase_id phrase group_id phrase_id list_position
1 'a' 1 1 0
2 'b' 1 2 1
1 2 2
Here is the attempt to what I thought would work; I added an extra id field because I could see no way to use the foreign key as part of the id, and annotating the list with #Id didn't work.
#Entity #Table(name = "phrase_list")
public class PhraseList {
#ElementCollection
#CollectionTable(
name="phrase",
joinColumns=#JoinColumn(name="phrase_id")
)
#OrderColumn(name="list_position")
#Column(name="phrase")
private List<String> phrases;
#Id #GeneratedValue
#Column(name = "list_id")
private Long id;
#Column(name = "goup_id")
private Long groupId;
public void setResults(List<String> results){
this.results = results;
}
public void setGroupId(Integer groupId) {
this.groupId = groupId;
}
}
I get this exception:
org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
ERROR: Cannot add or update a child row: a foreign key constraint fails (test_db.phrase_list, CONSTRAINTfk_phrase_list_phrase_idFOREIGN KEY (phrase_id) REFERENCESphrase(phrase_id`) ON DELETE NO ACTION ON UPDATE )
Is there any way to get this to work simply by annotating the plain Java object? If not what is the best way to achieve this?
If I can't get it to work with annotation I would probably write custom queries and/or specialized methods for persisting the object. I.e., a method that is coupled to that particular class in knowing how to persist its objects, which I hoped to avoid.
I am wondering if there is any way to retrieve a record and specific number of its members of collection.
I have a class called MyGroup which keeps a list of Students, each student can be in one group at a time. I need to retrieve list of available students of each group. If I retrieve all the students of each group and find available ones it needs a big amount of memory to run a loop through the collection and check the available field of each student.
On the other hand, (Bidirectional) if I execute a select clause on students to retrieve those students that are available, in this way I am retrieving the group class record as well (since it is a member of student). So for each of students I am retrieving its fields + group's fields.
Sample data
Group 1
Name available
Jack true
Luke false
Nou true
...
Group 2
Name available
Mike false
George false
Alex true
...
Expected Result
Name Available Group GroupName
Jack true 1 Wolfs
Nou true 1 Wolfs
Alex true 2 Tigers
Classes
#Entity
public class Student {
#Id
#GeneratedValue
private long id;
private String name;
private boolean available;
#OneToOne
private MyGroup group;
getters and setters
}
#Entity
public class MyGroup {
#Id
#GeneratedValue
private long id;
private String name;
#OneToMany
private List<Student> student = new ArrayList();
getters and setters
}
In the hibernate by default lazy loading is true so if you are executing a select clause on the students table and fetching students so by default with one student object u will get the group id as the foreign key and i think not all the records of the associated group object will fetch atonce .If u want to fetch the list of students associated with the group object later u can do that but due to the lazy loading list of students associated with a group object will not fetch atonce .I think this is your major problem.You do not want to fetch the list of students associated with a group atonce.I think your current student table structure will be like this .
id name group_id
1 jack 1
2 joe 2
3 Mack 1
if you can add one more field boolean available then your query can be more specific like the student which belong to a group id and avialble true.
Boolean available
now your student table structure will be like this.
id name group_id available
1 jack 1 true
2 Joe 2 true
3 Mack 1 false
so now u can query specific set of student based on available boolean field
I have a task to design an online reservation system.
Where a user can enter zip code/ no of people/time of reservation and get a list of restaurants. Assumption (User and restaurant are always in the same city)
Each restaurant can have multiple tables with different number of seats. So, 2 tables that seat 4 people and 4 tables that seat 4 people.
I'm having trouble coming up with the right data structures to use.
My classes are as follows
Restaurant : Contains timeofopening, timeOfClosing, totalNoOfSeatsAvailable
Not sure how i will store table information within the restaurant. It doesn't make sense to have a separate class for the table. All the info i need is howManytables are free and what are their sizes.
Reservation: This maintains the actual reservation and allows to cancel reservation
ReservationSystem :
contains the interface to `List checkAvailability(long time, int people)'
How will this return this list? I initially thought of using a priorityQueue to maintain a queue with max no of seats available. But then i will go through that list to see if the time is correct to even make the reservation and then once a reservation is made,update this queue. One problem is the queue does all duplicates.
My specific questions are:
How do i store the table information within each restaurant.
What is the best way to maintain this list of restaurants so i can give return a list without having to sort this information everytime.
EDIT:
For the question on how to store the table information. My specific concern is
that storing a table class would mean that i'm creating un necessary objects. Here's my reasoning. 5 tables that seat 2 people each with have the exact same objects - i mean there isn't any meaningful information that will be differnet among them. I just need to numbers. no of seats/table.(If i have a table of 4 but 3 peole, I will consider this table taken)
I thought of creating 3 arrays. Lets say table represent 1,2 etc so int[] differentSeatingOnTable; its indexes are tables and values are seats allowed. Next an array of tables with totalNoOfThosetable where indexs are tables and values are total number of such table. Similary for free tables freeTables where index are table and how many of such free table are left.
1. ) If you just store the amount of seats in a restaurant, you're shooting yourself in the foot. Suppose I need to make a reservation for 16 people, and they all must be on the same table (yes, I need a pretty long table). Your system could take my guests to someplace where they'd have to sit in 8 tables for two people each.
You do need a table class. Then your restaurants need to have collections of tables. If you want to know how many seats you have in a restaurant, you just have to iterate through its table collection and count the seats. And if you want to know if you can sit a family in a single table in a restaurant, you just have to check whether it has any table with that amount of seats.
EDIT: there is a more minimalistic way to store seats per restaurant. Use a dictionary, hash table or any other structure that holds keys and associated values. So have the key represent a type of table. The key may be an integer saying how many people the table sits. The value is the amount of tables of that type present in the restaurant. I think this is way better than my original suggestion.
So, for example, a restaurant with such a hash table:
Key | Value
4 | 5
2 | 8
16 | 1
Has five tables with 4 seats each, 8 tables with 2 seats each, and a single long table that sits 16 people.
(Also using a table to store tables is so meta).
2. ) Your reasoning is right for the reservations. If it is doing duplicates, you should post a more especific question showing how you're doing it so we can try and help you locate the bug.
Relational databases make both these requirements easy.
You'll have two tables: RESTAURANT and SITTING (TABLE is a reserved word in SQL) with a one-to-many relationship between them.
A RESTAURANT will have a name, so you can ORDER BY name.
package model;
class Table {
private int id;
private int numSeats;
public Table(int id, int numSeats) {
this.id = id;
this.numSeats = numSeats;
}
public int getId() { return this.id; }
public int getNumSeats() { return this.getNumSeats; }
}
class Restaurant implements Comparable {
private String name;
private List<Table> tables;
public Restaurant(String name) {
this.name = name;
this.tables = new ArrayList<Table>();
}
public void addTable(Table t) { this.tables.add(t); }
public void removeTable(int id) {
for (Table t : this.tables) {
if (t.getId() == id) {
this.tables.remove(t);
break;
}
}
}
public int getCapacity() {
int capacity = 0;
for (Table t : this.tables) {
capacity += t.getNumSeats();
}
return capacity;
}
public int compareTo(Restaurant r) {
return this.name.compareTo(r.name);
}
}
1) well..i think it makes more sense if you created the table class.its easier than trying to cramp it in the restaurant class.and you would find it easier too
2)maintain a primary key field,maybe a composite key,marking out the uniques,this could keep out duplicates
Reccomendations:
Res_Table class
Restaurant class
primary key fields with ORDERING
I'm trying to follow the JPA tutorial and using ElementCollection to record employee phone numbers:
PHONE (table)
OWNER_ID TYPE NUMBER
1 home 792-0001
1 work 494-1234
2 work 892-0005
Short version
What I need is a class like this:
#Entity
#Table(name="Phones")
public class PhoneId {
#Id
#Column(name="owner_id")
long owner_id;
#Embedded
List<Phone> phones;
}
that stores each person's phone numbers in a collection.
Long version
I follow the tutorial code:
#Entity
#Table(name="Phones")
public class PhoneId {
#Id
#Column(name="owner_id")
long owner_id;
#ElementCollection
#CollectionTable(
name="Phones",
joinColumns=#JoinColumn(name="owner_id")
)
List<Phone> phones = new ArrayList<Phone>();
}
#Embeddable
class Phone {
#Column(name="type")
String type = "";
#Column(name="number")
String number = "";
public Phone () {}
public Phone (String type, String number)
{ this.type = type; this.number = number; }
}
with a slight difference that I only keep one table. I tried to use the following code to add records to this table:
public static void main (String[] args) {
EntityManagerFactory entityFactory =
Persistence.createEntityManagerFactory("Tutorial");
EntityManager entityManager = entityFactory.createEntityManager();
// Create new entity
entityManager.getTransaction().begin();
Phone ph = new Phone("home", "001-010-0100");
PhoneId phid = new PhoneId();
phid.phones.add(ph);
entityManager.persist(phid);
entityManager.getTransaction().commit();
entityManager.close();
}
but it keeps throwing exceptions
Internal Exception: org.postgresql.util.PSQLException: ERROR: null
value in column "type" violates not-null constraint Detail: Failing
row contains (0, null, null). Error Code: 0 Call: INSERT INTO Phones
(owner_id) VALUES (?) bind => [1 parameter bound] Query:
InsertObjectQuery(tutorial.Phone1#162e295)
What did I do wrong?
Sadly, i think the slight difference that you only keep one table is the problem here.
Look at the declaration of the PhoneId class (which i would suggest is better called PhoneOwner or something like that):
#Entity
#Table(name="Phones")
public class PhoneId {
When you declare that a class is an entity mapped to a certain table, you are making a set of assertions, of which two are particularly important here. Firstly, that there is one row in the table for each instance of the entity, and vice versa. Secondly, that there is one column in the table for each scalar field of the entity, and vice versa. Both of these are at the heart of the idea of object-relational mapping.
However, in your schema, neither of these assertions hold. In the data you gave:
OWNER_ID TYPE NUMBER
1 home 792-0001
1 work 494-1234
2 work 892-0005
There are two rows corresponding to the entity with owner_id 1, violating the first assertion. There are columns TYPE and NUMBER which are not mapped to fields in the entity, violating the second assertion.
(To be clear, there is nothing wrong with your declaration of the Phone class or the phones field - just the PhoneId entity)
As a result, when your JPA provider tries to insert an instance of PhoneId into the database, it runs into trouble. Because there are no mappings for the TYPE and NUMBER columns in PhoneId, when it generates the SQL for the insert, it does not include values for them. This is why you get the error you see - the provider writes INSERT INTO Phones (owner_id) VALUES (?), which PostgreSQL treats as INSERT INTO Phones (owner_id, type, number) VALUES (?, null, null), which is rejected.
Even if you did manage to insert a row into this table, you would then run into trouble on retrieving an object from it. Say you asked for the instance of PhoneId with owner_id 1. The provider would write SQL amounting to select * from Phones where owner_id = 1, and it would expect that to find exactly one row, which it can map to an object. But it will find two rows!
The solution, i'm afraid, is to use two tables, one for PhoneId, and one for Phone. The table for PhoneId will be trivially simple, but it is necessary for the correct operation of the JPA machinery.
Assuming you rename PhoneId to PhoneOwner, the tables need to look like:
create table PhoneOwner (
owner_id integer primary key
)
create table Phone (
owner_id integer not null references PhoneOwner,
type varchar(255) not null,
number varchar(255) not null,
primary key (owner_id, number)
)
(I've made (owner_id, number) the primary key for Phone, on the assumption that one owner might have more than one number of a given type, but will never have one number recorded under two types. You might prefer (owner_id, type) if that better reflects your domain.)
The entities are then:
#Entity
#Table(name="PhoneOwner")
public class PhoneOwner {
#Id
#Column(name="owner_id")
long id;
#ElementCollection
#CollectionTable(name = "Phone", joinColumns = #JoinColumn(name = "owner_id"))
List<Phone> phones = new ArrayList<Phone>();
}
#Embeddable
class Phone {
#Column(name="type", nullable = false)
String type;
#Column(name="number", nullable = false)
String number;
}
Now, if you really don't want to introduce a table for the PhoneOwner, then you might be able to get out of it using a view. Like this:
create view PhoneOwner as select distinct owner_id from Phone;
As far as the JPA provider can tell, this is a table, and it will support the queries it needs to do to read data.
However, it won't support inserts. If you ever needed to add a phone for an owner who is not currently in the database, you would need to go round the back and insert a row directly into Phone. Not very nice.