I would like to map an simple excel table to my javaEE application using hibernate. I'm really new to Databases and ORM so i would like to know if the following relations make sense and in how many Entities would make sense to split the Table.
This is the attributes contained in the Excel spreadsheet:
(Office Room Number|ComputerName|ComputerIP|Computer OS|UserFirstName|UserLastName)
Relations:
OfficeRoomNumber -- 1 : N -- Users
N users working in 1 Office?
OfficeRoomNumber -- 1 : N -- Computer
N Computers are in 1 Office ?
User -- 1:1 -- Computer
1 User got 1 Computer?
Thanks for any help and sorry for my horrible English.
Here are my 50c for modelling your domain. First, one can use an abstract base class for generic aspects, such as primary key generation:
#MappedSuperClass
public abstract class AbstractEntity {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "pk-sequence")
#SequenceGenerator(name = "pk-sequence", sequenceName = "ID_GEN", allocationSize = 1)
protected Long objectID = -1;
#Version
private int version;
public int getVersion() {
return version;
}
public long getObjectID() {
return objectID;
}
}
Note well, this can be enhanced to include other generic aspects, e.g. creation/modification date/timestamps.
Next, we introduce three domain classes/entities as follows:
#Entity
public class OfficeRoom extends AbstractEntity {
private String name;
private String roomNumer;
#ManyToMany // Maybe an employee is associated with 2 or more office places she/he might work at?
private Collection<Employee> staff;
#OneToMany(mappedBy="location")
private Collection<Computer> equipment;
// getters and setters
}
I added a comment as you can see above on the field staff. Potentially, one would like to associated two different office rooms to certain VIP staff, so you should consider this case in modelling your domain by using #ManyToMany here already.
Moving on with:
#Entity
public class Computer extends AbstractEntity {
private String name;
private String model;
private String vendor;
private String installedOS;
private String ipAddress;
#ManyToOne
private OfficeRoom location;
#OneToMany(mappedBy="machine") // Maybe a computer is associated with 2 or more employees?
private Collection<Employee> user;
// getters and setters
}
Again, consider my comment carefully. Finally,...
#Entity
public class Employee extends AbstractEntity {
private String firstName;
private String lastName;
// other staff related attributes here ...
#ManyToOne
private Computer machine;
// getters and setters
}
Note well: Use only annotations originating from the javax.persistence package, in your import statements to stay compliant with the JPA 2.x specification and remain JPA-provider neutral with your application.
Hope this helps.
Related
I have a user class which is a supper class and a student class a subclass of users. I don’t have an error in the code but I don't why it does not make tables in the database when I remove "extends user" it creates the table?
here is my code
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
#Data
public abstract class User {
#Id
#GeneratedValue(strategy= GenerationType.IDENTITY)
private Long id;
private String username;
private String email;
private String password;
#Enumerated(EnumType.STRING)
#Column(length = 20)
private Role name;
}
#Entity
#Table(name = "student")
#Data
public class Student extends User{
#Id
private Long id;
private LocalDate dob;
private String tell;
private String course;
}
In this link you can have an overview of the following approaches to inheritance:
MappedSuperclass - the parent classes, can't be entities
Single Table -The entities from different classes with a common ancestor are placed in a single table.
Joined Table - Each class has its table, and querying a subclass entity requires joining the tables.
Table per Class -All the properties of a class are in its table, so no join is required.
Regards
As part of the training project, I create a database of passenger rail traffic. A user registers, buys a train ticket. The train goes on a route with several stations.
Help, please, deal with relationships.
There are several entities: user, ticket, train, station, route.
I create each entity as a:
#Entity
#Table(name = "...")
public class ... implements Serializable { ... }
User:
id (primary key),
email,
password,
firstName,
lastName,
birthDate,
role (user/admin for example).
With this, I understand everything. Further questions arise. Ticket:
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column("TICKET_ID")
private int id;
// One user can have multiple tickets?
#ManyToOne
#JoinColumn(name = "USER_ID")
private User user;
#Column(name = "SALE_TIME")
private Date saleTime;
// One train can have multiple tickets?
#ManyToOne
#JoinColumn(name = "TRAIN_ID")
private Train train;
#Column(name = "CARRIAGE")
private int carriage;
#Column(name = "PLACE")
private int place;
Is everything right here? Next...
#Entity
#Table(name = "TRAINS")
public class Train implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "TRAIN_ID")
private int id;
#Column(name = "TRAIN_NUMBER")
private int number;
#Column(name = "SEATS")
private int seats;
// on the way for example
#Column(name = "STATUS")
private String status;
How to set a train a fixed number of seats and how to reduce them when buying a ticket?
With the Station is not difficult: id, name, status.
And finally, Route:
#Entity
#Table(name = "ROUTE_POINT")
public class RoutePoint implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ROUTE_ID")
private int id;
// ?????????
#ManyToOne
#JoinColumn(name = "TRAIN_NUMBER")
private Train train;
// ?????????
#ManyToOne
#JoinColumn(name = "STATION_NAME")
private Station station;
#Column(name = "DATE_ARRIVAL")
private Date dateArrival;
#Column(name = "DATE_DEPARTURE")
private Date dateDeparture;
Please help me deal with annotations and relationships, and most importantly, understand this. Google is already purple, the best understanding comes through practice. Thank.
First of all - don't use primitive types for iDs. Use Integer or better Long.
According to the Hibernate documentation:
We recommend that you declare consistently-named identifier properties
on persistent classes and that you use a nullable (i.e.,
non-primitive) type.
About seats. There is two ways. First way:
- You don't need to reduce seats in trains. It can be fixed. Just when your customer trying to buy tickets, your application doing query to database for all tickets on that train. And if number of existing tickets are more or equals than train capacity customer just can't buy ticket. But that way is good, when all your seats are equals (don't have numbers, like in bus, for example). But if your seats are not equal (train with different type of seats) you go with second way:
- You must have another entity SEATS, which has id, number, price etc., etc. and has ManyToOne relationship with TRAIN. In that time TRAIN must have next field
#OneToMany(mappedBy = "train", cascade = CascadeType.ALL)
private Set<Seat> seats;
pros:
- If you properly set getters and setters (and it's not just
public setSeats (Set<Seat> seats) {
this.seats = seats
}
, you must google for right setters, cuz if you setters works only by eager fetch - it's not right setters), you'll have advantage of cascading (for example - when you delete train from DB, all seats will be deleted automatically)
cons:
- bidirectional relationship can be the pain in the performance when you use JPQL (N+1 and so on, and you feel it when your table will be more than 1000 rows). So there is third way:
You still have SEAT entity. Train can know about seats anything, but in Seat you have field Train like this
#OneToOne
public Train getTrain() {
return train;
}
public void setTrain(Train train) {
this.train = train;
}
cons:
- When you want to delete train, you should at first delete all seats from that train
pros:
- It's much faster than bidirectional relation for JPQL
I have a Spring JPA Repository which behaves in a strange way. To be precise, it returns a list of objects which all appear to be identical, although the underlying database query seems to be returning the correct information.
The entity class is below. It corresponds to a View in MySQL.
#Entity
#Getter
#Cacheable(false)
#Table(name="view_assignment_selector")
public class AssignmentSelectorView {
#EmbeddedId private ID id;
private int areaId;
private String name;
#Enumerated(EnumType.ORDINAL) private Preference preference;
private int assigned;
private int required;
private boolean selected;
#Embeddable #Getter
public static class ID implements Serializable {
private Integer volunteerId;
private Integer sessionId;
}
}
Here is the Repository:
public interface AssignmentSelectorViewRepository extends JpaRepository<AssignmentSelectorView, AssignmentSelectorView.ID> {
List<AssignmentSelectorView> findByIdVolunteerIdAndIdSessionId(int volunteerId, int sessionId);
}
Here is the generated query as logged by MySQL:
SELECT AREAID, ASSIGNED, NAME, PREFERENCE, REQUIRED, SELECTED, SESSIONID, VOLUNTEERID FROM view_assignment_selector WHERE ((VOLUNTEERID = 820) AND (SESSIONID = 32))
When I try the query in MySQL directly, the result is correct. But the list of AssignmentSelectorView objects is the correct size, but all entries are identical to the first.
What's going on here?
Lesson learned - by extra careful with Ids.
It's quite tricky to write #Entity classes for Views because Views don't really have Primary Keys, but the #Entity class still needs an Id.
My original Id was wrong in that the 2 columns were not unique. I needed a 3rd column. The correct Id is:
#Embeddable #Getter
public static class ID implements Serializable {
private Integer volunteerId;
private Integer sessionId;
private Integer areaId;
}
Now it works.
I have two entities in my system
#Entity
public class Person {
#Id
private Long id;
private String name;
#ManyToMany()
private List<Book> books;
}
#Entity
public class Book {
#Id
private Long id;
private String name;
private String Volume;
private String pageNumber;
#ManyToMany(mappedBy = "books")
private List<Person> people;
}
Essentially a person can appear in multiple books , and books can reference multiple people.
I am using spring data with jpa and exposing a service that returns paged results where I will be able to sort using the sort parameter (such as /service/people?sort=name)
I have a requirement to sort the people in the order they appear in a given book defined by the id of the book.
Is there a way to list all the people in the order they appear in book id 4 for example (sort by the volume and pageNumber in book 4), no matter what the order is in other books? What would the SQL query be? And is it doable with JPA?
It's ok to assumer that All books are associated with all "persons"
I create 3 model classes in playframework, and set one-one relationship and one-to many relationship in one of the class. The code snippet are as follows:
Person.java
///////////////////////
#Entity
#Table(name = "person")
public class Person extends Model{
#Id
private Long id;
private String lastName;
private String firstName;
private String userId;
private Address address;
private List<Task> tasks;
....
}
Task.java
//////////////////////////
#Entity
#Table(name = "task")
public class Task extends Model{
#Id
private Long id;
private String name;
private String descript;
private String details;
...........
}
Address.java
////////////////////
#Entity
#Table(name = "address")
public class Address extends Model{
#Id
private Long id;
private String street;
private String state;
.........
}
I create person object and set the attributes/one-one/one-many relationships.
I try to save the person object with both attributes and relationships to mysql db by calling person.save().However, it ends up saving only attributes userId/firstName/LastName. the address object and tasks list object are not saved in db.
My question is : is there any way to save the relationship objects in db long with person.save()? that is , after calling person.save(), address table and task table create new entires corresponding to them.
I end up setting foreign keys in person class to handle this relationship manually.
Thanks in advance!
You might want to have a look at a JPA tutorial in particular topics about #OneToMany and #OneToOne annotations. I'd recommend https://en.wikibooks.org/wiki/Java_Persistence/OneToMany and https://en.wikibooks.org/wiki/Java_Persistence/OneToOne.