I need to model a Customer and an Address for applications in django as well as in Play!.I believe that two Customers can have the same address.
So a Many to One relation between Customer and Address
class Customer extends play.db.jpa.Model{
#ManyToOne
public Address address;
..
}
In django ,does this python code below give similar mapping?
class Address(models.Model):
customer= models.ForeignKey(Customer)
What will be the tables created like?I am slightly confused here..
You almost got that right. The many-to-one relationship in Django is indeed represented by the models.ForeignKey.
To express relationship that two customers can have the same address you would define that relation in the Customer model (not in the Address model as you assumed).
class Customer(models.Model):
address = models.ForeignKey(Address)
Related
I'm hoping someone can help me figure out a problem I am having with hibernate.
I am working on a billing system where different types of entities can be invoiced. The entities implement an "Invoicable" interface.
In my invoice class I have this line
#ManyToOne(fetch = FetchType.EAGER)
private Invoiceable responsibleEntity;
The invoiceable interface looks like this
#MappedSuperclass
public interface Invoiceable
{
// Name to display as entity responsible
String getInvoiceOwnerName();
// Get email address to send invoice
String getInvoiceOwnerEmail();
}
I'm getting an exception when I run this
org.hibernate.AnnotationException: #OneToOne or #ManyToOne on models.Invoice.responsibleEntity references an unknown entity: interfaces.Invoiceable
I've tried googling it and reading some similar posts but I can't get anything to work. Does hibernate support this type of mapping?
Thanks
You have to use Inheritance in the Hibernate way to do this. Details can be found in the --> Hibernate Inheritance Doc
Additional information:
Hibernate is not able to wire types together where no database table is behind it. What does this mean for you. MappedSuperclasses do not have a table so there's nothing to wire together. So this is out of business. Most important keep in mind. When you request to read all parent objects. To which tables should he join? This is the reason why the inheritance system of hibernate comes in to play. You have to change the interface to a normal class. This should not be to much of a problem. Now choose an inheritance Strategy of your choice. Each of them have their pros and cons. Please read the doc to get an idea of which is best for your situation.
The following is an example of a the single table approach with an Invoice class.
#Entity
#Inheritance(strategy=InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(
name="invoiceType",
discriminatorType=DiscriminatorType.STRING
)
#DiscriminatorValue("Invoice")
public class Invoiceable { ... }
#Entity
#DiscriminatorValue("CustomInvoice")
public class CustomInvoice extends Invoiceable { ... }
I have a User entity. Each User can have one or more personal Addresses. According to the Hibernate documentation for mapping embeddable collections this is how it should be done:
#Entity
public class User {
[...]
public String getLastname() { ...}
#ElementCollection
#CollectionTable(name="Addresses", joinColumns=#JoinColumn(name="user_id"))
#AttributeOverrides({
#AttributeOverride(name="street1", column=#Column(name="fld_street"))
})
public Set<Address> getAddresses() { ... }
}
#Embeddable
public class Address {
public String getStreet1() {...}
[...]
}
Now if I want the User to have a collection for work addresses too, what should I do?
Here is what I thought:
Create 2 different collections for work addresses and personal addresses then map them into 2 different tables. ( Sounds like over complicating things as both addresses are exactly the same)
Store both addresses into the same table. (However, I don't know how will I differentiate between them)
Introduce a look up entity/value object and use it somehow to differentiate between personal and work addresses. (from the database point of view we will have a look up table for address types linked via a foreign key to the address table, but I don't know how that should be modeled in the domain itself using Hibernate)
Alternative approaches are very welcomed.
Try using hibernate single table inheritance mapping:
#Entity
#Inheritance(strategy= InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name="addresstype",
discriminatorType= DiscriminatorType.STRING)
public abstract class Address {
... common attributes here
}
#Entity
#DiscriminatorValue("home")
public class HomeAddress extends Address {
...
}
#Entity
#DiscriminatorValue("work")
public class WorkAddress extends Address {
...
}
And then create two collections, one for home addresses and the other for work addresses.
If there is code that is valid only for home addresses then we use the HomeAddress type, the same if there is code that is only valid for work addresses we use WorkAddress.
If there is code that is valid for both address types then we use the Address super type.
How to annotate my code to have a Person with 2 Addresses :
#Entity
public Person {
// ... other attributes for a person
#OneToOne
public Address homeAddress;
#OneToOne
public Address workAddress;
}
#Entity
public Address {
// ... other attributes for an address
#OneToOne
public Person person;
}
Can I use OneToOne ?
Should I have to use options on this annotations ?
Unfortunately this is not possible to achieve with #OneToOne. The reason:
the persistence provider will have one Person id for two entries the Address table. This is not sufficient to decide which relation a given Address belongs to.
The simplest solution would be to add a type field (an enum) to the Address entity and map the addresses with #OneToMany/#ManyToOne.
In order to get the home address, you would need to iterate over the addresses and check for type.
Alternatively, you could create extra types like HomeAddress and WorkAddress which would derive from the Address. You could then keep the #OneToOne relations, but would end up with two additional types.
IMO a cleaner entity relation mapping is not a sufficient reason for doing this, as you are inviting some issues. For example a HomeAddress can never be a WorkAddress.
EDIT: If both Address ids are stored in the Person table, you should be able to use the#OneToOne relation. To ensure deletion of attached Address entities and deletion of orphaned Address entities, you can use cascading and orphan removal:
#OneToOne(cascade=CascadeType.ALL, orphanRemoval=true)
Although it might look like this makes sure that there could be no orphaned Address records in the DB, it is not entirely true. Orphan removal works only when you remove the referenced entity inside a transaction while the entities are attached. Furthermore it does not work for bulk updates. A DELETE FROM Person WHERE ... query will happily delete the Persons and will not touch the connected Addresses.
OneToOne implies a table has a foreign key to another, but you haven't specified which, and are implying that it isn't a real 1:1 situation from address->person. Will employee have a workAddress_ID and homeAddress_id field? In which case, there are two different 1:1s. What isn't valid is your address->Employee 1:1 as there is no way for it to use both the workAddress_ID and homeAddress_id relationships. You could work around this by having address have 2 OneToOnes that are private, and then a public getPerson method used by the application that returns the one that isn't null. Setting the person would require looking at the passed in person object ot know which of the Address 1:1's to populate, but it wouldn't matter as much since they wouldn't control the relationship:
public Address {
// ... other attributes for an address
#OneToOne(mappedby="workAddress")
private Person workPerson;
#OneToOne(mappedby="homeAddress")
private Person homePerson;
public Person getPerson() {
return workPerson==null? homePerson:workPerson;
}
public void setPerson(Person p) {
workPerson=null;
homePerson=null;
if (p !=null) {
if (p.getHomeAddress()==this) {
homePerson=p;
} else {
workPerson=p;
}
}
}
}
I'm not 100% sure this is only a Hibernate issue as this might be a more abstract decision but I'll give it a try.
Since the problem description is a bit lengthy I'll first state that what I'd like to do is see if I can change the implementation to something which more resembles a Best practice implementation then this.
I have 3 entities, relevant to this issue: Workstation (ws), Employee and Organization-unit(org-unit).
An Employee can belong to one org-unit.
An Org-unit can hold many employees.
A Workstation is used to display data of an Org-unit(in general), Of an Org-unit and a specific employee in it and an employee which does not belong to an org-unit.
Currently, for various reasons which were out of my control, we do not use any associations between the entities in Hibernate or via DB-Constraints but we just use Columns which logically serve as Foreign-Keys.
We currently have an additional table which has 4 columns:Id,WSId,EmployeeId,OrgUnitId.
This allows a WS to refer to an orgunit (where employeeId is null),to an employee without an org-unit (orgunitId is null) or to an employee and org-unit (where none are null).
I'd like to be able to know:
1.Given a WS, which employees is it following and which org-units and how (i.e., alone, with an employee? which?)
2.Given an employee, which WS are monitoring it.
3.Given an org-unit, which WS are monitoring it and how (i.e., alone, with an employee? which?)
This issues relates to the Presentation layer as it dictates the view will be generated BUT it is a part of the domain model as a user, will use, an interface to manipulate these monitoring mappings and so these mappings are a part of the domain model.
I'm not sure if what I have is not the least evil among options, and I would greatly appreciate comments and suggestions.
EDIT From one of the answers I think it is not clear enough that a WS can display data for many such mappings at the same time, in a mixture of the above sorts (org-unit, employee etc.)
OK, I don't know how to implement this on the database side, but here is an Entity Model that should cover the relationship you are talking about.
Edit:
This is a new version in response to your comments. Now every WorkStation has n bindings each of which can have employee or orgunit or both (use DB constraints to ensure they don't have neither).
You can also access the bindings per orgunit and per employee, which should make the above queries much easier:
#Entity
public class OrgUnit{
#OneToMany(mappedBy="orgUnit")
private Set<Binding> bindings;
}
#Entity
public class Employee{
#OneToMany(mappedBy="employee")
private Set<Binding> bindings;
}
#Entity
public class Binding{
#ManyToOne(optional = true)
private Employee employee;
#ManyToOne(optional=true)
private OrgUnit orgUnit;
#ManyToOne(optional=false)
private WorkStation owner;
}
#Entity
public class WorkStation{
#OneToMany(mappedBy="owner")
private Set<Binding> bindings;
}
Sample Client code:
public Set<WorkStation> getWorkstationsPerEmployee(final Employee employee){
final Set<WorkStation> workStations = new HashSet<WorkStation>();
for(final Binding binding : employee.getBindings()){
WorkStation workStation = binding.getOwner();
if(workStation!=null)
workStations.add(workStation);
}
return workStations;
}
Sounds like all you really need is a nullable FK on Employee to OrgUnit, and two nullable FKs on WS to both Employee and OrgUnit. To see which WS are monitoring an employee, just get all the WS with matching emp_id columns. Same with the WS monitoring an OrgUnit, possibly with the additional stipulation of emp_id being null or not (depending on if you need to handle those situations separately). No idea where "patients" fits in, you didn't give any details about that.
I ran some DDL script to setup a complete country table in my database. The country table's primary key column contains the corresponding ISO code for every country.
In my JPA project I have a User entity having an embedded Address entity and this Address entity has a reference to a Country. The relationship between User and Address seems to be no problem to me, but the relationship between Address and Country. I tried to map it as a ManyToOne relationship, since many addresses can share a country.
Problem is: I annotated the iso member variable of the Country class with Id -> Now, JPA/Hibernate complains about not having set the id of the country manually. But in this case, the id is already given and set, since I imported the data once and the ISO code is unique and by db schema means declared as primary key. In this special case, there is no need for updates or inserts in the country table - the information should be read only!
Any idea what to do, so I can use my countries table without altering?
Your question is missing some details, so the following involves a lot of guessing :-)
Your Country class should look something like:
#Entity
#Immutable
#Table(name="countries")
public class Country {
#Id
private String isoCode;
// all other attributes, getters / setters, etc...
}
#Immutable is a Hibernate extension to JPA standard; you don't have to put it on entity but having it will result in slightly better performance. Keep in mind that it will really make the Country immutable - you won't be able to create / update / delete countries through your application. You may want to configure cache for your Country entity as well if it's used often enough.
Your Address would have the following mapping to country:
#ManyToOne
#JoinColumn(name="country_iso_code")
private Country country;
Note the absence of "cascade" attributes - you don't need any. The final important point here is you actually need to get or load the Country instance to set it on address:
Country country = (Country) session.load(Country.class, isoCode);
// OR
Country country = (Country) session.get(Country.class, isoCode);
address.setCountry(country);
...
session.saveOrUpdate(address);
The first line above will not hit the database; use it if you know that country with such an ISO code exists. Second form will hit the database (or cache, if configured) and return NULL if country with that code does not exist.