I need to create #EqualsAndHashCode by the inner object field. I have two entities WorkPlace and Account.
Shortcode:
***WorkPlace.java***
public class WorkPlace {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToOne(optional = false)
#NotNull
private Account account;
.......................
}
***Account.java***
public class Account {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
...............
}
I want to create EqualsAndHashCode in WorkPlace.class using lombok like:
#EqualsAndHashCode(of = {"id", "account.id"})
When build a project - "account.id" ignored and created EqualsAndHashCode by id field.
Is it possible to do something like this using lombok?
You can add the following method and annotation in Workplace.java to get the desired result:
#EqualsAndHashcode.Include
public Long getAccountId() {
return account.getId();
}
Related
I have two different tables, Pizza and User.
First of all, when I create the first entity from for example the user, ID is 1. After that, when I want to create a Pizza, the ID of it will be 2. They sharing the ID somehow. How can I fix that?
And my other question, I have a third table, named Orders. I managed to ask on Order creating for the valid User and Pizza ID, but I just wanna know, what would be the best solution for it?
I just created the Pizza and User Service object in the Order Controller as well, and refered from there. But I don't know how bad is it.
Thank you for the answers!
#Entity(name = "pizza")
#Table(name = "pizza")
public class Pizza {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#NotNull
private String type;
#Entity(name = "users")
#Table(name = "users")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#NotNull
private String email;
#NotNull
private String address;
#Entity(name = "orders")
#Table(name = "orders")
public class Order {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#NotNull
private int user_id;
#NotNull
private int pizza_id;
#RestController
public class OrderController {
#Autowired
private OrderService orderService;
#Autowired
private UserService userService;
#Autowired
private PizzaService pizzaService;
try to use identity generation type instead of auto:
#GeneratedValue(strategy = GenerationType.IDENTITY)
for your first question I think you should change :
#GeneratedValue(strategy = GenerationType.AUTO)
to
#GeneratedValue(strategy = GenerationType.IDENTITY)
for your second question I think that you have to use relationship annotation between your entities :
like:
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "ID_USER")
Private User user;
I have three Entities i'm modeling and am having issues with the associated annotations. I basically have a class that I intend on returning to the caller, a nested listed of Project's and the Project can contain a nested list of Endpoint's. It's a top-level has-a one-to-many, then the nested one-to-many has two one-to-many's.
I've played with #JoinColumn annotations, i've attempted to put a #ManyToOne on the other side of the OneToMany's (but it doesn't like that it's a Long..). I'm just fairly new and unsure on how to do this. I think the mappedById is the solution, but i'm uncertain.
Main Issue: This code allows me to "save" to the database, but upon retrieval, the list of Project's inside the DownDetectorPackage is empty.
A CascadeType.ALL throws referential integrity errors that I don't completely understand.
#Data
#NoArgsConstructor
#AllArgsConstructor
#Entity
#Builder
public class DownDetectorPackage {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#OneToMany(mappedBy="id",fetch = FetchType.EAGER)
private List<Project> projects;
#Temporal(TemporalType.DATE)
private Date dateJobsLastRan;
#Entity
#Data
#NoArgsConstructor
#AllArgsConstructor
#Builder
public class Project{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String projectName;
#OneToMany(mappedBy="id")
private List<Service> externalDependencies;
#OneToMany(mappedBy="id")
private List<Service> endpoints;
}
#Entity
#Data
#NoArgsConstructor
#AllArgsConstructor
#Builder
public class Service {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String url;
private Boolean endpointIsUp;
private String serviceName;
}
You should be using #JoinColumn instead of mappedBy. MappedBy can be used when you have used #ManyToOne in the other class too, which you haven't.
So your final class should look something like this (this is applicable for the other classes too which you have mentioned) :
public class DownDetectorPackage {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#JoinColumn(name = "downDetectorPackageId")
#OneToMany(fetch = FetchType.EAGER)
private List<Project> projects;
#Temporal(TemporalType.DATE)
private Date dateJobsLastRan;
Also, remember to state the parent object name in #JoinColumn annotation, since it would create a column for that foreign key.
You should mark every join column as JoinColumn denotating the referenced column from the other entity. Then, you are supposed to say which relation type are using this column.
public class Project {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String projectName;
#JoinColumn(referencedColumnName = "id")
#OneToMany(fetch = FetchType.LAZY)
private ExternalDependencyEntity externalDependencies;
#JoinColumn(referencedColumnName = "id")
#OneToMany(fetch = FetchType.LAZY)
private EndpointEntity endpoints;
}
Finally, note that in a relational database, every fk column can takes only 1 value (pk of referenced entity id), so, on your entity, you should mark the data type as the entity you are refering to and no as a collection.
I think this sould solve your problem.
I work with an embedded H2 database in which I use the #OneToMany relationship to relate an entity instance (product) to multiple instances of the other entities (suppliers); it's useful when I have specific suppliers for a particular product.
However now, I want to associate all the suppliers with every single product; I don't want to generate in my supplier table different supplier records for each product, instead I want to have only 5 records (5 suppliers) in my supplier table which are associated to every single product, it few words I want to achieve something like "one to all", is it possible to do it using JPA annotations?
Product entity
#Entity
public class Product {
#Id
private String productCode;
#OneToMany
#JoinColumn(name = "supplier_id", referencedColumnName = "productCode")
private List<Supplier> suppliers;
}
Supplier entity
#Entity
public class Supplier {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private Long id;
private String name;
}
Unidirectional #OneToMany association:
#Entity
public class Product {
#Id
// #Column(name = "id") maybe
// #GeneratedValue maybe
private String productCode;
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) // according to your need
private List<Supplier> suppliers;
...
}
And,
#Entity
public class Supplier {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
...
}
#ManyToOne association:
#Entity
public class Product {
#Id
// #Column(name = "id") maybe
// #GeneratedValue maybe
private String productCode;
...
}
And,
#Entity
public class Supplier {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#ManyToOne
#JoinColumn(name = "product_id", foreignKey = #ForeignKey(name = "PRODUCT_ID_FK"))
private Product product;
private String name;
...
}
I have object with #Id (primary key) and this is some business UIID field and I want another Long technical Id for some reasons but when saving the object I get null from getObjectId field:
#Id
private String id;
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "object_id")
private Long objectId;
public Long getObjectId() {
return objectId;
}
public void setObjectId(Long objectId) {
this.objectId = objectId;
}
I have this storage class:
interface MyObjectStorage extends JpaRepository<MyObject, String>
And this is how I save it:
final MyObject saved = storage.saveAndFlush(toSave);
saved.objectId is null here..
And in my MySQL db the objectId field is marked not null auto increment..
PS. And I don't want this objectId field to be used by JPA when findById is executed.
Hibernate/JPA isn't able to automatically create a value for your non-id-properties. The #GeneratedValue annotation is only used in conjunction with #Id to create auto-numbers.
The solution (or work-around) suggested in this forum is to create a separate entity with a generated Id, something like this:
#Entity
public class GeneralSequenceNumber {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "object_id")
private Long objectId;
}
#Entity
public class MyEntity {
#Id ..
private Long id;
#OneToOne(...)
private GeneralSequnceNumber myVal;
}
try the following code
#Id must be a type of Integer or Long
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "object_id")
private Long objectId;
private String id;
public Long getObjectId() {
return objectId;
}
public void setObjectId(Long objectId) {
this.objectId = objectId;
}
interface MyObjectStorage extends JpaRepository<MyObject, Long>
#Entity
public class TestPair implements Serializable {
#Id
#GeneratedValue(strategy= GenerationType.AUTO)
private Long id;
#OneToOne(cascade = {CascadeType.ALL})
#JsonProperty("target_Test")
private Test targetTest;
#OneToOne(cascade = {CascadeType.ALL})
#JsonProperty("source_Test")
private Test sourceTest;
...}
#Entity
public class Test {
#Id
#GeneratedValue(strategy= GenerationType.AUTO)
private Long id;
private String name;
private String shortname;
...}
I have a List<TestPair> that i want to persist using spring boot CrudRepository.
TestPair's contain Test's and these Test's are the same along some of the TestPair's.
When i use the saveAll method, it persists the objects but the Test's that are equal it inserts new one's, creating lots of repeating elements in the db.
I've create the equals and hashcode for this classes.
Check the auto generation logic for both the ids. If it is auto incremental then all the created entity will be different hence new entry is getting created every time.
I've found a solution.
Instead of using the crud saveAll for the Hashset, i'm saving one by one.
for(TestPair tPair : TPairs){
testRepository.save(tPair.getSourceTest());
testRepository.save(tPair.getTargetTest());
testPairRepository.save(tPair);
}
And changed the classes to:
#Entity
public class TestPair implements Serializable {
#Id
#GeneratedValue(strategy= GenerationType.AUTO)
private Long id;
#OneToOne(cascade = {CascadeType.MERGE})
#JsonProperty("target_Test")
private Test targetTest;
#OneToOne(cascade = {CascadeType.MERGE})
#JsonProperty("source_Test")
private Test sourceTest;
}
#Entity
public class Test {
private String name;
#Id
private String shortname;
}
This way hibernate merges the objects, not creating new one's. Thank you all!