I have two java entity classes :
#Table(name = "user")
public class UserEntity
{
#Id
#Column(name = "id", unique = true, nullable = false)
private Long id;
#OneToOne(cascade = CascadeType.PERSIST, fetch = FetchType.EAGER)
#JoinColumn(name = "opportunity_id")
private OpportunityEntity opportunity;
}
and
#Table(name = "opportunity")
public class OpportunityEntity
{
#Id
#Column(name = "id", unique = true, nullable = false)
private Long id;
#OneToMany
#JoinColumn(name = "opportunity_id")
private List<UserEntity> users;
#OneToOne
#JoinColumn(name = "mainuser_id")
private UserEntity mainUser;
}
When i search for a list of Users [find users], i've got a "stackoverflow" when mapping User.opportunity.
the bug was clear that the opportunity.mainUser refer to User which itself refer to the same opportunity.
Is there another way to design my models ?
For example create a boolean isMain in User Model ?
Try to specify relationship to UserEntity by adding mappedBy to annotatation
#Table(name = "opportunity")
public class OpportunityEntity
{
#Id
#Column(name = "id", unique = true, nullable = false)
private Long id;
#OneToMany
#JoinColumn(name = "opportunity_id")
private List<UserEntity> users;
#OneToOne(mappedBy="opportunity")
#JoinColumn(name = "mainuser_id")
private UserEntity mainUser;
}
I'm having problem with mapping two classes with composite keys.
The first class is Product:
#Entity
#Table(name = "Products")
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#SuperBuilder
public class Product {
#EmbeddedId
private ProductKey prodPK;
#Column(name = "name", length = 50, nullable = false)
private String name;
#Column(name = "description", length = 80)
private String description;
#Column(name = "totalStock", columnDefinition = "double(8,2) default 0")
private double totalStock;
#ManyToOne
#JoinColumn(name = "companyId", referencedColumnName = "id", nullable = false)
private Company company;
}
With this #EmbeddedId:
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#EqualsAndHashCode
#Embeddable
public class ProductKey implements Serializable {
#Column(name = "sku", length = 50)
private String sku;
#Embedded
private LotKey lot;
}
At the same time, this embedded class has as part of its composite key another composite key "LotKey"
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#EqualsAndHashCode
#Embeddable
public class LotKey implements Serializable {
#Column(name = "lot")
private String lot;
#ManyToOne
#JoinColumn(name = "company", referencedColumnName = "id")
private Company company;
}
which belongs to the class:
#Entity
#Table(name = "Lots")
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#SuperBuilder
public class Lote {
#EmbeddedId
private LotKey lotpk;
#Column(name = "stock")
private double stock;
#Column(name = "expirationDate", columnDefinition = "default current_timestamp()")
private Date expirationDate;
}
But I'm having trouble referencing to them:
#Entity
#Table(name = "quantityProduct")
public class QuantityProduct{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private long id;
#ManyToOne
#JoinColumns({
#JoinColumn(
name = "sku",
referencedColumnName = "sku"),
#JoinColumn(
name = "lot")
})
private Product product;
#Column(name = "quantity", columnDefinition = "double(8,2) default 0")
private double quantity;
}
I am getting the following error
image
Thank you so much !
In QuantityProduct, set also referencedColumnName in
#JoinColumn(
name = "lot")
I'm having issues with the next samples whenever I remove the one to one relationship from the CustomerOrderEntity my tests are passed without problems however when I put back the relationship it fails telling me that a String can't be assigned to an Integer
What do I have wrong in my code?
How can I solve it?
#Getter
#Setter
#Builder
#NoArgsConstructor
#AllArgsConstructor
#Entity
#Accessors(chain = true)
#Table(name = "cust_order")
#EqualsAndHashCode(callSuper = true, onlyExplicitlyIncluded = true)
#NamedEntityGraphs({
#NamedEntityGraph(
name = CustomerOrderEntity.GRAPH_WITH_LINES,
attributeNodes = {
#NamedAttributeNode(value = "lines", subgraph = "subgraph.alternatives")
},
subgraphs = {
#NamedSubgraph(
name = "subgraph.alternatives",
attributeNodes = #NamedAttributeNode(value = "alternatives")
)
}
),
#NamedEntityGraph(
name = CustomerOrderEntity.GRAPH_WITH_DELIVERY,
attributeNodes = {
#NamedAttributeNode(value = "delivery")
}
),
#NamedEntityGraph(
name = CustomerOrderEntity.GRAPH_WITH_ALL_PROPS,
attributeNodes = {
#NamedAttributeNode(value = "lines", subgraph = "subgraph.alternatives"),
#NamedAttributeNode("delivery")
},
subgraphs = {
#NamedSubgraph(
name = "subgraph.alternatives",
attributeNodes = #NamedAttributeNode(value = "alternatives")
)
}
)
})
public class CustomerOrderEntity extends Auditable implements Serializable {
private static final long serialVersionUID = 1L;
public static final String GRAPH_WITH_LINES = "graph.CustomerOrderEntity.lines";
public static final String GRAPH_WITH_DELIVERY = "graph.CustomerOrderEntity.delivery";
public static final String GRAPH_WITH_ALL_PROPS = "graph.CustomerOrderEntity.all";
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "hash_generator")
#GenericGenerator(
name = "hash_generator",
strategy = "com.persistence.generator.HashSequenceGenerator",
parameters = {
#org.hibernate.annotations.Parameter(name = HashSequenceGenerator.EXTRACT_FIELDS_HASHING, value = "tenantId,fulfilLocationId,fulfilOrderId"),
#org.hibernate.annotations.Parameter(name = HashSequenceGenerator.EXTRACT_FIELDS_FORMAT, value = HashSequenceGenerator.EXTRACT_FIELDS_FORMAT_HEX_VALUE)
}
)
#Column(name = "cust_order_key", nullable = false)
private String custOrderKey;
#Column(name = "tenant_id")
private Integer tenantId;
#Column(name = "fulfil_location_id")
private Integer fulfilLocationId;
#Column(name = "fulfil_order_id")
private String fulfilOrderId;
#OneToMany(
targetEntity = CustomerOrderLineEntity.class,
mappedBy = "order",
fetch = FetchType.LAZY
)
#OrderColumn(name = "fulfil_order_line_id")
private List<CustomerOrderLineEntity> lines;
#OneToOne(
targetEntity = CustomerDeliveryEntity.class,
mappedBy = "order",
fetch = FetchType.LAZY
)
private CustomerDeliveryEntity delivery;
}
#Entity
#Getter
#Setter
#Builder
#NoArgsConstructor
#AllArgsConstructor
#Accessors(chain = true)
#Table(name = "cust_order_line")
#ToString(onlyExplicitlyIncluded = true)
#EqualsAndHashCode(onlyExplicitlyIncluded = true, callSuper = true)
public class CustomerOrderLineEntity extends Auditable implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "hash_generator")
#GenericGenerator(
name = "hash_generator",
strategy = "com.persistence.generator.HashSequenceGenerator",
parameters = {
#org.hibernate.annotations.Parameter(name = HashSequenceGenerator.EXTRACT_FIELDS_HASHING, value = "tenantId,fulfilLocationId,fulfilOrderId,fulfilOrderLineId"),
#org.hibernate.annotations.Parameter(name = HashSequenceGenerator.EXTRACT_FIELDS_FORMAT, value = HashSequenceGenerator.EXTRACT_FIELDS_FORMAT_HEX_VALUE)
}
)
#Column(name = "cust_order_line_key", nullable = false)
#ToString.Include
#EqualsAndHashCode.Include
private String custOrderLineKey;
#Column(name = "tenant_id")
#ToString.Include
#EqualsAndHashCode.Include
private Integer tenantId;
#Column(name = "fulfil_location_id")
#ToString.Include
#EqualsAndHashCode.Include
private Integer fulfilLocationId;
#Column(name = "fulfil_order_id")
#ToString.Include
#EqualsAndHashCode.Include
private String fulfilOrderId;
#Column(name = "fulfil_order_line_id")
#ToString.Include
#EqualsAndHashCode.Include
private Integer fulfilOrderLineId;
#ManyToOne(
targetEntity = CustomerOrderEntity.class,
fetch = FetchType.LAZY
)
#JoinColumns({
#JoinColumn(name = "tenant_id", referencedColumnName = "tenant_id", updatable = false, insertable = false),
#JoinColumn(name = "fulfil_location_id", referencedColumnName = "fulfil_location_id", updatable = false, insertable = false),
#JoinColumn(name = "fulfil_order_id", referencedColumnName = "fulfil_order_id", updatable = false, insertable = false)
})
private CustomerOrderEntity order;
#OneToMany(
targetEntity = CustomerOrderLineProdAltEntity.class,
mappedBy = "line",
fetch = FetchType.LAZY
)
private List<CustomerOrderLineProdAltEntity> alternatives;
}
#Entity
#Getter
#Setter
#Builder
#NoArgsConstructor
#AllArgsConstructor
#Accessors(chain = true)
#Table(name = "order_line_prod_alt")
#ToString(callSuper = true, onlyExplicitlyIncluded = true)
#EqualsAndHashCode(callSuper = true, onlyExplicitlyIncluded = true)
public class CustomerOrderLineProdAltEntity extends Auditable implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "order_line_prod_alt_key", nullable = false)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "hash_generator")
#GenericGenerator(
name = "hash_generator",
strategy = "com.persistence.generator.HashSequenceGenerator",
parameters = {
#org.hibernate.annotations.Parameter(name = HashSequenceGenerator.EXTRACT_FIELDS_HASHING, value = "tenantId,fulfilLocationId,fulfilOrderId,fulfilOrderLineId,altGtin"),
#org.hibernate.annotations.Parameter(name = HashSequenceGenerator.EXTRACT_FIELDS_FORMAT, value = HashSequenceGenerator.EXTRACT_FIELDS_FORMAT_HEX_VALUE)
}
)
#ToString.Include
#EqualsAndHashCode.Include
private String orderLineProdAltKey;
#Column(name = "tenant_id")
#ToString.Include
#EqualsAndHashCode.Include
private Integer tenantId;
#Column(name = "fulfil_location_id")
#ToString.Include
#EqualsAndHashCode.Include
private Integer fulfilLocationId;
#Column(name = "fulfil_order_id")
#ToString.Include
#EqualsAndHashCode.Include
private String fulfilOrderId;
#Column(name = "fulfil_order_line_id")
#ToString.Include
#EqualsAndHashCode.Include
private Integer fulfilOrderLineId;
#ManyToOne(
targetEntity = CustomerOrderLineEntity.class,
fetch = FetchType.LAZY
)
#JoinColumns({
#JoinColumn(name = "tenant_id", referencedColumnName = "tenant_id", updatable = false, insertable = false),
#JoinColumn(name = "fulfil_location_id", referencedColumnName = "fulfil_location_id", updatable = false, insertable = false),
#JoinColumn(name = "fulfil_order_id", referencedColumnName = "fulfil_order_id", updatable = false, insertable = false),
#JoinColumn(name = "fulfil_order_line_id", referencedColumnName = "fulfil_order_line_id", updatable = false, insertable = false)
})
private CustomerOrderLineEntity line;
}
#Getter
#Setter
#Builder
#NoArgsConstructor
#AllArgsConstructor
#Entity
#Accessors(chain = true)
#Table(name = "cust_delivery")
#EqualsAndHashCode(callSuper = true, onlyExplicitlyIncluded = true)
public class CustomerDeliveryEntity extends Auditable implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "hash_generator")
#GenericGenerator(
name = "hash_generator",
strategy = "com.persistence.generator.HashSequenceGenerator",
parameters = {
#org.hibernate.annotations.Parameter(name = HashSequenceGenerator.EXTRACT_FIELDS_HASHING, value = "tenantId,fulfilLocationId,fulfilOrderId"),
#org.hibernate.annotations.Parameter(name = HashSequenceGenerator.EXTRACT_FIELDS_FORMAT, value = HashSequenceGenerator.EXTRACT_FIELDS_FORMAT_HEX_VALUE)
}
)
#Column(name = "cust_delivery_key", nullable = false)
private String custDeliveryKey;
#Column(name = "tenant_id")
private Integer tenantId;
#Column(name = "fulfil_location_id")
private Integer fulfilLocationId;
#Column(name = "fulfil_order_id")
private String fulfilOrderId;
#OneToOne(
targetEntity = CustomerOrderEntity.class,
fetch = FetchType.LAZY
)
#JoinColumns({
#JoinColumn(name = "tenant_id", referencedColumnName = "tenant_id", updatable = false, insertable = false),
#JoinColumn(name = "fulfil_location_id", referencedColumnName = "fulfil_location_id", updatable = false, insertable = false),
#JoinColumn(name = "fulfil_order_id", referencedColumnName = "fulfil_order_id", updatable = false, insertable = false)
})
private CustomerOrderEntity order;
}
with the next spring boot repository
#Repository
public interface CustomerOrderEntityRepository extends JpaRepository<CustomerOrderEntity, String>, JpaSpecificationExecutor<CustomerOrderEntity> {
#EntityGraph(CustomerOrderEntity.GRAPH_WITH_LINES)
#Query("select entity from CustomerOrderEntity entity where entity.tenantId = :#{#param.tenantId} and entity.fulfilLocationId = :#{#param.fulfilLocationId} and entity.fulfilOrderId = :#{#param.fulfilOrderId}")
Optional<CustomerOrderEntity> findOneByOrderIdWithLines(CustomerOrderEntity param);
#EntityGraph(CustomerOrderEntity.GRAPH_WITH_DELIVERY)
#Query("select entity from CustomerOrderEntity entity where entity.tenantId = :#{#param.tenantId} and entity.fulfilLocationId = :#{#param.fulfilLocationId} and entity.fulfilOrderId = :#{#param.fulfilOrderId}")
Optional<CustomerOrderEntity> findOneByOrderIdWithDelivery(CustomerOrderEntity param);
#EntityGraph(CustomerOrderEntity.GRAPH_WITH_ALL_PROPS)
#Query("select entity from CustomerOrderEntity entity where entity.tenantId = :#{#param.tenantId} and entity.fulfilLocationId = :#{#param.fulfilLocationId} and entity.fulfilOrderId = :#{#param.fulfilOrderId}")
Optional<CustomerOrderEntity> findOneByOrderIdWithAllProps(CustomerOrderEntity param);
}
and the next test:
TestCase
And when I try to retrieve a CustomerOrderEntity from the repository it gives the next error trace:
Stacktrace
I think you need to add getters and setters for the properties of your domain objects. You might start by adding a getter and a setter for CustomerOrderEntity.tenantId to see if that changes the behaviour when you try to reproduce this issue.
How to copy entity with multiple #OneToMany?
I have entities:
Profile.java
#Getter
#Setter
#ToString
#JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
#EqualsAndHashCode(exclude = {"id"})
#Entity
#Table(name = "profile")
public class Profile implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false)
private Long id;
#OneToMany(fetch = FetchType.EAGER, mappedBy = "profile", cascade = CascadeType.ALL, orphanRemoval = true)
private List<ProfileDoc> documents = new ArrayList<>();
#OneToMany(mappedBy = "profile", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Contact> contacts = new ArrayList<>();
#OneToOne(mappedBy = "profileAddress", cascade = CascadeType.ALL, orphanRemoval = true)
private AddressBirth birthPlace;
}
ProfileDoc
#Getter
#Setter
#JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
#ToString(exclude = "profile")
#EqualsAndHashCode(exclude = {"id", "profile"})
#TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
#Entity
#Table(name = "profile_doc")
public class ProfileDoc implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false)
private Long id;
#Column(name = "doc_code")
private String documentCode;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name="profile_id")
private Profile profile;
#OneToMany(mappedBy = "document", cascade = CascadeType.ALL, orphanRemoval = true)
private List<DocFile> files = new ArrayList<>();
}
How to copy Profile(all field) without id?
as I understand it, you need to copy documents without profile_id in ProfileDoc class
UPD:
I want copy entity from another entity(copy) for save to DB
BeanUtils.copyProperties(profile, newProfile);
if I copy with Id, then the original entity will update, not a new one
I did googled a lot, still dont find any solution hence posting a question here..
I am developing Many-To-Many relationship example using lombok. I just want to create argument constructor for only two fields out of four. How we can do that ?
#Data
#Entity
#Table(name = "stock")
public class Stock implements Serializable{
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "STOCK_ID", unique = true, nullable = false)
private Integer stockId;
#Column(name = "STOCK_CODE", unique = true, nullable = false, length = 10)
private String stockCode;
#Column(name = "STOCK_NAME", unique = true, nullable = false, length = 20)
private String stockName;
#ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinTable(name = "stock_category", joinColumns = {
#JoinColumn(name = "STOCK_ID", nullable = false, updatable = false)},
inverseJoinColumns = {#JoinColumn(name = "CATEGORY_ID", nullable = false, updatable = false)})
private Set<Category> categories = new HashSet<Category>(0);
}
Category
#Data
#RequiredArgsConstructor(staticName = "of")
#Entity
#Table(name = "category")
public class Category {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "CATEGORY_ID", unique = true, nullable = false)
private Integer categoryId;
#Column(name = "NAME", nullable = false, length = 10)
#NonNull
private String name;
#Column(name = "[DESC]", nullable = false)
#NonNull
private String desc;
#ManyToMany(fetch = FetchType.LAZY, mappedBy = "categories")
private Set<Stock> stocks = new HashSet<Stock>(0);
}
App.java
Why cant I set the limitted field constructor
public class App {
public static void main(String[] args) {
System.out.println("Hello World!");
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
Stock stock = new Stock();
stock.setStockCode("7052");
stock.setStockName("PADINI");
Category category1 = new Category("CONSUMER", "CONSUMER COMPANY");
Category category2 = new Category("INVESTMENT", "INVESTMENT COMPANY");
Set<Category> categories = new HashSet<Category>();
categories.add(category1);
categories.add(category2);
stock.setCategories(categories);
session.save(stock);
session.getTransaction().commit();
System.out.println("Done");
}
}
The reason is that
If staticName set, the generated constructor will be private, and an additional
static 'constructor' is generated with the same argument list that
wraps the real constructor.
Please, don't forget about #NoArgsConstructor because Hibernate needs it.