I have a User class that has #Embedded a class Profile. How can I give the instances of Profile a reference to their owner the User class?
#Entity
class User implements Serializable {
#Id #GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Embedded Profile profile;
// .. other properties ..
}
#Embeddable
class Profile implements Serializable {
User user; // how to make this work?
setURL(String url) {
if (user.active() ) { // for this kind of usage
// do something
}
}
// .. other properties ..
}
Refer to the official documentation ,section 2.4.3.4. , http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/ , you can use #org.hibernate.annotations.Parent to give the Profile object a back-pointer to its owning User object and implement the getter of the user object .
#Embeddable
class Profile implements Serializable {
#org.hibernate.annotations.Parent
User user; // how to make this work?
setURL(String url) {
if (user.active() ) { // for this kind of usage
// do something
}
}
User getUser(){
return this.user;
}
// .. other properties ..
}
Assuming JPA rather than strictly Hibernate, you might do this by applying #Embedded to a getter/setter pair rather than to the private member itself.
#Entity
class User implements Serializable {
#Id #GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Access(AccessType.PROPERTY)
#Embedded
private Profile profile;
public Profile getProfile() {
return profile;
}
public void setProfile(Profile profile) {
this.profile = profile;
this.profile.setUser(this);
}
// ...
}
However, I would question whether an embedded entity is what you want at all in this case, as opposed to a #OneToOne relationship or simply "flattening" the Profile class into User. The main rationale for #Embeddable is code reuse, which seems unlikely in this scenario.
Related
What I want to achieve to take auto generated ID, hash it and save it into other field in the class, but at the stage of creating object by constructor ID is not yet generated. Any workaround ideas?
#Entity
public class MyClass {
#Id
#Column(name="id")
#GeneratedValue(strategy=GenerationType.AUTO)
Long id;
String hashID;
MyClass(){
this.hashID = Utils.hashID(id);
}
//setters and getters
}
```
One way that I can think of is you can use an entity lifecycle callback event like #PostLoad which is called when the entity is loaded in the persistence context, and initialize your hashed field from the id.
E.g.
#Entity
public class MyClass {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
Long id;
String hashID;
#PostLoad
public void postLoad() {
// Here id is initialized
this.hashID = Utils.hashID(id);
}
}
I saw this kind of API style once and it worked proper
Noob here and I am current learning RESTful stuff,If anyone who may gives some advice and instruction.I'd be very appreciate!
Get URL
//The argument isn't mandatory, May be order.orderInfo,order.orderPrice etc
http://localhost:8080/order?order.orderNo=123
Controller code
#GetMapping
CollectionModel<Order> getOrders(Order order) {
List<Order> ordersResult = orderService.getOrders(order);
for (Order result : ordersResult) {
Link selfLink = WebMvcLinkBuilder.linkTo(OrderController.class).slash(result.getId()).withSelfRel();
result.add(selfLink);
}
Link link = WebMvcLinkBuilder.linkTo(OrderController.class).withSelfRel();
return CollectionModel.of(ordersResult, link);
}
Entity code
public class Order extends RepresentationModel<Order> implements Serializable {
#Id
#GeneratedValue
#Column(unique = true)
private Integer id;
private Long orderNo;
}
And my jpa repository
public interface OrderRepository extends JpaRepository<Order, Integer>,PagingAndSortingRepository<Order, Integer> {
}
I have finally figured out that this kind of URL is not work this way.
Shoud be apply to a specific situation.Which is the get endpoint method has a 'Relative Object'.Then we may use URL like this to improve flexable api.
Talk is cheap,I'll show you the code!
Entity->Customer
public class Customer extends RepresentationModel<Customer> implements Serializable {
#Id
#GeneratedValue
#Column(unique = true)
private Integer id;
private String name;
//Add relative Object to entity.
#OneToOne
private Order order;
}
Entity->Order
public class Order extends RepresentationModel<Order> implements Serializable {
#Id
#GeneratedValue
#Column(unique = true)
private Integer id;
private Long orderNo;
//Add relative Object to entity.
#OneToOne
private Customer customer;
}
Endpoint->CustomerController/getMethod
#GetMapping
CollectionModel<Customer> getCustomers(Customer customer) {
List<Customer> customersResult =
customerService.getCustomers(customer);
for (Customer result : customersResult) {
Link selfLink = WebMvcLinkBuilder.linkTo(CustomerController.class).slash(result.getId()).withSelfRel();
result.add(selfLink);
}
Link link = WebMvcLinkBuilder.linkTo(CustomerController.class).withSelfRel();
return CollectionModel.of(customersResult, link);
}
URL
scheme://[api]/[order.orderNo=123]
Then the value will mapping to paramter-custoemr inside.
PS:HTTP method '#fragment' may suitable for this case.
Thanks to #JRichardsz :)
Let's say I have two entities:
#Entity
public class Phone {
#Id
private Long id;
private String number;
}
#Entity
public class Person {
#Id
private Long id;
private String name;
}
The relationship between a person and a phone is one to one.
How could I access only the phone's number in the Person entity mapped by the phone's id
#Entity
public class Person {
#Id
private Long id;
private String name;
// ???
private String phoneNumber;
}
The reason for not mapping the whole entity is because in some more realistic entities there are too many properties.
I don't think you can, but something like this might be acceptable:
public class Person {
#OneToOne
#JoinColumn(name = "phone_id")
private Phone phone;
public String getPhoneNumber() {
return phone.getNumber();
}
}
Although you have mapped the whole object, not just the single property, you have only exposed the single property you want. The other stuff is hidden.
Alternatively, do it at the DB layer using a View:
create view person_with_phone as
select p.id, p.name,f.number
from person p
join phone f on f.id=p.phone_id
and then have an entity class to match the view. You'll need to turn off schema creation in your JPA implementation.
I've got an object with this parameters
{
"id" : "36461dd3-2bdb-42de-8e3d-b44e28696b1e",
"race" : "HUMAN",
"age" : "18",
"name" : "Alisa"
}
I attempt to save it
List<MainFemaleCharacter> batch = Arrays.asList(sampleMainCharacter());
try (Session session = sessionFactory.openSession()) {
session.beginTransaction();
batch.forEach(session::save);
session.getTransaction().commit();
}
In debug, before saving, it shows id with expected value. But when I retrieve object it shows another id for example dccaf5d0-5c2b-4336-a0f3-ff65f92bf5f1. Why? MainFemaleCharacter class looks like this
#Entity
#Table(name="main_female_character")
#EqualsAndHashCode(callSuper=true)
#ToString(callSuper=true)
public #Data class MainFemaleCharacter extends BasicCharacter {
}
#MappedSuperclass
#EqualsAndHashCode(callSuper=true)
#ToString(callSuper=true)
public #Data class BasicCharacter extends UidNamedObject {
#OneToOne
private Race race;
private int age;
}
#MappedSuperclass
public #Data class UidNamedObject {
#Id
#GeneratedValue
private UUID id;
#Column(unique=true)
private String name;
}
The annotation #GeneratedValue will generate an id automatically. It is the same as the #GeneratedValue(strategy=GenerationType.AUTO) annotation.
GenerationType.AUTO means that the persistence provider chooses a strategy which will restart the values after a server restart in your case.
I recommend you to consider using GenerationType.SEQUENCE.
i have 2 entities: User and Role
i have one class Userrole that will contain a composite key between user and role.
now Userrole will not contain userId and roleId.. but the object User and Role and it looks like this:
public class UserRole implements Serializable{
User user;
Role role;
can i put #Id on the User? like:
#Id
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
?
Using annotations, you need to define a proper class for your composite id, and annotate it as #Embeddable. (With XML, one can map the composite id without an explicit id class too.) Here is an example using an inner class as composite id, and another one, with a top-level id class.
no.
You can only use #Id in primitives. But you can use a #ComposeId or #IdClass (something like that, cant access hibernate doc now...) and map user as your composed id
The way I would do:
#Entity
public class User {
...
#OneToMany
public Set<UserRoles> getUserRoles() {
return this.userRoles;
}
}
#Entity
public class UserRole {
...
#Id
#GeneratedValue
public long getId() {
return this.id;
}
#ManyToOne
public Role getRole() {
return this.role;
}
#ManyToOne
public Role getCategory() {
return this.category;
}
}