I have 2 tables, products, and product_photos. I need to insert data to both tables in one transaction.
#Entity
#Table(name = "products", schema = "my_schema")
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Integer id;
...
//getter + setter + constructor
}
#Entity
#Table(name = "product_photos", schema = "my_schema")
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
public class ProductPhoto {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Integer id;
#Column(name = "product_id")
private Integer productId;
...
}
}
Is there a way to retrieve the id of the Product before writing the entity to DB in order to put it on ProductPhoto (column product_id)?
Related
I have two tables defined as follows:
Action
#Entity
#EntityListeners(AuditingEntityListener.class)
#Table(name = "\"action_recipient_log\"")
#Getter
#Setter
public class ActionRecipientLog {
// generated id
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#JsonManagedReference(value = "action_id") #JsonInclude(JsonInclude.Include.NON_NULL)
private Long action_id;
#JsonManagedReference(value = "recipient_id") #JsonInclude(JsonInclude.Include.NON_NULL)
private String recipient_id;
#JsonManagedReference(value = "is_read") #JsonInclude(JsonInclude.Include.NON_NULL)
private boolean is_read;
}
ActionRecipientLog
#Entity
#EntityListeners(AuditingEntityListener.class)
#Table(name = "\"action_recipient_log\"")
#Getter
#Setter
public class ActionRecipientLog {
// generated id
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#JsonManagedReference(value = "action_id") #JsonInclude(JsonInclude.Include.NON_NULL)
private Long action_id;
#JsonManagedReference(value = "recipient_id") #JsonInclude(JsonInclude.Include.NON_NULL)
private String recipient_id;
#JsonManagedReference(value = "is_read") #JsonInclude(JsonInclude.Include.NON_NULL)
private boolean is_read;
}
Inside ActionRepository, I'm trying to fetch the fields from both Action table and ActionRepository:
#Query("SELECT a, b.is_read FROM Action a LEFT JOIN FETCH ActionRecipientLog b " +
"ON b.recipient_id = a.user.id WHERE a.id = b.action_id ORDER BY a.lastModifiedDate DESC")
List<Action> findUnreadActionByUserId(#Param("userId") String userId, Pageable pageable);
But I'm not sure how to do that because current implementation only returns data from Action (because return type is List<Action>). Can anyone help me figure out how I can return data from both Action table and ActionRecipientLog (b.is_read column)?
I'm auto generating entities within the database which works great using:
spring.jpa.hibernate.ddl-auto=update
Now I need an additional attribute within the association table and I can't figure it out without creating an association entity by hand. The current classes listed below generate an association table without the additional attribute.
The tables I need:
persons:
id
search_requests:
id
search_requests_persons:
person_id
search_request_id
study_id
The classes I currently have (simplified):
#NoArgsConstructor
#RequiredArgsConstructor(staticName = "of")
#Getter
#Setter
#Entity
#EqualsAndHashCode
#Table(name = "persons")
public class Person {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#JsonProperty(access = JsonProperty.Access.READ_ONLY)
private Long id;
// The following line is what I would need
// private List<Integer> studyIds;
}
#NoArgsConstructor
#RequiredArgsConstructor(staticName = "of")
#Getter
#Setter
#Entity
#EqualsAndHashCode
#Table(name = "search_requests")
public class SearchRequest {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#JsonProperty(access = JsonProperty.Access.READ_ONLY)
private Long id;
#NonNull
#ManyToMany
private List<Person> persons;
}
I'm using Lombok and Javax Persistence for the annotations.
In order to add additional attributes in your JoinTable, you could manually create your JoinTable entity. e.g:
PersonSearchRequest.java
#Entity
#Table(name = "person_search_request)
#Getter
#Setter
#NoArgsConstructor
public class PersonSearchRequest {
#EmbeddedId
private PersonSearchRequestPK id;
// put your additional attribute here, e.g:
private String attribute1;
private Long attribute2;
#ElementCollection
private List<String> attribute3s;
#Embeddable
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
public static class PersonSearchRequestPK implements Serializable {
#ManyToOne(fetch = FetchType.LAZY)
private Person person;
#ManyToOne(fetch = FetchType.LAZY)
private SearchRequest searchRequest;
}
}
Person.java
#NoArgsConstructor
#RequiredArgsConstructor(staticName = "of")
#Getter
#Setter
#Entity
#EqualsAndHashCode
#Table(name = "persons")
public class Person {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#JsonProperty(access = JsonProperty.Access.READ_ONLY)
private Long id;
#OneToMany(mappedBy = "id.person")
private List<PersonSearchRequest> personSearchRequests;
}
SearchRequest.java
#NoArgsConstructor
#RequiredArgsConstructor(staticName = "of")
#Getter
#Setter
#Entity
#EqualsAndHashCode
#Table(name = "search_requests")
public class SearchRequest {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#JsonProperty(access = JsonProperty.Access.READ_ONLY)
private Long id;
#OneToMany(mappedBy = "id.searchRequest")
private List<PersonSearchRequest> personSearchRequests;
}
I have the following entity 'User' where the field 'companyId' is a foreign key:
#Entity
#Table(name = "Users")
#Getter #Setter #ToString
public class User {
#Id
#GeneratedValue
private long id;
#Column(name = "company_id")
private Long companyId;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "company_id", insertable = false, updatable = false)
private Company company;
The Company entity:
#Entity
#Table(name = "Companies")
#Getter #Setter #ToString
public class Company {
#Id
#GeneratedValue
private long id;
#OneToMany(mappedBy = "company", cascade = CascadeType.REMOVE, fetch = FetchType.LAZY)
private List<User> users;
I removed other irrelevant fields from the classes.
I'm using spring boot data jpa.
My question is how to remove the field 'companyId' and use the company id inside the field 'company' for CRUD functions with the DB.
Simply remove the companyId and make Company writable
#Entity
#Table(name = "Users")
#Getter #Setter #ToString
public class User {
#Id
#GeneratedValue
private long id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "company_id")
private Company company;
#Entity
#Data
#NoArgsConstructor
public class Offer {
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name = "user_id", referencedColumnName = "id")
private User user;
}
#Data
#EqualsAndHashCode
#Entity
#NoArgsConstructor
public class User {
#OneToMany(mappedBy = "user",cascade = CascadeType.ALL,fetch=FetchType.LAZY)
private Set<Offer> offers = new HashSet<Offer>();
}
Please help if the mapping is correct in table User and Offer .user_id column have null values ....:(
I'm not sure if these are only parts of the entities but in order for the entity to have an id, you need to provide it with one and annotate the relevant field as #Id.
I also use #GeneratedValue(strategy = GenerationType.IDENTITY) so each table will get it's own id (generated by Hibernate, you don't provide the id when you save a new entity and not a global id, otherwise let's say you add an Offer, you get id with value x, then add new User you get id with value x+1 and so on...
#Entity
#Data
#NoArgsConstructor
public class Offer {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name = "user_id", referencedColumnName = "id")
private User user;
}
#Data
#EqualsAndHashCode
#Entity
#NoArgsConstructor
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#OneToMany(mappedBy = "user",cascade = CascadeType.ALL,fetch=FetchType.LAZY)
private Set<Offer> offers = new HashSet<Offer>();
}`
Is this possible? Haven't seen much discussion on it.
Sure! It works great from my experience. Here's an example entity:
#Entity
#Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class PingerEntity {
// ID
#Id
#Getter
#Setter
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
// USER
#Getter
#Setter
#ManyToOne(fetch = FetchType.LAZY, optional = false)
private UserEntity user;
// URL
#Getter
#Setter
#Basic(optional = false)
private String url;
/**
* The number of seconds between checks
*/
#Getter
#Setter
#Basic(optional = false)
private int frequency;
#Getter
#Setter
#Basic(optional = false)
#Enumerated(EnumType.STRING)
public MonitorType monitorType;
}
You can use it also with #Data (and it works !)
#Entity
#Data
public class Customer {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String firstName;
private String lastName;
}
I have never tried Lombok with Hibernate but I don't see why it shouldn't work.
Also, take a look here: http://groups.google.com/group/project-lombok/browse_thread/thread/294bd52d9d8695df/7bc6b0f343831af1?lnk=gst&q=hibernate#7bc6b0f343831af1
Also, Lombok project release notes mention Hibernate explicitely.
A simple example; Library.java:
#Data
#NoArgsConstructor // JPA
#Entity
#Table(name = "libraries")
public class Library {
#Id
#GeneratedValue
private Long id;
#OneToMany(cascade = CascadeType.ALL)
#EqualsAndHashCode.Exclude
// This will be included in the json
private List<Book> books = new ArrayList<>();
#JsonIgnore
public void addBook(Book book) {
books.add(book);
book.setLibrary(this);
}
}
And Book.java:
#Data
#NoArgsConstructor // JPA
#Entity
#Table(name = "books")
public class Book {
#Id
#GeneratedValue
private Long id;
#NotBlank
private String title;
#ManyToOne
#JoinColumn(name = "library_id") // Owning side of the relationship
#EqualsAndHashCode.Exclude
#JsonIgnore // Avoid infinite loops
private Library library;
}