Hibernate doesn't change column for new parameters - java

I have a simple object which I want save in DB. But for time it was necessary to change someone parameters. I drop my old table but when I turn on my program - Hibernate still create DB with old columns.
For example:
My old class looked like this :
#Entity
#Table(name = "Tests")
public class Test {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
private String description;
private boolean isFree;
private int status;
private String author;
private String section;
#OneToMany(mappedBy = "qTest", fetch = FetchType.LAZY, cascade = { CascadeType.ALL })
private List<Question> questions;
private String commentToAdmin;
...
and geters-seters
}
In table I have column "status" like INT.
But then I change this class parameter to String. Now my class looks like this:
#Entity
#Table(name = "Tests")
public class Test {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
private String description;
private boolean isFree;
#Column(name = "statusT")
private String status;
private String author;
private String section;
#OneToMany(mappedBy = "qTest", fetch = FetchType.LAZY, cascade = { CascadeType.ALL })
private List<Question> questions;
private String commentToAdmin;
And geters-setters
}
But after drop old table and restart my application column "status" still "INT" and his name "status" (not "statust").
Please help me understand why it's happening

Related

Spring Boot Data JPA detached entity passed to persist on #OneToMany and #OneToOne

Problem
I am trying to store an object in my Postgres database. This consists of the Order.class, (List) OrderDevice.class, and a Department.class.
The important thing is that the OrderDevices are always stored new in the DB, but a Department may already exist.
When I try to save the object to my database using save I get the following error message: (shown below)
I get the error message "detached entity passed to persist: com.niclas.model.OrderDevice" if the department does not exist yet, if the department exists the error message looks like this: "detached entity passed to persist: com.niclas.model.Department".
Solution attempts
This solution cannot be used because I do not use bidirectional mapping.
(I don't want to use a bidirectional mapping because I want to access the departments without an order.)
I also tried to change the Cascade types to MERGE like in this solution
I also tried using #Transactional on the method
I also tried to save the children in the database first and then the parent like this:
departmentRepository.save(order.getDepartment()); orderDeviceRepository.saveAll(order.getDevices()); orderRepository.save(order);
I hope I have described my good enough and I am happy about suggestions for solutions
Error.log
The log can be viewed here. (The formatting did not work here)
Order.class
#Entity
#Table(name = "orders")
public class Order extends AuditModel {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.AUTO) //TODO better config for GenerationType
private long id;
#Column(name = "order_id")
private String orderId;
#Column(name = "department_id")
private long departmentId;
#OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinColumn(name = "department", referencedColumnName = "id")
private Department department;
#JsonProperty("deviceList")
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinColumn(name = "order_id", referencedColumnName = "order_id")
private List<OrderDevice> devices;
#JsonProperty("forename")
#Column(name = "sender_forename")
private String senderForename;
#JsonProperty("surname")
#Column(name = "sender_surname")
private String senderSurname;
#Column(name = "notes", columnDefinition = "TEXT")
private String notes;
#Column(name = "month")
private int month;
#Column(name = "year")
private int year;
public Order() {
}
... Getter/Setters
}
OrderDevice.class
#Entity
#Table(name = "order_devices")
public class OrderDevice extends AuditModel{
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.AUTO) //TODO better config for GenerationType
private long id;
#Column( name = "order_id", insertable = false, updatable = false )
private String orderId;
#Column(name = "device_id")
private long deviceId;
#Column(name = "device_name")
private String deviceName;
#Column(name = "priceName")
private String priceName;
#Column(name = "price")
private double price;
#Column(name = "count")
private int count;
public OrderDevice() {
}
... Getters/Setters
}
Department.class
#Entity
#Table(name = "departments")
public class Department {
//TODO add Form Validation
//TODO better Naming for From Attributes on Frontend and Backend
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.AUTO) //TODO better config for GenerationType
private long id;
#Column(name = "department_name")
private String department;
#Column(name = "contact_person_forename")
private String forename;
#Column(name = "contact_person_surname")
private String surname;
#Column(name = "contact_person_mail")
private String mail;
#Column(name = "street")
private String street;
#Column(name = "house_number")
private String houseNumber;
#Column(name = "location")
private String location;
#Column(name = "postal_code")
private int postalCode;
#Column(name = "country")
private String country;
#Column(name = "auto_send_invoice")
private boolean autoSend;
#Column(name = "registered")
private boolean registered;
public Department() {
}
... Getter/Setters
}
OrderController.class
#Slf4j
#RestController
public class OrderController {
private final DepartmentRepository departmentRepository;
private final OrderRepository orderRepository;
private final OrderDeviceRepository orderDeviceRepository;
public OrderController(OrderRepository orderRepository, DepartmentRepository departmentRepository,
OrderDeviceRepository orderDeviceRepository) {
this.orderRepository = orderRepository;
this.departmentRepository = departmentRepository;
this.orderDeviceRepository = orderDeviceRepository;
}
#PostMapping("/orders/add")
public ResponseEntity<Order> addDepartment(#RequestBody Order order) throws JsonProcessingException {
order.setOrderId(order.generateOrderId());
DateTime dateTime = new DateTime();
order.setMonth(dateTime.getMonthOfYear());
order.setYear(dateTime.getYear());
order.getDevices().forEach(orderDevice -> {
orderDevice.setOrderId(order.getOrderId());
});
//departmentRepository.save(order.getDepartment());
//orderDeviceRepository.saveAll(order.getDevices());
orderRepository.save(order);
return new ResponseEntity<>(order, HttpStatus.CREATED);
}
Update
If the objects are created in this way, no error will occur and the order will be successfully saved in the database.
However, I don't understand why it works this way and not via ObjectMapper. Does anyone know why?
#PostMapping("/orders/add")
public ResponseEntity<Order> addDepartment(#RequestBody JsonNode jsonNode) throws JsonProcessingException {
Order order = new Order();
JsonNode departmentJson = jsonNode.get("department");
Department department;
if ( departmentJson.get("id").canConvertToInt() ) {
department = departmentRepository.findDepartmentById(departmentJson.get("id").asInt());
} else {
department = new Department();
department.setDepartment(departmentJson.get("department").asText());
department.setForename(departmentJson.get("forename").asText());
department.setSurname(departmentJson.get("surname").asText());
department.setMail(departmentJson.get("mail").asText());
department.setStreet(departmentJson.get("street").asText());
department.setHouseNumber(departmentJson.get("houseNumber").asText());
department.setLocation(departmentJson.get("location").asText());
department.setPostalCode(departmentJson.get("postalCode").asInt());
department.setCountry(departmentJson.get("country").asText());
department.setAutoSend(departmentJson.get("autoSend").asBoolean());
department.setRegistered(departmentJson.get("registered").asBoolean());
}
order.setDepartment(department);
order.setOrderId(order.generateOrderId());
order.setDepartmentId(department.getId());
List<OrderDevice> orderDevices = new ArrayList<>();
JsonNode devices = jsonNode.get("deviceList");
for (JsonNode node : devices) {
//TODO replace this mess with objectMapper
if (node.has("count") && node.get("count").asInt() != 0){
OrderDevice device = new OrderDevice();
device.setOrderId(order.getOrderId());
device.setDeviceId(node.get("id").asLong());
device.setDeviceName(node.get("deviceName").asText());
device.setPriceName(node.get("priceName").asText());
device.setPrice(node.get("price").asDouble());
device.setCount(node.get("count").asInt());
orderDevices.add(device);
}
}
order.setDevices(orderDevices);
order.setSenderForename(jsonNode.get("forename").asText());
order.setSenderSurname(jsonNode.get("surname").asText());
order.setNotes(jsonNode.get("notes").asText());
DateTime dateTime = new DateTime();
order.setMonth(dateTime.getMonthOfYear());
order.setYear(dateTime.getYear());
orderRepository.save(order);
return new ResponseEntity<>(order, HttpStatus.CREATED);
}
You can try to use instead of orderRepository.save(order) use orderRespostiory.saveOrUpdate(order).

How get 2 SELECT in 1 query with SPRING DATA

I have 3 entities :
#Entity
#Table(name = "copy")
public class Copy {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column
private Long id;
#Column(name = "format")
private String format;
#Column(name = "status")
private String status;
#ManyToOne
#JoinColumn(name = "book_id")
private Book book;
#ManyToOne
#JoinColumn(name = "library_id")
private Library library;
#Entity
#Table(name = "book")
public class Book implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column
private Long id;
#Column(name = "title")
private String title;
#Column(name = "pub_date")
private Date pubDate;
#Column(name = "page")
private int page;
#Column(name = "synopsis")
private String synopsis;
//TODO Image à gérer
#Column(name = "cover")
private String cover;
#ManyToOne
#JoinColumn(name = "categorie_id")
private Categorie categorie;
#ManyToOne
#JoinColumn(name = "author_id")
private Author author;
#OneToMany(mappedBy = "book")
List<Copy> copyList = new ArrayList<>();
#Entity
#Table(name = "library")
public class Library implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column
private Long id;
#Column(name = "nom")
private String nom;
#Column(name = "adress")
private String adress;
#Column(name = "phone_num")
private String phoneNum;
#Column(name = "email")
private String email;
#OneToMany(mappedBy = "library")
private List<Copy> copyList = new ArrayList<>();
I would like to recover the number of copies of a book according to its format and its libraries. However I cannot figure out how to retrieve a list of copies and the total number depending on the format and its library. How can I do. I wrote this request but I can't get what I want.
My request :
#Query("SELECT DISTINCT c, COUNT(c.format) FROM Copy c WHERE c.book.id = :id")
List<Copy> getCopyById(#Param("id") Long id);
first you need to create class to handel query result (copy,total)
public class CopyWithTotal{
Copy c;
int total;
CopyWithTotal(Copy c, int total){
this.c = c;
this.total = total;
}
}
then you should constratc this class in the query
#Query("SELECT new packgeTo.CopyWithTotal(DISTINCT c, COUNT(c.format)) FROM Copy c WHERE c.book.id = :id group by c")
List<CopyWithTotal> getCopyById(#Param("id") Long id);
whenever you use aggregation function like count all selected column shoud apper in the group by

How can i create only one record with Hibernate JPA Annotation

I have got 3 entity. These are: Tweet,Thread and Media. I am using Hibernate JPA Annotations. When i save one Thread object, it must trigger to tweet and automatically tweet must saved like thread and Tweet's "media" must saved of course.
You can see my entity class as below. Right now i'm working on Tweet beetween Thread. When i use these code, The number of thread is being recorded as much as tweet object. But i want that only one record inside thread.
Process must be like that after saved thread:
add a new record to Thread table. (only one row)
add all tweet to tweet table(all of "threadid" column same because these tweets belong only one thread!)
add all media to media table(all of "tweetid" column same )
Tweet Table:
#Entity
#Table(name = "tbl_tweet")
public class Tweet implements Serializable {
#Id
#GeneratedValue
private long id;
#Column(name = "tweetid")
private String tweetID;
private String parentTweetID;
private String avatar;
private String owner_name;
private String owner_nick;
private String content;
private String sent_time;
private String sent_date;
private String retweet_count;
private String like_count;
private String owner_link;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name="threadid")
private Thread thread;
#OneToMany(mappedBy = "tweet",fetch = FetchType.LAZY,cascade = {CascadeType.PERSIST,CascadeType.MERGE})
private List<Media> mediaURLs;
Thread Table:
#Entity
#Table(name = "tbl_thread")
public class Thread implements Serializable {
#Id
#GeneratedValue
private Long id;
#Column(name = "threadid")
private String threadID;
#Transient
private List<Tweet> listOfTweets;
Media Table:
#Entity
#Table(name = "tbl_media")
public class Media implements Serializable {
#Id
#GeneratedValue
private long id;
private String mediaID;
private String mediaType;
private String mediaUrl;
private String mediaUrlHttps;
private String mediaVideoUrl;
#ManyToOne
#JoinColumn(name = "tweetid")
private Tweet tweet;
My expected and actual results:
http://prntscr.com/mkaul5
I changed that way. Right now it's working good. Long live annotations!
Tweet Table:
#Entity
#Table(name = "tbl_tweet")
public class Tweet implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column(unique = true,nullable = false,name = "tweetID")
private String tweetID;
private String parentTweetID;
private String avatar;
private long owner_id;
private String owner_name;
private String owner_nick;
private String content;
private String sent_time;
private String sent_date;
private String retweet_count;
private String like_count;
#Transient
private String quotedTweetHtml;
#Transient
#JoinColumn(name = "threadid",referencedColumnName = "id")
private Thread thread;
#OneToMany(cascade = CascadeType.PERSIST,fetch = FetchType.EAGER)
#JoinColumn(name = "tweetID")
private List<Media> mediaURLs;
Thread Table:
#Entity
#Table(name = "tbl_thread")
public class Thread implements Serializable {
#Id
#GeneratedValue
private Long id;
#Column(name = "threadid")
private String threadID;
#OneToMany(cascade = CascadeType.PERSIST,fetch = FetchType.EAGER)
#JoinColumn(name = "threadid")
private List<Tweet> listOfTweets;
Media Table:
#Entity
#Table(name = "tbl_media")
public class Media implements Serializable {
#Id
#GeneratedValue
private long id;
private String mediaID;
private String mediaType;
private String mediaUrl;
private String mediaUrlHttps;
private String mediaVideoUrl;
#Transient
#JoinColumn(name = "tweetID")
private Tweet tweet;

JPA many to many relation in Spring Boot app doesn't work

I want to create a many to many relation in my application but it doesen't work.
My first entity:
#Entity
#Table(name = "Person")
public class Person implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Version
private Long version;
private String firstName;
private String lastName;
private String location;
private String email;
private String status;
private String role;
private LocalDateTime createdOn;
private LocalDateTime modifiedOn;
#ManyToMany(mappedBy = "persons")
private Set<Team> teams = new HashSet<Team>();
My second entity:
#Entity
#Table(name = "Team")
public class Team {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Version
private Long version;
private String name;
private String description;
private String city;
private Integer headcount;
private LocalDateTime createdOn;
private LocalDateTime modifiedOn;
#ManyToMany(cascade = CascadeType.MERGE)
#JoinTable(name = "persons_teams",
joinColumns = #JoinColumn(name = "teamId"),
inverseJoinColumns = #JoinColumn(name = "personId"))
private Set<Person> people = new HashSet<>();
I don't know what is wrong but the program doesn't compile.
Please help.
In Person class you have indicated the name of field to be mapped in Team by using name "persons" but the actual field name in Team class is "people".

Hibernate user and friend relationship add other column

I want to make a friend system via hibernate, and I need to check user-friend's corresponding time when this user had related to other.
I hope table columns like following code:
table 1:
int id;
String name;
table 2:
int user_id;
int friend_id;
Date startdate;
POJO code:
public class User {
private int id;
private String name;
private Map<User,Date> friends;
}
I think you need nothing more then JPA. Something like this:
#Entity
#Table(name = "users")
public class User implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column
private String name;
#ElementCollection(fetch = FetchType.EAGER)
#CollectionTable(name = "friendship", joinColumns = #JoinColumn(name = "user_id"))
#MapKeyColumn(name = "friend_id")
#Column(name = "start_date")
private Map<Long, Date> friendshipMap;
... getters/setters ...
}

Categories