I want to insert doctor object to database, how should I put annotations for properties?
I tried to do it with te code shown below.
But i don't know how to do it on list properties specializations and phoneNumbers.
#Table(databaseName = WMDatabase.NAME)
public class Doctor extends BaseModel{
#Column
#PrimaryKey
#Unique(unique = true)
private String doctorId;
#Column
private FullName fullName;
#Column
private String organizationId;
#Column What shuld i put here?????
private List<Specialization> specializations;
#Column What shuld i put here?????
private Contacts contacts;
}
Below are the classes I use for doctor attributes:
public class Contacts extends BaseModel {
private List<PhoneNumber> phoneNumbers;
private String email;
private String fax;
}
public class Specialization extends BaseModel {
#Column
#PrimaryKey
#Unique(unique = true)
private String doctorId;
#Unique(unique = true)
private String specializationName;
public String getSpecializationName() {
return specializationName;
}
public void setSpecializationName(String specializationName) {
this.specializationName = specializationName;
}
DBFlow is a relational database system (not a mongo-type key/value store) and doesn't support lists as columns, according to the doc here.
List : List columns are not supported and not generally proper for a relational database. However, you can get away with a non-generic List column via a TypeConverter. But again, avoid this if you can.
The documentation on relationships may help you refine the model to suit your needs.
Related
I have user in database and trip holidays, now, I want to create a document that will store holidays that user saved. Something like when you go on some website for buying products and then you 'favorite - save - bookmark' something.
I have a couple of entities for trip holidays like AdventureHolidays, Backpacking, CruiseHolidays etc.
Model looks like this:
#Document("adventureholidays")
public class AdventureHolidays {
#Id
private String id;
private String title;
private String description;
private String state;
private String typeOfAdventureHolidays;
private String image;
And I have a lot of them for each holiday as I said, Backpacking, CruiseHolidays etc.
I have user model like this:
#Document
public class User {
#Id
private String id;
#Indexed(unique = true)
#NonNull
private String username;
#Indexed(unique = true)
#NonNull
private String email;
#JsonIgnore
#NonNull
private String password;
Next I created a new model that will actually store userId and documents that he has saved.
#Document
public class UserSavedTrips {
#Id
private String userId;
#DBRef
AdventureHolidays adventureHolidays;
#DBRef
User user;
I dont know did I even implement that document for storing user saved holidays right.
Next I created repository:
#Repository
public interface UserSavedTripsRepository extends MongoRepository<UserSavedTrips, String> {
}
And service:
#Service
public class UserSavedTripsServiceImpl implements UserSavedTripsService {
#Autowired
UserSavedTripsRepository userSavedTripsRepository;
#Override
public UserSavedTrips save(UserSavedTrips userSavedTrips) {
return userSavedTripsRepository.save(userSavedTrips);
}
}
How I can now create controller for this so actually I can do what I want when I hit save button? And also, is this even good? Will that actually save holidayID to userSavedHolidays with also userID?
When i trying to do my RBAC job , I've made a class RolePermission like belows:
#Data
#AllArgsConstructor
#NoArgsConstructor
public class RolePermission extends BaseEntity{
private Long roleId;
private Long permissionId;
#Transient
private List<Permission> permissions;
public RolePermission(Long roleId,Long permissionId){
this.roleId = roleId;
this.permissionId = permissionId;
}
}
class Permission like belows
#AllArgsConstructor
#NoArgsConstructor
#Data
public class Permission extends BaseEntity{
public Permission(Long id, Long parentId, String name){
this.setId(id);
this.parentId = parentId;
this.name = name;
}
private String name;
private Long parentId;
private String url;
private String permission;
private Integer type;
private String icon;
private Integer status;
private Integer ord;
}
Here comes my test :
LookupOperation lookup = Aggregation.lookup("permission", "roleId", "_id", "permissions");
Aggregation aggregation = Aggregation.newAggregation(lookup);
AggregationResults<RolePermission> role_permission = mongoTemplate.aggregate(aggregation, "role_permission", RolePermission.class);
//AggregationResults<Map> role_permission = mongoTemplate.aggregate(aggregation, "role_permission", Map.class);
System.out.println(role_permission.getMappedResults());
//userService.getAllPermissions(u);
When I add #Transient , permissions comes to null
and When I remove #Transient,permissions comes back.
I don't wanna save permissions to MongoDB, so I add #Transient, is there any way i can draw the data back without saving it to the Database. Because I get the permissions data from a relationship collectionRolePermission,not itself.
The #Transient behaves similar to the transient keyword.
transient is used to denote that a field is not to be serialized (and therefore not saved in the database too).
#Transient is used to denote that a field should not persisted in database (but it is still serializable as java object).
Take look this baeldung tutorial for it: https://www.baeldung.com/jpa-transient-ignore-field
There is no way to draw the data back without saving it to the Database because it isn't persisted at all since it is what #Transient is used for.
To get the data back you have to persist it somewhere else, but the best place is in the database. If you don't want to persist it along with the other data, consider saving it in a sperate database. So, you could split user data and authentication/RBAC data.
I'm trying to fetch just a part of the model using Ebean in Play! Framework, but I'm having some problems and I didn't found any solutions.
I have these models:
User:
#Entity
#Table(name = "users")
#JsonInclude(JsonInclude.Include.NON_NULL)
public class User extends Model{
#Id
private int id;
#NotNull
#Column(name = "first_name", nullable = false)
private String firstName;
#Column(name = "last_name")
private String lastName;
#NotNull
#Column(nullable = false)
private String username;
#NotNull
#Column(nullable = false)
private String email;
private String gender;
private String locale;
private Date birthday;
private String bio;
#NotNull
#Column(nullable = false)
private boolean active;
private String avatar;
#Column(name = "created_at",nullable = false)
private Date createdAt;
#OneToMany
private List<UserToken> userTokens;
// Getters and Setters omitted for brevity
}
UserToken:
#Entity
#Table(name = "user_tokens")
public class UserToken extends Model {
#Id
private int id;
#Column(name = "user_id")
private int userId;
private String token;
#Column(name = "created_at")
#CreatedTimestamp
private Date createdAt;
#ManyToOne
private User user;
// Getters and Setters omitted for brevity
}
And then, I have a controller UserController:
public class UserController extends Controller{
public static Result list(){
User user = Ebean.find(User.class).select("firstName").where().idEq(1).findUnique();
return Results.ok(Json.toJson(user));
}
}
I expected that, when using the .select(), it would filter the fields and load a partial object, but it loads it entirely.
In the logs, there is more problems that I don't know why its happening.
It is making 3 queries. First is the one that I want. And then it makes one to fetch the whole Model, and another one to find the UserTokens. I don't know why it is doing these last two queries and I wanted just the first one to be executed.
Solution Edit
After already accepted the fact that I would have to build the Json as suggested by #biesior , I found (out of nowhere) the solution!
public static Result list() throws JsonProcessingException {
User user = Ebean.find(User.class).select("firstName").where().idEq(1).findUnique();
JsonContext jc = Ebean.createJsonContext();
return Results.ok(jc.toJsonString(user));
}
I render only the wanted fields selected in .select() after using JsonContext.
That's simple, when you using select("...") it always gets just id field (cannot be avoided - it's required for mapping) + desired fields, but if later you are trying to access the field that wasn't available in first select("...") - Ebean repeats the query and maps whole object.
In other words, you are accessing somewhere the field that wasn't available in first query, analyze your controller and/or templates, find all fields and add it to your select (even if i.e. they're commented with common HTML comment in the view!)
In the last version of Play Framework (2.6) the proper way to do this is:
public Result list() {
JsonContext json = ebeanServer.json();
List<MyClass> orders= ebeanServer.find(MyClass.class).select("id,property1,property2").findList();
return ok(json.toJson(orders));
}
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.
So, after several attempts of trying and trying to make this work the way I want, and of course checking different guide, I now come to you guys.
My program is designed to work like this:
persona (the father object)
-persona_cuil (pk on DB, generated by user)
empleado (persona's son)
-legajo_id (pk on DB, generated by program NOT DB (couldnt make that work either))
-persona_cuil (FK from persona)
empvarios (empleado's son)
-legajo_id (PK and FK from empleado)
Now, the database is mapped that way, and it works just fine, the problem seems to be that hibernate somewhere mixes the primary keys sent to each object, and instead of inserting a legajo_id in empvarios, it inserts a persona_cuil.
Code for clases:
persona:
#Entity
#Table(name = "persona")
#Inheritance(strategy = InheritanceType.JOINED)
public class persona implements Serializable {
private static final long serialVersionUID = 2847733720742959767L;
#Id
#Column(name="persona_cuil")
private String persona_cuil;
#Column(name="nombre")
private String nombre;
#Column(name="apellido")
private String apellido;
#Column(name="fecha_nac")
private String fecha_nac;
#Column(name="direccion")
private String direccion;
#Column(name="localidad")
private String localidad;
#Column(name="provincia")
private String provincia;
#Column(name="pais")
private String pais;
#Column(name="fecha_muerte")
private String fecha_muerte;
#Column(name="fecha_alta")
private String fecha_alta;
#Column(name="fecha_baja")
private String fecha_baja;
#Column(name="mail")
private String mail;
#Column(name="plan_id")
private int plan_id;
public persona (){
this.setPlan_id(0);
}
//Getters and Setters
}
empleado:
#Entity
#Table(name = "empleado")
#Inheritance(strategy = InheritanceType.JOINED)
#PrimaryKeyJoinColumn(name="persona_cuil")
public class empleado extends persona implements Serializable {
private static final long serialVersionUID = -7792000781951823557L;
#Column(name="legajo_id")
private int legajo_id;
public empleado(){
super();
int leg = SentenceManager.ultimoRegistro("empleado");
if (leg == 0){ //this works fine, it just searches the last registry, if it exists, i uses the next available number
this.setLegajo_id(1);
}
else {
this.setLegajo_id(leg+1);
}
}
//Getters and Setters
}
empvarios:
#Entity
#Table(name="empvarios")
#PrimaryKeyJoinColumn(name="legajo_id")
public class empvarios extends empleado implements Serializable, ToPersona{
private static final long serialVersionUID = -6327388765162454657L;
#Column(name="ocupacion_id")
int ocupacion_id;
public empvarios() {
super();
this.setLegajo_id(super.getLegajo_id());
}
//Getters and setters
}
Now, if I try to insert a new empleado into the database, it works just fine... BUT if I try to insert an empvarios, in the place where should be legajo_id, hibernate places the persona_cuil (I tested this by removing the FK restriction on the data base)
Images below:
(cant post images due reputation restriction :/)
https://www.dropbox.com/sh/mu5c797adlf7jiv/AACnd8mx7GriSyq5OMKoddRna?dl=0
There you have the 3 photos, the name of the files shows which table is each one.
Any ideas on whats going on?
The problem was that the data base was wrongly mapped.
If anyone has this problem then you will have to rethink the structure of the DB.
As seen in the example i gave above, the database should look like this:
persona:
persona_id (PK-autoincemental)
empleado:
persona_id (FK to persona)
legajo_id
empvarios:
persona_id (FK to persona)
ocupacion_id
The reason this works like this is because you cannot have different ids to depend different clases within the data base. On the program side it "can" work like that, but it the data base it has to be mapped differently.
Thanks!