We are using some #Embeddable beans within some JPA Entities for better code structure and reuse. What I'm wondering is: every example I come across provides setters and getters for the #Embedded objects. Why? I tried just having them as final fields - that works, too, and makes much sense in our case, since the embedded stuff is always present. Is there some disadvantage of this that I am not aware of?
For example: usually it is done that way:
#Embeddable
public class Address {
// ...
}
#Entity
public class Person {
#Embedded
private Address address;
public void setAddress(Address address) {
this.address = address;
}
public Address getAddress() {
return address;
}
}
Is there any trouble when I write Person this way, when there is always an Address:
#Entity
public class Person {
#Embedded
private final Address address = new Address();
public Address getAddress() {
return address;
}
}
You cannot persist final or static fields, and that applies whether embedded or non-embedded. The JPA spec is very clear about that, as are documents for the different JPA providers.
JPA Spec $2.1
The entity class must not be final. No methods or persistent instance
variables of the entity class may be final.
Related
If I have a Entity class as such where a user can have multiple addresses:
#Entity
public class User {
private String name;
private List<Address> address;
}
#Entity
public class Address {
private String area;
private String city;
}
Should the DTO exposed for the webservice contain Address object (like what User contains) or an AddressDTO object like this?
public class UserDTO {
private String name;
private List<AddressDTO> addressList;
}
Where can I find example code using DTO objects that contain nested objects as such, where I can see best practices on how to populate those nested objects inside the main DTO? (I've googled ad nauseam but so far no examples with this scenario)
I have a User, a Shop, and an Address entity.
Both a user and a shop can have an address.
What would be the best way to set up such a relationship using Spring JPA/Hibernate?
I had thought of creating an interface and let user and shop implement it, then use the interface in the address entity class to access the their common code. I couldn't get it to work, and I kinda feel like I'm over-complicating things. It might have looked something like this:
Addressable Address
|
+---+---+
| |
Shop User
#Entity
#Table(name = "shops")
public class Shop implements Addressable {
#OneToOne
#JoinColumn(name = "address_id")
private Address address;
#Column(name = "name", nullable = false)
private String name;
#Entity
#Table(name = "users")
public class User implements Addressable {
#OneToOne
#JoinColumn(name = "address_id")
private Address address;
#Column(name = "name", nullable = false)
private String name;
public interface Addressable {
String getName();
void setName(String name);
#Entity
#Table(name = "addresses")
public class Address {
#OneToOne
private Addressable addressable;
#Override
public String toString() {
return addressable.getName() + "\n" +
streetName + " " + streetNumber + "\n" +
postalCode + " " + cityName;
}
I might be waay off course, it doesn't quite feel right. I'm sure this is problem other people have encountered as well, though I as of yet to have found a nice if any solution.
Do you need your addresses to be separate entities? In other words, is there a specific need to store addresses in a dedicated table, or do you just want to group address related properties in a common object included in shop and user just for the purpose of code reuse? If the latter applies, you could make the address embeddable and mark it as embedded in your user and shop entities. They become additional properties in the user and shop table represented by the corresponding entities.
#Entity
#Table(name = "shops")
public class Shop {
#Embedded
private Address address;
#Entity
#Table(name = "users")
public class User {
#Embedded
private Address address;
#Embeddable
public class Address {
#Column(name = "name")
private String name;
public String getName() {...}
If you need to store them as separate entries in a dedicated table, using a "real" relationship is the correct approach (one-to-one, one-to-many annotations etc...)
Using an interface as a member of a relationship in JPA instead of a real object is not possible. A member of a relationship needs to be a POJO (a real object) because the JPA engine (like Hibernate) needs to be able to instantiate such classes in the background. Since you cannot instantiate an interface (or abstract class), you cannot use interfaces in relationships directly. One rather dirty trick could be working when defining custom converters that translate between the interface and a real POJO. This I have never tried before so I am not sure this will work. I also discourage this approach since it would imply some mechanism to choose the concrete class implementation to instantiate in your converter which seems very bad code design to me ;-)
What you also could try is create an abstract class storing the name property together with getter and setters and proper column annotations for all common properties. Mark this abstract class as MappedSuperclass and let your User and Shop class subclass this abstract class. Both subclasses have the superclass' common code inherited. The mappedsuperclass and your subclass code will be merged into one entity.
#Entity
#Table(name = "shops")
public class Shop extends Addressable{
...
#Entity
#Table(name = "users")
public class User extends Addressable{
...
#MappedSuperclass
public abstract class Addressable {
#Column(name = "name")
private String name;
public String getName() {...}
It looks like you are just using Java EE JPA, not Spring JPA or Hibernate.
There are data model patterns such as "the party model" where Person and Shop are subclasses of the same parent. (Parties have one or more Addresses and are People or Organizations, Shops are Organizations)
while you can use #MappedSuperClass to have a non-entity superclass, for your specific question I would look the Java EE JPA's #AttributeOverride. This helps to let JPA know that what in the Interface will be part of the Entity.
Suppose i have two morphia entities: Person and Team which are look like this
#Entity
public class Person {
private String name;
private String login;
private String mail;
private List<Team> teams;
}
#Entity
public class Team {
private String name;
private String description;
private List<Person> members;
//some more fields
}
I want map this model into Mongodb database like this
Users collection
{
name:"someName",
login:"somelogin",
mail:"some#mail.com",
teams: [
{id:"teamId", name:"TeamName"} //only specific fields fron Team Entity
{id:"anotherTeamId", name:"AnotherTeamName"}
]
}
Teams collection
{
id:"teamId",
name:"TeamName",
description:"Very strong team",
members: [id:"aaa", name: "someName"] //only specific fields fron User Entity
//some other fields
}
{
id:"anotherTeamId",
name:"AnotherTeamName",
description:"Brave new team",
members: [id:"aaa", name: "someName"] //only specific fields fron User Entity
//some other fields
}
So, I want denormolize only specific fields (only name for example) from Team document into User's teams field.
I don't understand Can I use morphia (or some other odm) for this case? Which annotations I should use in my Entities?
It seems that #Reference annotation is not allowed with List<> fields.
I think, i should create inner class PersonTeam, which will contain Team's name and id, and use it in Person class
#Entity
public class Person {
private String name;
private String login;
private String mail;
private List<PersonTeam> teams;
}
public class PersonTeam {
private String teamId;
private String teamName;
}
Is this a good way to solve my problem? thank you!
That's about the only way to do it with morphia at least. You might consider using #Reference on those fields and only storing the IDs. That'd help if your concern is saving space.
I have following DTO and Domain objects. I am using Mapstruct to copy domain object to DTO object.
public class AddressDomain {
private String street;
private Telephone telephone;
}
public class CompanyDomain{
private String id;
private Address address;
}
public class AddressDTO {
private String street;
private Telephone telephone;
}
public class CompanyDTO{
private String id;
private Address address;
}
Mapping Domain to DTO using below Mapper. i don't want to map telephone property from domain to DTO. How to do that? i tried providing nested target property in mapping ignore but it gives error:
public interface CompanyMapper {
//**below line gives error**
#Mapping(target = "address.telephone", ignore=true)
CompanyDTO map(AddressDTO dto);
}
Your current definition maps an address into a company object which doesn't seem right. You need to declare two methods, one for mapping addresses and one for mapping companies (whose generated implementation will in turn invoke the address mapping method):
public interface CompanyMapper {
CompanyDTO map(Company company);
#Mapping(target="telephone", ignore=true)
AddressDTO map(Address address);
}
I am new to jpa and wonder how I have to realize this. I want to use an Entity called Address in several other Entities.
Car entity:
#Entity
public class Car
#Id
private String id;
private String licensePlate;
#ManyToOne
private Address address;
public Car() {
}
/* Getter and setters */
....
..
Person entity:
#Entity
public class Person {
#Id
private String id;
private String name;
#OneToMany(mappedBy = "address", cascade = CascadeType.ALL)
private Set<Address> addresses;
public Person() {
}
/* Getter and setters */
....
..
Address entity:
#Entity
public class Address {
#Id
private String id
private String streetAndNumber;
/* Now what?????? */
private Car car; // would fit for car
private Person person; // would fit for person
// But what would be fitted both?
I searched the internet to find a solution. But, most likely to my lack of knowledge. I couldn't find something understandable.
There is actually no need to make all relations bidirectional, it's a best practice to prefer unidirectional relationships in a model whenever possible, see Domain Driven Design Quickly.
In this case Address does not need to know of all the entities that it's associated with. Also consider making the address a Value Object (see DDD quickly) using the #Embeddable annotation.