Could not able to delete collection rows in JPA while calling save() - spring

I have this below entity classes.
Parent Entity:
---------------
public class MLW implements Serializable {
#Id
#Column(name = "mlwId", updatable = false, nullable = false)
private String mlwId;
#OneToOne(optional = false, fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumn(name="mlwId")
private MLWJob mlwJob;
private Date createdDate;
private Date lastUpdatedDate;
}
public class MLWJob implements Serializable {
#Id
private String mlwId;
#Column(name = "Id")
#OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumn(name="mlwId")
private List<MLWJobItem> items;
}
public class MLWJobItem implements Serializable {
#Id
private String itemId;
#OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumn(name="itemId")
private List<MLWJobItemExtension> mlwJobItemExtensions;
}
public class MLWJobItemExtension implements Serializable {
#Id
private String extnId;
#Id
private String itemId;
private String name;
private String value;
}
Repository class:
------------------
public interface MLWRepository extends JpaRepository<MLW, String> {
}
When I try to call save method using above repository I am getting below exception. Could someone help me to understand and fix this issue? TIA
could not delete collection rows:
[com.cpc.wgln.entity.MLWJobItem.mlwJobItemExtensions#0105021001713441];
nested exception is org.hibernate.exception.GenericJDBCException:
could not delete collection rows:
[com.cpc.wgln.entity.MLWJobItem.mlwJobItemExtensions#0105021001713441]

Related

Spring Data Projection with OneToMany error

I have a entity call Circuit.
#Entity
public class Circuit implements Comparable<Circuit>, Serializable {
#Column
private String id;
#OneToMany(mappedBy = "circuit", cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
private Set<Step> workflow = new HashSet<>();
...
}
I have a class called CircuitLight
public class CircuitLight {
private String id;
private Set<Step> workflow;
/* constructor, getters and setters */
}
In my CircuitRepository, i'm trying to make a projection
#Transactional(readOnly = true)
#Query("select new com.docapost.circuit.CircuitLight(c.id, c.workflow) from Circuit c where c.account.siren = :siren")
Set<CircuitLight> findAllByAccountSirenProjection(#Param("siren") String siren);
When i execute, i have a error message:
could not extract ResultSet; SQL [n/a] com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'circuit0_.id' in 'on clause'
I try with other entity. Every time i have a property with a relation #OneToMany, i have the issue...
Is it possible to make a projection with class (Without use a interface) when there are a relation OneToMany ?
UPDATE:
Step.class
#Entity
public class Step implements Comparable<Step>, Serializable {
private static final List<String> INDEXABLE_PROCESSES = Arrays.asList(
ParapheurWorkflowModel.SERVER,
ParapheurWorkflowModel.SIGN,
ParapheurWorkflowModel.VISA
);
#Id
#GeneratedValue
#Expose
#SerializedName("step_id")
public long id;
#ManyToOne
public Circuit circuit;
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(joinColumns = #JoinColumn(name = "step_id"), inverseJoinColumns = #JoinColumn(name = "technicalGroup_id"))
private List<TechnicalGroup> technicalGroups = new ArrayList<>();
#Column(name = "step_type", nullable = false)
#Expose
#SerializedName("subprocess_ref")
public String type;
#Column(nullable = false)
public int orderIndex;
/* contructor, getters and setters */
}
UPDATE 2:
Hum.... My bad, in my circuit class, i have a EmbeddedId
#EmbeddedId
private CircuitPK key;
#Embeddable
public static class CircuitPK implements Serializable {
public String id;
public String siren;
}
I try with this code in Step.class
#ManyToOne
#JoinColumns(value = {
#JoinColumn(name = "circuit_siren", referencedColumnName = "siren"),
#JoinColumn(name = "circuit_id", referencedColumnName = "id")
})
public Circuit circuit;
The result is the same
Write the following code in the Step entity
#ManyToOne
#JoinColumn(name="id", nullable=false)
private Circuit circuit;

OneToOne CascadeType in spring data jpa

I use OneToOne in the spring data JPA and I want to delete a record from the Address table without touching the user. But I can't.
If I remove User, in this case Address is removed, that's good.
But how can you delete an Address without touching the User?
https://github.com/myTestPercon/TestCascade
User.Java
#Entity
#Table(name = "user", schema = "testCascade")
public class User implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Column(name = "name")
private String name;
#OneToOne(mappedBy = "user", cascade = CascadeType.ALL)
private Address address;
// Getter and Setter ...
}
Address.java
#Entity
#Table(name = "address", schema = "testCascade")
public class Address implements Serializable {
#Id
private Long id;
#Column(name = "city")
private String city;
#OneToOne
#MapsId
#JoinColumn(name = "id")
private User user;
// Getter and Setter ...
}
DeleteController.java
#Controller
public class DeleteController {
#Autowired
ServiceJpa serviceJpa;
#GetMapping(value = "/deleteAddressById")
public String deleteAddressById () {
serviceJpa.deleteAddressById(4L);
return "redirect:/home";
}
}
You got your mapping wrong thats all is the problem .
try the below and see
User.java
#Entity
#Table(name = "user", schema = "testCascade")
public class User implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Column(name = "name")
private String name;
#OneToOne(cascade=CascadeType.ALL)
#JoinColumn(name="foriegn key column in user table for address example.. address_id")
private Address address;
// Getter and Setter ...
}
Address.java
#Entity
#Table(name = "address", schema = "testCascade")
public class Address implements Serializable {
#Id
private Long id;
#Column(name = "city")
private String city;
//name of the address variable in your user class
#OneToOne(mappedBy="address",
cascade={CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST,
CascadeType.REFRESH})
private User user;
// Getter and Setter ...
}
In order to solve this problem, you need to read the hibernate Documentation Hibernate Example 162, Example 163, Example 164.
And also I recommend to look at this is Using #PrimaryKeyJoinColumn annotation in spring data jpa
This helped me in solving this problem.
And also you need to specify the parameter orphanRemoval = true
User.java
#Entity(name = "User")
#Table(name = "user", schema = "testother")
public class User implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Column(name = "name")
private String name;
#OneToOne(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
private Address address;
public void addAddress(Address address) {
address.setUser( this );
this.address = address;
}
public void removeAddress() {
if ( address != null ) {
address.setUser( null );
this.address = null;
}
}
// Getter and Setter
}
Address.java
#Entity(name = "Address")
#Table(name = "address", schema = "testother")
public class Address implements Serializable {
#Id
private Long id;
#Column(name = "city")
private String city;
#OneToOne
#MapsId
#JoinColumn(name = "id")
private User user;
// Getter and Setter
}
DeleteController .java
#Controller
public class DeleteController {
#Autowired
ServiceJpa serviceJpa;
#GetMapping(value = "/deleteUser")
public String deleteUser () {
User user = serviceJpa.findUserById(2L).get();
user.removeAddress();
serviceJpa.saveUser(user);
return "/deleteUser";
}
}
Or make a custom SQL query.
#Repository
public interface DeleteAddress extends JpaRepository<Address, Long> {
#Modifying
#Query("delete from Address b where b.id=:id")
void deleteBooks(#Param("id") Long id);
}
public class Address {
#Id
private Long id;
#MapsId
#JoinColumn(name = "id")
private User user;
}
Rename #JoinColumn(name = "id") to #JoinColumn(name = "user_id")
You can't say that the column that will point to user will be the id of the Address

Spring data jpa CRUDRepository/ JPArepository saveall can not get id (non primary key)

I am fetching data from FB marketing API and trying to save in DB. I am able to save data in the DB using CrudRepository or JpaRepository -> saveall method, but when trying to fetch the id in response of saveall, I am getting id as null. When I see in the h2-console, able to see the auto increment value after the completion of transaction.
Note: id is not used as primary key #Id. accountId is used as primary key.
Model:
#Entity
#Table(name = "accounts")
#Data
#ToString(onlyExplicitlyIncluded = true)
public class Account implements Serializable{
#JsonIgnore
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(columnDefinition = "integer auto_increment",insertable = false)
private Long id;
#JsonProperty("account_id")
#Column(name = "account_id")
#Id
private String accountId;
#Column(name = "account_status")
private int accountStatus;
#JsonProperty("timezone_id")
#Column(name = "timezone_id")
private int timezoneId;
private int timezoneOffsetUtc;
private String currency;
#Column(name = "timezone_name")
#JsonProperty("timezone_name")
private String timezoneName;
private String name;
#Column(name = "created_on",nullable = false, updatable = false)
#CreationTimestamp
private LocalDateTime createdOn;
#Column(name = "updated_on")
#UpdateTimestamp
private LocalDateTime updatedOn;
}
Repository:
#Repository()
public interface AccountRepository extends CrudRepository<Account, String> {
}
Tried with JpaRepository<Account, Long> too and flush after saving..but still getting id null in return list response of saveall()
Service:
#Service
public class AccountsService {
#Autowired
private AccountRepository repository;
#Override
#Transactional
public List<Account> saveAll(List<Account> accounts) {
//in case of JpaRepository
List<Account> savedAccounts= repository.saveAll(accounts);
repository.flush();
return savedAccounts;
//in case of CrudRepository
return (List<Account>)repository.saveAll(accounts);
}
}
when executing this
//accountsList received from FB API
List<Account> savedList=iAccountsService.saveAll(accountsList);
savedList.get(0).getId() **//this is coming as null**
Any sort of help is appreciated.
In your entity class :
Use this #GeneratedValue(strategy = GenerationType.IDENTITY)
public class Account implements Serializable{
#JsonIgnore
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(unique = true, nullable = false, insertable = false, updatable = false)
private Long id;
}

Spring JPA: How to insert data to join many tables with #ManytoMany relationship

I'm starting to learn Spring Java Framework . I created some Enity to join 2 Model like my Database. And now I want to insert to Join Table by JpaRepository. What i have to do?
This is my Code (Please fix help me me if something is not right)
Model Users_RoomId to define Composite Primary Key
#Embeddable
public class Users_RoomId implements Serializable {
private static final long serialVersionUID = 1L;
#Column(name = "ID_room", nullable = false)
private String idRoom;
#Column(name = "user_id", nullable = false)
private int idUser;
}
Model Users_Room to join 2 Model Users and Room
#Entity
#Table(name ="bookroom")
public class Users_Room {
#EmbeddedId
private Users_RoomId usersroomId;
#ManyToOne
#MapsId("idRoom")
private Room room;
#ManyToOne
#MapsId("idUser")
private Users users;
#Column(name = "Bookday")
private String bookday;
Model Users and Room I used annotation #OneToMany
Model Users
#Entity
#Table(name = "users")
public class Users implements Serializable{
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "user_id", nullable = false)
private int id;
#Column(name = "name", nullable = false)
private String name;
#Column(name = "email")
private String email;
#Column(name = "pass")
private String pass;
#Column(name = "role")
private int role;
#OneToMany(mappedBy = "users")
private List<Users_Room> user;
Model Room
#Entity
#Table(name ="room")
public class Room implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "ID_room", nullable = false)
private String id;
#Column(name = "name_room", nullable = false)
private String name;
#Column(name = "Description")
private String describe;
#ManyToOne
#JoinColumn(name = "ID_status")
private Status status;
#Column(name = "room_image")
private String image;
public Room() {
super();
}
#ManyToOne
#JoinColumn(name = "ID_kind")
private KindRoom kind;
#OneToMany(mappedBy = "room")
private List<Users_Room> rooms;
This is my database
So I don't know how to insert a new bookroom with iduser,idroom and bookday with JPA repository.. It'necessary to write Query in JPARepository or We just need to use method save() to insert data
Thanks everyone
I had same problem and solved with following code. I used method save() to insert data. Following code is 'createRoom' method in 'RoomService.java'.
RoomService.java
private final RoomRepository roomRepository;
private final UserRoomRepository userRoomRepository;
private final UserRepository userRepository;
public RoomService(RoomRepository roomRepository, UserRoomRepository userRoomRepository, UserRepository userRepository) {
this.roomRepository = roomRepository;
this.userRoomRepository = userRoomRepository;
this.userRepository = userRepository;
}
#Transactional
public RoomDto createRoom(Long userId, Long chattingUserId) {
Room room = roomRepository.save(new Room());
room.addUserRoom(userRepository.findById(userId).orElseThrow(()->new NoSuchElementException("No User")));
room.addUserRoom(userRepository.findById(chattingUserId).orElseThrow(()->new NoSuchElementException("No User")));
userRoomRepository.save(new UserRoom(userRepository.findById(userId).orElseThrow(()->new NoSuchElementException("No User")),room));
userRoomRepository.save(new UserRoom(userRepository.findById(chattingUserId).orElseThrow(()->new NoSuchElementException("No User")),room));
RoomDto roomDto = RoomDto.of(room);
return roomDto;
}

How to get specific inheritant entity using generic dao and service layer

Working on my spring mvc project I face following issu:
I have UnitAppUser, VStanAppUser and RjuAppUser entity classes which extend User entity. User entity stores some general informations. Rest of inheritant entities stores the references to the particular entities (UnitAppUser has a field Unit type, VStanAppUser has a VStan type so on).
Here is my parent User entity
#Entity
#Inheritance(strategy=InheritanceType.JOINED)
#Table(name="app_user")
public class User implements Serializable {
/**
*
*/
private static final long serialVersionUID = 6628717324563396999L;
#Id #GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
#NotEmpty
#Column(name="SSO_ID", unique=true, nullable=false)
private String ssoId;
#NotEmpty
#Column(name="PASSWORD", nullable=false)
private String password;
#NotEmpty
#Column(name="FIRST_NAME", nullable=false)
private String firstName;
#NotEmpty
#Column(name="LAST_NAME", nullable=false)
private String lastName;
#NotEmpty
#Column(name="EMAIL", nullable=false)
private String email;
}
Here's my child classes:
#Entity
#Table(name = "unit_app_user")
public class UnitAppUser extends User implements Serializable {
#JoinColumn(name = "UNITWORK", referencedColumnName = "ID")
#ManyToOne(optional = false)
private UnitDepart unitdepart;
public UnitDepart getWorkat() {
return unitdepart;
}
public void setWorkat(UnitDepart unitdepart) {
this.unitdepart = unitdepart;
}
}
#Entity
#Table(name="rju_app_user")
public class RjuAppUser extends User implements Serializable{
#JoinColumn(name = "workrju", referencedColumnName = "id")
#ManyToOne(optional = false)
private Rju rju;
public Rju getWorkat() {
return rju;
}
public void setWorkat(Rju rju) {
this.rju = rju;
}
}
and finally my VStan entity:
#Entity
#Table(name="vstan_app_user")
public class VstanAppUser extends User implements Serializable{
#JoinColumn(name = "WORKSTATION", referencedColumnName = "kod")
#ManyToOne(optional = false)
private Vstan vstan;
public Vstan getWorkat() {
return vstan;
}
public void setWorkat(Vstan vstan) {
this.vstan = vstan;
}
}
How to write generic dao and service to get specific entity?
As a result I should have something like this
userService.findBySSOId("somessoId").getWorkat() //should return UnitDepart, Rju or VStan

Resources