I have a base class for fields that are common in all the models
#Getter
#Setter
public class BaseModel {
#Id
private String id;
#CreatedDate
private Date createdAt;
#LastModifiedDate
private Date modifiedAt;
#Version
private Long version;
}
and other models are inheriting this class, for eg
#Document(collection = "accounts")
#Getter
#Setter
#ToString
public class Account extends BaseModel {
#Indexed(unique = true)
private String name;
}
When I persist account object then i can see createdAt and modifiedAt getting persisted, but when i query the same account object then I am getting createdAt and modifiedAt as null.
I have enabled mongo auditing also.
I have tried TypeAlias also but not working, any suggestion or help would be appreciated
Related
I have mongodb collection for following documents:
#Builder
#Data
#AllArgsConstructor
#NoArgsConstructor
#Document
public class Account {
#Id
private String id;
#Indexed(unique=true)
private String username;
#Indexed(unique=true)
private String email;
#Indexed(unique=true)
private String contact;
private ConfirmationTokenDetails confirmationTokenDetails;
}
#Builder
#Data
#AllArgsConstructor
#NoArgsConstructor
#Document
public class ConfirmationTokenDetails {
#Indexed(unique=true)
private String confirmationToken;
private LocalDateTime createdAt;
private LocalDateTime expiredAt;
}
Basically all what I want is just get Account entity by confirmationToken attribut which stores in nested ConfirmationTokenDetails object. I tried do that by using following method
public interface AccountRepository extends MongoRepository<Account, String> {
Optional<Account> findByConfirmationTokenDetails_ConfirmationToken(String token);
}
but it wasn't working for me.
I'm mapping classes via Hibernate and I need to map multiple ID for Relationship.
All ID's extend from BaseEntity. How can I implement multiple ID mapping for Relationship which contains Foreign Key for User in DataBase ?
Basicly fields userIdOne and userIdTwo in Relationship has to contain user's id which send request.
User extend own ID from BaseEntity.
Each time I run it - get en error:
This class [class com.mylov.springsocialnetwork.model.Relationship]
does not define an IdClass
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#MappedSuperclass
#EqualsAndHashCode
public class BaseEntity implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
}
#Builder
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#EqualsAndHashCode(exclude = {"posts"}, callSuper = false)
#Entity
public class User extends BaseEntity {
private String userName;
private String realName;
private String email;
private String phoneNumber;
private LocalDate birthDate;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "userPosted")
private Set<Post> posts = new HashSet<>();
private String password;
public User(Long id, String userName, String realName, String email, String phoneNumber, LocalDate birthDate,
Set<Post> posts, String password) {
super(id);
this.userName = userName;
this.realName = realName;
this.email = email;
this.phoneNumber = phoneNumber;
this.birthDate = birthDate;
this.posts = posts;
this.password = password;
}
}
#Builder
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#Entity
public class Relationship implements Serializable {
//#Id not working
private Long userIdFrom;
//#Id
private Long userIdTo;
#Enumerated(value = EnumType.STRING)
private RelationshipStatus status;
private LocalDate friendsRequestDate;
}
It appears that you are looking to establish a Relationship between two different users. This would mean that each Relationship is an object/entity of its own and should have its very own #Id (unrelated to user IDs).
The linkage to each User that form part of this Relationship should be mapped as foreign keys instead (probably #ManyToOne and a #JoinColumn).
For example:
#Entity
public class Relationship implements Serializable {
#Id
private Long relationshipId;
#ManyToOne(...)
#ForeignKey(name="FK_USER_ONE") //for generation only, it isn't strictly required
#JoinColumn(name="from")
private Long userIdFrom;
#ManyToOne(...)
#ForeignKey(name="FK_USER_TWO") //for generation only, it isn't strictly required
#JoinColumn(name="to")
private Long userIdTo;
#Enumerated(value = EnumType.STRING)
private RelationshipStatus status;
private LocalDate friendsRequestDate;
}
Edit:
It isn't required to specify the #ForeignKey annotations. They will be used if the database tables are generated automatically (ok for testing, but usually not something you'll want in production) and will create the FOREIGN KEY constraint on the table accordingly, but JPA mapping will work fine without it, because it takes the relationships from your defined model, not from the database itself.
I have Spring MVC + JPA applications.
I have several entities in application which Are constantly changing. I want to be able to audit this changes. I found that there is an #Audited annotation that track changes to certain fields or whole Entity. I want to know if there any way to configure this track options - I want to be able to track what was changed and who changed it.Also is it possible to have changes from several Entities in 1 Table in SQL? Also is it possible to track changes of - #OneToMany Fields in Entity?
Thanks
Yes, you can keep track the changes made, updated user and time-stamp.
Hibernate provides #Audited annotation to maintain entity version.
Spring provides #CreatedBy #LastModifiedBy #CreatedDate and #LastModifiedDate annotations, among these you need to provide the user name who updates using AuditorAware bean.
To enable auditing,
should add #EnableJpaAuditing on configuration class
#Audited and #EntityListeners(AuditingEntityListener.class) on entities
AuditorAware<T> to provide the username
Children entities should be annotated with #Audited
Example
#Bean
public AuditorAware<String> createAuditorProvider() {
return () -> "username"; // should be from context/session
}
For each entities an additional table will be created to maintain version
{ENTITY_NAME}_AUD // can override the prefix and suffix of audit table name
REVINFO
below is an example of one-to-many relationship with hibernate and spring auditing
UserInfo.java
#Audited
#Entity
#EntityListeners(AuditingEntityListener.class)
public class UserInfo extends AuditInfo {
#Id
#GeneratedValue
private Long id;
#Column
private String name;
#OneToMany(mappedBy = "userInfo", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private List<UserAddress> addresses;
}
UserAddress.java
#Entity
#Audited
#EntityListeners(AuditingEntityListener.class)
public class UserAddress extends AuditInfo {
#Id
#GeneratedValue
private Long addressId;
#ManyToOne
#JoinColumn(name = "id", nullable = false)
private UserInfo userInfo;
#Column
private Long no;
#Column
private String street;
}
AuditInfo.java
#EntityListeners(AuditingEntityListener.class)
#MappedSuperclass
public abstract class AuditInfo {
#CreatedBy
private String createdBy;
#LastModifiedBy
private String updatedBy;
#CreatedDate
private LocalDateTime createdOn;
#LastModifiedDate
private LocalDateTime updatedOn;
}
I know this question have been asked several times but, they didn't help me.
I have the following test:
public class PlantCatalogTests {
#Autowired
PlantInventoryEntryRepository plantRepo;
#Test
public void queryPlantCatalog() {
assertThat(plantRepo.count(), is(14l));
}
and here is PlantInventoryEntryRepository
#Repository
public interface PlantInventoryEntryRepository extends JpaRepository<PlantInventoryEntry, Long> {}
As you see, this repository is based on the class PlantInventoryEntry
#Entity
#Data
public class PlantInventoryEntry {
#Id
#GeneratedValue
Long id;
#OneToOne
PurchaseOrder plant_id;
String name;
String description;
String price;
}
PurchaseOrder is another class, which i have one instance of it as an attribute in my PlantInventoryEntry class:
#Entity
#Data
public class PurchaseOrder {
#Id
#GeneratedValue
Long id;
List<PlantReservation> reservations;
PlantInventoryEntry plant;
LocalDate issueDate;
LocalDate paymentSchedule;
#Column(precision=8,scale=2)
BigDecimal total;
#Enumerated(EnumType.STRING)
POStatus status;
LocalDate startDate;
LocalDate endDate;
}
My main problem is that, when i run my test, i face with this error:
org.hibernate.MappingException: Could not determine type for: com.example.models.PlantInventoryEntry, at table: purchase_order, for columns: [org.hibernate.mapping.Column(plant)
How can i fix the error??
You need to identify the relationship by using a #ManyToOne or #OneToOne annotation on PlantInventoryEntry in PurchaseOrder, depending on what the actual relationship is between the entities.
Edit: You most likely need to identify the relatationship between the List of PlantReservations and PurchaseOrder, or you need to mark it as #Transient if its not managed by JPA.
#Entity
#Data
public class PurchaseOrder {
#Id
#GeneratedValue
Long id;
// You need to set the mappedBy attribute to the field name
// of PurchaseOrder in PlantReservation
// Update: omit mappedBy if PurchaseOrder is not mapped in PlantReservation
#OneToMany(mappedBy="order")
List<PlantReservation> reservations;
#ManyToOne
PlantInventoryEntry plant;
LocalDate issueDate;
LocalDate paymentSchedule;
#Column(precision=8,scale=2)
BigDecimal total;
#Enumerated(EnumType.STRING)
POStatus status;
LocalDate startDate;
LocalDate endDate;
}
I have a problem, that a Date-Type from an #Embeddable-Class will not mapped as a Date-Type in the MySQL-Database. Instead it gets mapped as VARCHAR(255). With normal #Entity-Classes it is working properly.
I am using JPA 2.1 with EclipseLink 2.5.
I have an #Embeddable-Class like this:
#Embeddable
public class AbsencePeriod implements Serializable {
#Getter
#Setter
#Column(name = "\"START\"")
#Temporal(TemporalType.DATE)
private Date start;
#Getter
#Setter
#Column(name = "\"END\"")
#Temporal(TemporalType.DATE)
private Date end;
public AbsencePeriod() {
}
}
I include it at another class like this:
#Entity
public Person extends BaseEntity implements Serializable {
#ElementCollection
#CollectionTable(
name = "_PERSON_ABSENCEPERIODS",
joinColumns = #JoinColumn(name = "PERSON_ID")
)
#Getter
#Setter
private List<AbsencePeriod> absencePeriods;
}
I have also a workaround for this, but I want to know, why the wrong mapping happens. Workaround looks like setting the #ColumnDefinition manual:
#Embeddable
public class AbsencePeriod implements Serializable {
#Getter
#Setter
#Column(name = "\"START\"")
#Basic
#Column(columnDefinition = "TIMESTAMP")
#Temporal(TemporalType.TIMESTAMP)
private Date start;
}