spring JPA repository not flushing record to database - spring-boot

I see the response from repository.save() as updated object but same is not getting reflected in database.
I tried using JPArepository also and tried saveandflush method exposed by API but no luck.
Below are the details of code and configuration
Used sql driver with hibernate as middleware.
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=
spring.datasource.url=jdbc:mysql://localhost:3306/ccmBatch?useSSL=false
spring.batch.job.enabled=false
spring.datasource.initialize=false
spring.jpa.open-in-view=false
spring.jpa.hibernate.ddl-auto=create
spring.jpa.generate-ddl=true
spring.jpa.hibernate.use-new-id-generator-mappings=true
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.jpa.hibernate.naming.strategy=org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
POJO :
#Entity(name = "jobtracker")
public class JobTracker implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Column(name = "CCMBATCH")
String lockVal;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
long id;
public JobTracker() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getLockVal() {
return lockVal;
}
public void setLockVal(String lockVal) {
this.lockVal = lockVal;
}
}
Repository :
#Repository
public interface JobTrackerRepository extends CrudRepository<JobTracker, Long>{
}
Caller code :
#Autowired
JobTrackerRepository repsositoy;
#Transactional
public boolean acquireJobExecutionLock() {
LOGGER.info("acquire lock!!!");
String jobExecutionLockValue = new Date().toString();
JobTracker tracker = new JobTracker();
tracker.setLockVal(jobExecutionLockValue);
JobTracker job = repsositoy.save(tracker);
LOGGER.info("lock acquired!!!"+job.id+" "+job.lockVal);
return true;
}
job object used above is printing correct updated values.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>2.4.3</version>
</dependency>
mysql> desc jobtracker;
+----------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+-------+
| id | bigint | NO | PRI | NULL | |
| CCMBATCH | varchar(255) | YES | | NULL | |
+----------+--------------+------+-----+---------+-------+

Related

Composite primary key vs multiple primary keys

Having this entities:
User.java:
#Entity
#NoArgsConstructor
#Getter
#Setter
public class User {
#Id
private int id;
private String username;
#OneToMany(mappedBy = "owner")
#MapKey(name = "friend_id")
private Map<User, Friendship> friends = new HashMap<>();
}
Friendship:
#Entity
#Data
//#IdClass(Friendship.class)
public class Friendship implements Serializable {
#Id
private int owner_id;
#Id
private int friend_id;
private String level;
#ManyToOne
#MapsId("owner_id")
private User owner;
#ManyToOne
#MapsId("friend_id")
private User friend;
}
I though I must have #IdClass or #EmbeddedId if I want to use two or more primary keys. But as shown above, I could ommit either, and just declare two primary keys (this is what I mean it "compiles"). So the question is, why to even bother using either of those annotations and just declare more keys?
generated table:
+-----------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+-------+
| owner_id | int | NO | PRI | NULL | |
| friend_id | int | NO | PRI | NULL | |
| level | varchar(255) | YES | | NULL | |
+-----------+--------------+------+-----+---------+-------+
As it's mentioned in the hibernate documentation:
The restriction that a composite identifier has to be represented by a "primary key class" (e.g. #EmbeddedId or #IdClass) is only JPA-specific.
Hibernate does allow composite identifiers to be defined without a "primary key class" via multiple #Id attributes.
Although the mapping is much simpler than using an #EmbeddedId or an #IdClass, there’s no separation between the entity instance and the actual identifier. To query this entity, an instance of the entity itself must be supplied to the persistence context.
#Entity
public class Friendship implements Serializable {
/*
It's better to use object wrapper classes instead of the corresponding
primitive types. Because, for example, uninitialized Integer is null,
but uninitialized int is 0 that can be a legal id.
*/
#Id
private Integer ownerId;
#Id
private Integer friendId;
public Friendship() {
}
public Friendship(Integer ownerId, Integer friendId) {
this.ownerId = ownerId;
this.friendId = friendId;
}
// ...
}
Friendship friendship = entityManager.find(Friendship.class, new Friendship(ownerId, friendId));

Save creationTimestamp and updatedTime in spring + hibernate

I need to update the postgres DB with createdDate and updatedDate
I tried using approach 1, But it is inserting null values.
When I read about, it seems the #prepersist annotations does not work for session.
So I decided to go with Approach 2 : Hibernate #CreationTimeStamp Annotation, I added hibernate-annotations maven dependency, But #CreationTimeStamp is not resolved and gives compilation error.
Can someone advise me on how I can resolve the issue ?
Approach 1
Entity class annotated with #Entity and #Table
public class Status{
#Id
#Column(name = "run_id")
private int run_id;
#Column(name = "status")
private String status;
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "created_date" , updatable=false)
private Date created;
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "updated_date" , insertable=false)
private Date updated;
#PrePersist
protected void onCreate() {
created = new Date();
}
#PreUpdate
protected void onUpdate() {
updated = new Date();
}
//Getters and setters here
}
implementation class is
sessionFactory.getCurrentSession().save(status);
Approach 2
using #CreationTimeStamp and #updatedTimeStamp. But the maven dependency
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-annotations -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
<version>3.5.0-Final</version>
</dependency>
does not add these annotations to classpath
Is there a reason you are using the session.save() method instead of an entitymanager? I'll post an example of my application using an entitymanager to persist and merge entities. Also I am using java.time.LocalDateTime instead of java.util.Date, that's why I don't need #Temporal.
This may also help: How to use #PrePersist and #PreUpdate on Embeddable with JPA and Hibernate
If you want to use an entitymanager this will help: Guide to the Hibernate EntityManager
Entity class:
public abstract class AbstractEntity implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(updatable = false, nullable = false)
private Long id;
#Column
private LocalDateTime createdTimestamp;
#Column
private LocalDateTime modifiedTimestamp;
#Version
private Long version;
#PrePersist
public void setCreationDateTime() {
this.createdTimestamp = LocalDateTime.now();
}
#PreUpdate
public void setChangeDateTime() {
this.modifiedTimestamp = LocalDateTime.now();
}
//Getter and setter
}
Abstract database service class:
public abstract class AbstractDatabaseService {
#PersistenceContext(name = "examplePU")
protected EntityManager entityManager;
}
Example Entity Repository Interface:
public interface ExampleRepository {
ExampleEntity save(ExampleEntity exampleEntity);
}
Example Entity Repository Implementation:
public class ExampleRepositoryImpl extends AbstractDatabaseService implements ExampleRepository , Serializable {
#Transactional
#Override
public ExampleEntity save(ExampleEntity exampleEntity) {
ExampleEntity toPersist;
// Updating an already existing entity
if (exampleEntity.getId() != null) {
toPersist = entityManager.find(ExampleEntity .class, exampleEntity.getId());
// Omitted merging toPersist with the given exampleEntity through a mapper class here
} else {
toPersist = exampleEntity;
}
try {
toPersist = entityManager.merge(toPersist);
} catch (Exception e) {
// Logging e
}
return toPersist;
}
}
Hope this helps.

Hibernate didn't create one of tables

I'm learning spring..., I build a simple application.
I have a problem because hibernate does not want to generate one of the models..
I do not know what's wrong
import com.fasterxml.jackson.annotation.JsonIgnore;
import javax.persistence.*;
import java.io.Serializable;
#Entity
#Table(name="access_card")
public class AccessCard implements Serializable{
private static final long serialVersionUID = -4015209774835055079L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="id")
private Long id;
#Column(name="key")
private String key;
#Column(name="enabled")
private Boolean enabled;
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "user_id", nullable = false)
#JsonIgnore
private User user;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public Boolean getEnabled() {
return enabled;
}
public void setEnabled(Boolean enabled) {
this.enabled = enabled;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
Other classes are written similarly and everything works.
Error:
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error
executing DDL "create table access_card (id bigint not null, enabled
bit, key varchar(255), user_id bigint not null, primary key (id))
engine=MyISAM" via JDBC Statement
And properties
spring.jpa.hibernate.ddl-auto = update
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
Follow your comment, The problem pointed out at here
key varchar(255)
The table name is reserved keyword.
See https://hibernate.atlassian.net/browse/HHH-4453
If you still want it, the solution is https://vladmihalcea.com/escape-sql-reserved-keywords-jpa-hibernate/

Unable to persist child class records using spring data jpa

Problem
1)I created a class employee that extends Person.I can persist employee records and not person.
Solution I implemented
1)Created modal classes Employee and Person.
Modal Classes
Employee
#Entity
#Table(name = "employee",
indexes = {#Index(name = "username", columnList = "username", unique = true)})
public class BaseEmployee extends Person {
public static final String OBJECT_KEY = "EMPLOYEE";
#Id
#GeneratedValue
private Long id;
// Who created this baseEmployee
private String userId;
// #Indexed(unique = true)
private String username;
#Enumerated(EnumType.STRING)
private ROLE role;
#Enumerated(EnumType.STRING)
private STATUS status;
private String designation;
Person
public class Person extends AbstractEntity {
private String firstName;
private String lastName;
private String contact;
private String email;
#Enumerated(EnumType.STRING)
private GENDER gender;
private String imageId;
private String address;
private String locationId;
private DateTime dob;
private double[] location;
private String pinCode;
Employee Controller
#PostMapping
ApiResponse<BaseEmployee> post(#RequestBody CreateEntry<BaseEmployee> baseEmployeeCreateEntry) {
BaseEmployee baseEmployeeToCreate = baseEmployeeCreateEntry.getEntry();
baseEmployeeToCreate.setStatus(STATUS.ACTIVE);
baseEmployeeToCreate = employeeService.post(baseEmployeeToCreate);
if (baseEmployeeToCreate != null)
authenticationService.setPassword(baseEmployeeToCreate, baseEmployeeCreateEntry.getPassword());
return ApiResponse.success().message("Created Successfully!").object(baseEmployeeToCreate);
}
public class CreateEntry<T> {
private T entry;
private String password;
Service
#Override
public <E extends BaseEmployee> E post(E employee) {
employee = employeeRepository.save(employee);
System.out.println(employee);
LOG.info("Admin data" + employee);
LOG.info("PUT employee {} {} {}", employee.getId(), employee.getFirstName(), employee.getEmail());
return employee;
}
Repository
public interface EmployeeRepository extends JpaRepository<BaseEmployee, Long> {}
#Expected Output
The Employee class Columns and Person class Columns
#Output Shown
mysql> select * from employee;
id | created_at | created_by | last_modified_at | last_modified_by | version | designation | role | status | user_id | username |
1 | 1519624346694 | anonymousUser | 1519624346694 | anonymousUser | 0 | csdcs | ADMIN | ACTIVE | string | admin |
3 | 1519624856504 | anonymousUser | 1519624856504 | anonymousUser | 0 | csdcs | ADMIN | ACTIVE | string | admin1 |
4 | 1519626598478 | anonymousUser | 1519626598478 | anonymousUser | 0 | csdcs | ADMIN | ACTIVE | string | admin2 |
Can anyone guide me what I am doing wrong.Thankx in advance?
Can you try adding #MappedSuperclass to Person entity?

Embeddable with #ManyToOne and AccessType.Property on Id field

I am trying to define a #Embeddable class with a #ManyToOne relationship to another entity. The #OneToMany side has a #Id field annotated with #Access(AccessType.Property). Here is an example code to illustrate:
#Embeddable
class Embeddable {
#ManyToOne
private ClassA classA;
}
#Entity
class ClassA implements Serializable {
#Id
#GeneratedValue
#Access(AccessType.Property)
private Long id;
public Long getId() { return id; }
}
#Entity
class ClassB {
#ElementCollection
private List<Embeddable> embeddables;
}
The problem is that the created table definition for the class Embeddable seems to be wrong. The column for ClassA is of type bytea and is named class_a instead of bigint and class_a_id. Also if i try to persist one dataset the related entity of ClassA is saved serialized as hex..Every other #Entity works as expected. Is this a bug or an error on my part?
Edit:
Table for Embeddable (current state):
| class_b_id | class_a |
| type: int | type: typea |
|:-----------|------------:|
| 123 | A3B4738D.. |
Table for Embeddable (needed state):
| class_b_id | class_a_id |
| type: int | type: int |
|:-----------|------------:|
| 123 | 2 |

Resources