I've got 2 tables vehicle and vehicle_image. The vehicle table contains all master data of the vehicles and the vehicle_image table contains the meta information of the images and the Base64 encoded string of the image. On vehicle may have 0 or more images.
Now when I query the vehicle object I'd like the object to contain the information from the vehicle_image table.
I'm pretty new to JPA and the examples I could find always seem to read only one value from another table, not a list.
What would be the simplest way of adding an attribute to the vehicle object that contains the image data?
#Entity
#XmlRootElement(name = "vehicle")
public class Vehicle {
#Id
private String vin;
private String commission;
#Column(name="swiss_type_number")
private String swissTypeNumber;
#Column(name="sale_type")
private String saleType;
#Column(name="exterior_color")
private String exteriorColor;
#Column(name="interior_color")
private String interiorColor;
private String remarks;
#Column(name="additional_title")
private String additionalTitle;
#Column(name="added_value_description")
private String addedValueDescription;
#Column(name="first_registration")
private String firstRegistration;
private String guaranty;
#Column(name="last_inspection")
private String lastInspection;
private int dealer;
private int mileage;
private int price;
private int seats;
#Column(name="model_year")
private int modelYear;
#Column(name="car_damaged_in_accident")
private boolean carDamagedInAccident;
private boolean imported;
// List of images
List<VehicleImage> vehicleImages; // Something like this would be nice
}
JPA supports associations between entities. The one you need is #OneToMany
If your vehicle_image' table contains columnvehicle_idyou will need following mapping inVehicle` class:
#Entity
#Table(name = "VEHICLE")
#XmlRootElement(name = "vehicle")
public class Vehicle {
// other fields here
#OneToMany(mappedBy = "vehicle")
Set<VehicleImage> vehicleImages;
}
And also this in VehicleImage
#Entity
#Table(name = "VEHICLE_IMAGE")
public class VehicleImage{
// other fields here
#ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
#JoinColumn(name="VEHICLE_ID", referencedColumnName = "ID")
Vehicle vehicle;
}
Also you should better use Set for collections mapping in JPA, but it is a different topic
What you have here is a one-to-may relationship, you can use:
#OneToMany
List<VehicleImage> vehicleImages;
Refere to the javadoc for the attributes it may take and add them according to your table definitions.
Here you can find some examples of how to use it.
Related
I'm trying to write a controller that will function as multiple seat reservation.The Integers list is used for filtering.
My Entity looks like this:
#Entity
#Id
private movieId;
private String movieName;
private String cinemaName;
private String cinemaHall;
private Intger seatingPlace;
private boolean booked;
How Can I pass list or sets in request body to access multiple update seatingPlace. Did I modyfing Enity or connect in smthing relation?
Acutally my multipleUpdate API works using JPA Query findByMovieNameAndCinemaNameAndcinemaHall and return me list wchich
I checking isnt Empty and cheking (field boolean booked) if true so ok u can booked them.
And after that i want filter by passing List seatingPlace and change boolen to false.
Based on my understanding of your requirements, a possible solution could be creating another entity (table) MovieSeatReservation and creating a One to Many relationship from your Entity. It could look like this: (You can replace Entity class name with your real entity name)
#Entity
public class Entity {
#Id
#GeneratedValue
private Long movieId;
private String movieName;
private String cinemaName;
private String cinemaHall;
#OneToMany
private List<MovieSeatReservation> reservedSeatsStatus;
// getters and setters
}
#Entity
public class MovieSeatReservation {
#Id
#GeneratedValue
private Long id;
private boolean isReserved;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "movie_id")
private Entity entity;
// getters and setters
}
I have the following Pojo:
#Entity
#Table(name = "USER")
class User {
#Id
private long id;
private String name;
private int age;
private long lastVisited;
private long lastPlayed;
private long lastPayed;
...
}
I would like somehow if possible to map the Pojo like this:
#Entity
#Table(name = "USER")
class User {
#Id
private long id;
private String name;
private int age;
#Embedded
private UserStatistics statistics;
...
}
#Embeddable
class UserStatistics {
private long lastVisited;
private long lastPlayed;
private long lastPayed;
}
BUT, I DON'T want to move the statistics columns into a new
USER_STATISTICS table and do #OneToOne mapping.
Is there a Hibernate trick I can use here?
Thanks!
What you did is already enough, Hibernate does not require you to define fields for all columns in your table. It's rather the other way around - all non-transient fields should be reflected as columns in the corresponding table either using name defined in #Column annotation or generated using a naming convention used in hibernate configuration.
The example you presented is sufficient and will work, but I wouldn't recommend it as you can have two entities mapping single row at the same time.
I have three classes corresponding to three tables in mysql database. My classes are as follows.
#Entity
#Table(name="location")
public class Location {
private Integer locationId;
private Integer hospitalId;
private Integer regionId;
private String locationCode;
private String locationName;
private String locationType;
#Entity
#Table(name="hospital_region")
public class HospitalRegion {
private Integer regionId;
private Integer hospitalId;
private String regionCode;
private String regionName;
public enum Status{Active,Inactive}
private Status status;
#Entity
#JsonAutoDetect
#Table(name="hospital_information")
public class HospitalInformation{
private Integer hospitalId;
private String shortName;
private String name;
private Integer packageId;
private Date implementationDate;
private Date validFrom;
private Date validUpTo;
private Date lastUpload;
public enum SubscriptionType{Free,Complimentary,Paid}
private Integer totalUsers;
I am making a Web Services for a Hospital Application where one region could have multiple locations(one-to-many) and one hospital could be in multiple regions(one-to-many).
So what I want to do is make a web service that would insert the data into location table.The ideal workflow should be that I shall pass every field in Location class as a json object to insert a record into the Location table.
My Business Logic should first check for my regionId and hospitalId value passed in the json object . If the hospitalId which is passed corresponds to the value of regionId in region table, if both correspond, only then data should be saved.
So I need help about how to implement it as a Business Logic.Thanks in advance
You miss the JPA relationships concept.
Your attributes are not annotated in the 3 classes.
You need to read about:
#ManyToOne Relation
#OneToMany Relation
#OneToOne Relation
#ManyToMany Relation
See more:
JPA Foreign Key Annotation
JPA Relationships 1
JPA Relationships 2
I would like to find an entity using a critera with restriction on the value of an attribute of a second entity wich is a member of the embedded id of my first entity.
First entity :
#Entity
public class Car {
#EmbeddedId
private Id id = new Id();
private String color;
#Embeddable
public static class Id implements Serializable {
private static final long serialVersionUID = -8141132005371636607L;
#ManyToOne
private Owner owner;
private String model;
// getters and setters...
// equals and hashcode methods
}
// getters and setters...
}
Second entity :
#Entity
public class Owner {
#Id
#GeneratedValue (strategy = GenerationType.AUTO)
private Long id;
private String firstname;
private String lastname;
#OneToMany (mappedBy = "id.owner")
private List<Car> cars;
// getters and setters...
}
In this example, I would like to obtain the car with the color 'black', model 'batmobile' and the owner's firstname 'Bruce' (oops... spoiler ;) )
I tried to do something like that but it won't work :
List<Car> cars = session.createCriteria(Car.class)
.add(Restrictions.eq("color", "black"))
.add(Restrictions.eq("id.model", "batmobile"))
.createAlias("id.owner", "o")
.add(Restrictions.eq("o.firstname", "Bruce"))
.list();
Result :
Hibernate: select this_.model as model1_0_0_, this_.owner_id as owner_id3_0_0_, this_.color as color2_0_0_ from Car this_ where this_.color=? and this_.model=? and o1_.firstname=?
ERROR: Unknown column 'o1_.firstname' in 'where clause'
What is the right way to obtain what I want ?
update
I tried in hql :
String hql = "FROM Car as car where car.color = :color and car.id.model = :model and car.id.owner.firstname = :firstname";
Query query = em.createQuery(hql);
query.setParameter("color", "black");
query.setParameter("model", "batmobile");
query.setParameter("firstname", "Bruce");
List<Car> cars = query.getResultList();
It works but is there a way to do this with criteria ?
You forgot to add the #Column annotation on top of the firstname and lastname fields (and the color field in Car). In hibernate if a field is not annotated, it doesn't recognize it as a database field. This page should give you a good idea about how to set up your model objects.
NOTE: You can have the column annotation over the getters and be fine, but you didn't show the getters. Either place is fine.
Look at what HQL is spitting back out, specifically the statement (formated for easier reading):
select
this_.model as model1_0_0_,
this_.owner_id as owner_id3_0_0_,
this_.color as color2_0_0_
from Car this_
where
this_.color=?
and this_.model=?
and o1_.firstname=?
It looks like hibernate is translating the field "id.owner" to "o" as your alias told it to to, but for some reason it's not writing down that "id.owner=o" as intended. You may want to do some research into why it may be doing that.
As per https://hibernate.atlassian.net/browse/HHH-4591 there is a workaround.
You have to copy the needed relation-property of the #EmbeddedId (owner in this case) to the main entity (Car in this case) with insertable = false, updatable = false as follows
#Entity
public class Car {
#EmbeddedId
private Id id = new Id();
private String color;
#ManyToOne
#JoinColumn(name = "column_name", insertable = false, updatable = false)
private Owner owner;
#Embeddable
public static class Id implements Serializable {
private static final long serialVersionUID = -8141132005371636607L;
#ManyToOne
private Owner owner;
private String model;
// getters and setters...
// equals and hashcode methods
}
// getters and setters...
}
Then just create directly the alias instead of using the composite id property
List<Car> cars = session.createCriteria(Car.class)
.add(Restrictions.eq("color", "black"))
.add(Restrictions.eq("id.model", "batmobile"))
.createAlias("owner", "o")
.add(Restrictions.eq("o.firstname", "Bruce"))
.list();
I want to use one class to map three tables. I know javax.persistance provides the #SecondaryTable annotation to map two tables to one class.
Below is the code, where I have used #SecondaryTable. It allows me to define only one secondary table. But I need 3 tables to be used by the same class.
#Entity
#Table(name = "table1")
#SecondaryTable(name="table2")
public class TableConfig
implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#Column(name = "mac", table= "table1")
private String uniqueIdentifier;
I want to use one class to map three tables, From what I know is that javax.persistance provides #SecondaryTable annotation to map two tables to one class
use #SecondaryTables to map more than one table.
You can map a single entity bean to several tables using the #SecondaryTables class level annotations. To express that a column is in a particular table, use the table parameter of #Column or #JoinColumn.
for example there is 3 entity's namely: Name , Address & Student:
Name entity will look like:
#Entity
#Table(name="name")
public class Name implements Serializable {
#Id
#Column(name="id")
private int id;
#Column(name="name")
private String name;
public Name(){}
public Name(int id,String name){
this.id=id;
this.name=name;
}
//getters and setters
}
Address entity will look like:
#Entity
#Table(name="address")
public class Address implements Serializable {
#Id
#Column(name="id")
private int id;
#Column(name="address")
private String address;
public Address(){}
public Address(int id, String address) {
super();
this.id = id;
this.address = address;
}
//getters and setters
}
Student entity will look like:
#Entity
#Table(name="student")
#SecondaryTables({
#SecondaryTable(name="name", pkJoinColumns={
#PrimaryKeyJoinColumn(name="id", referencedColumnName="student_id") }),
#SecondaryTable(name="address", pkJoinColumns={
#PrimaryKeyJoinColumn(name="id", referencedColumnName="student_id") })
})
public class Student implements Serializable {
#Id
#Column(name="student_id")
private int studentId;
#Column(table="name")
private String name;
#Column(table="address")
private String address;
public Student(){}
public Student(int studentId){
this.studentId=studentId;
}
//getters and setters
}
Store like:
Student s= new Student(1);
session.save(s);
Name n=new Name(s.getStudentId(),"Bilal Hasan");
session.save(n);
Address address = new Address(s.getStudentId(), "India");
session.save(address);
Student ob = (Student)session.get(Student.class, s.getStudentId());
System.out.println(ob.getStudentId());
System.out.println(ob.getName());
System.out.println(ob.getAddress());
ouput:
1
Bilal Hasan
India
you can define one class like below :
#Entity
#Table(name="table1")
#SecondaryTables({
#SecondaryTable(name="table2", pkColumnJoins={#PrimaryKeyJoinColumn(name = "id")}),
#SecondaryTable(name="table3", pkColumnJoins={#PrimaryKeyJoinColumn(name = "id")})
})
public class TestEntity {
#Id
#GeneratedValue
private int id;
private String field1;
#Column(name="column2", table="table2")
private String field2;
#Column(name="column3", table="table3")
private String field3;
getter and setter...
}
In your DB, should has three table, and all of them should has the same primary key "id".
then, use can test like this:
TestEntity test = new TestEntity();
test.setField1("field1");
test.setField2("field2");
test.setField3("field3");
em.merge(test);
after test, in your DB, you will find one record in each table:
table1:
1, field1
table2:
1, field2
table3:
1, field3
all of them will share the primary key value. Hope this will help you.
In Hibernate mapping file you can specify the entity-name mapping with virtual name along with polymorphism="explicit" and class name would be physical class name. Like that you may do multiple mappings. While loading the object use entityname (virtual name).