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

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;
}

Related

Auto populate created_date, last_modified_date, created_by and last_modified_by in entity : Hibernate with JPA

I am new to Hibernate and JPA. I have several entities, each of which contains following four columns:
1. created_by
2. last_modified_by
3. created_date
4. last_modified_date
I would like these columns to get auto-populated while saving the associated entity.
Two sample entities are as follows:
Entity 1:
#Entity
#Table(name = "my_entity1")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class MyEntity1 implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "name")
private String name;
#Column(name = "created_by")
private String createdBy;
#Column(name = "last_modified_by")
private String lastModifiedBy;
#Column(name = "created_date")
private Instant createdDate;
#Column(name = "last_modified_date")
private String lastModifiedDate;
}
Entity 2:
#Entity
#Table(name = "my_entity2")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class MyEntity2 implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "description")
private String description;
#Column(name = "created_by")
private String createdBy;
#Column(name = "last_modified_by")
private String lastModifiedBy;
#Column(name = "created_date")
private Instant createdDate;
#Column(name = "last_modified_date")
private String lastModifiedDate;
}
In this context, I have gone through following posts: How to autogenerate created or modified timestamp field?, How can you make a created_at column generate the creation date-time automatically like an ID automatically gets created?.
I am getting how to capture the dates fields but I cannot understand how to capture created_by and last_modified_by.
Auditing Author using AuditorAware and Spring Security...
To tell JPA about currently logged in user we will need to provide an
implementation of AuditorAware and override getCurrentAuditor()
method. And inside getCurrentAuditor() we will need to fetch currently
logged in user.
Like this:
public class AuditorAwareImpl implements AuditorAware<String> {
#Override
public String getCurrentAuditor() {
return "TestUser";
// Can use Spring Security to return currently logged in user
// return ((User) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername()
}
}
Now enable jpa auditing by using #EnableJpaAuditing
#Configuration
#EnableJpaAuditing(auditorAwareRef = "auditorAware")
public class JpaConfig {
#Bean
public AuditorAware<String> auditorAware() {
return new AuditorAwareImpl();
}
}
Look at this to get more details....

Join Two Tables without foreign keys in Spring Boot with similar Ids

Here I have two tables; both have IDs as primary keys. I want to know how to join these tables without foreign keys, based on their IDs. What should be the service implementation and what should be in the repository? How to write #Query with JOINS?
#Entity
#Table(name = "procedures")
#JsonIgnoreProperties({ "hibernateLazyInitializer", "handler" })
public class Procedure implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ProcedureId")
private int id;
#Column(name = "ProcedureName")
private String name;
#Column(name = "ProcedureCode")
private String code;
#Column(name = "ProcedureDesc")
private String desc;
// getters and setters
}
#Entity
#Table(name = "cliniciandescriptor")
public class CPTClinicianDescriptor {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "Id")
private int id;
#Column(name = "ConceptId")
private int conceptId;
#Column(name = "CPTCode")
private String cptCode;
#Column(name = "ClinicianDescriptorId")
private int clinicianDescriptorId;
#Column(name = "ClinicianDescriptor")
private String clinicianDescriptor;
// getters and setters
}
You can use the JOIN on syntax like in SQL
For example
select p from Procedure p join CPTClinicianDescriptor c on c.id = p.id;
Read more about that topic here:
https://72.services/how-to-join-two-entities-without-mapped-relationship/
Considering it as One-to-One relation, you can use something like this.
#Entity
#Table(name = "procedures")
#JsonIgnoreProperties({ "hibernateLazyInitializer", "handler" })
public class Procedure implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ProcedureId")
private int id;
#Column(name = "ProcedureName")
private String name;
#Column(name = "ProcedureCode")
private String code;
#OneToOne(optional = false)
#JoinColumn(name = "id", updatable = false, insertable = false)
private CPTClinicianDescriptor descriptor;
#Column(name = "ProcedureDesc")
private String desc;
// getters and setters
}

JPA one to many, fetch children with specific column value

I have two entities in one to many relationship in my spring-data-jpa project.
Parent entity -
#Entity
#Table(name = "code_group")
public class CodeGroup implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
#NaturalId
#Column(nullable = false)
private String entityId;
#OneToMany
#JoinColumn(name = "codeGroupId", referencedColumnName = "entityId")
private List<SystemCode> systemCodes;
// .. getters setters
}
Child entity -
#Entity
#Table(name = "system_code")
public class SystemCode implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
#Column(nullable = false)
private String codeGroupId;
#Column(nullable = false)
#Enumerated(EnumType.STRING)
private ActiveOrInactive status;
// getters and setters
}
status column is of enum type, it can only have Active or Inactive value.
My existing code works fine. It is fetching code group with associated system codes. I want to filter system code with status='Active'. How to do this?
Try like this:
#OneToMany
#JoinColumn(name = "codeGroupId", referencedColumnName = "entityId")
#Where(clause = "status= 'Active'")
private List<SystemCode> systemCodes;
You can create such methods in your repo:
List<CodeGroup> getAllBySystemCodes_Status(ActiveOrInactive status);
default List<CodeGroup> getAllActive() {
return getAllBySystemCodes_Status(ActiveOrInactive.Active);
}
default List<CodeGroup> getAllInactive() {
return getAllBySystemCodes_Status(ActiveOrInactive.Inactive);
}

Customizing HATEOS URI

I have a Spring Boot Data Rest project I'm working on.
Specifically, I have the following dependencies:
dependencies {
compile 'org.springframework.boot:spring-boot-starter-data-jpa:1.1.9.RELEASE'
compile 'org.springframework.boot:spring-boot-starter-data-rest:1.1.9.RELEASE'
compile 'org.springframework.boot:spring-boot-starter-actuator:1.1.9.RELEASE'
}
I have three entities:
#Entity
#Table(name = "prefecture", uniqueConstraints={#UniqueConstraint(columnNames = {"code", "name"})})
public class Prefecture implements Serializable {
private static final long serialVersionUID = -4664664252005282494L;
#Id
#Column(name = "code")
private Integer code;
#Column(name = "name")
private String name;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "prefecture")
private List<City> cities;
...
#Entity
#Table(name = "city", uniqueConstraints = {#UniqueConstraint(columnNames = {"code", "name"})})
public class City implements Serializable {
private static final long serialVersionUID = 1077260811602686775L;
#Id
#Column(name = "code")
private Integer code;
#ManyToOne
#JoinColumn(name = "prefecture_code", referencedColumnName = "code")
private Prefecture prefecture;
#Column(name = "name", unique = true)
private String name;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "city")
private List<TownArea> townAreas;
...
#Entity
#Table(name = "town_area", uniqueConstraints={#UniqueConstraint(columnNames = {"name"})})
public class TownArea implements Serializable {
private static final long serialVersionUID = -4908446167092081914L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Integer id;
#Column(name = "name")
private String name;
#ManyToOne
#JoinColumn(name = "city_code", referencedColumnName = "code")
private City city;
#Column(name = "prefecture_code")
private Integer prefectureCode;
#Column(name = "postal_code")
private String postalCode;
...
And three repositories:
#RepositoryRestResource(collectionResourceRel = "cities", path = "cities")
public interface CityRepository extends PagingAndSortingRepository<City, Integer> {}
#RepositoryRestResource(collectionResourceRel = "prefectures", path = "prefectures")
public interface PrefectureRepository extends PagingAndSortingRepository<Prefecture, Integer> {}
#RepositoryRestResource(collectionResourceRel = "town_areas", path = "town_areas")
public interface TownAreaRepository extends PagingAndSortingRepository<TownArea, Integer> {}
Given this, when I run my application locally I have a set of URLs like this:
http://localhost:8080/prefectures
http://localhost:8080/prefectures/1
http://localhost:8080/prefectures/1/cities
http://localhost:8080/cities/2/townareas
http://localhost:8080/townareas/3
However, I would like to configure the following URLs:
http://localhost:8080/prefectures/1/cities/2/
http://localhost:8080/prefectures/1/cities/2/townareas
http://localhost:8080/prefectures/1/cities/2/townareas/3
Is there a way I can customize the uris to accomplish this?

Hibernate 4 Entity Mapping with Spring

I've got 2 entity classes as follows:
#Entity
#Table(name = "USER_ACCT")
public class UserAccount implements Serializable{
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator="USER_ACCT_ID_SEQ")
#SequenceGenerator(name="USER_ACCT_ID_SEQ", sequenceName="USER_ACCT_ID_SEQ")
#Column(name = "USER_ACCT_ID")
protected Long id;
#Basic(optional = false)
#Column(length = 50, unique = true)
private String username;
#Basic(optional = false)
#Column(length = 128, nullable = false)
private String password;
#ManyToMany(targetEntity = UserPermission.class)
#JoinTable(name = "USER_ACCT_PERM",
joinColumns = #JoinColumn(name = "USER_ACCT_ID"),
inverseJoinColumns = #JoinColumn(name = "USER_PERM_ID", referencedColumnName = "USER_PERM_ID"))
private Set<UserPermission> permissions;
// getters and setters...
}
AND
#Entity
#Table(name = "USER_PERM")
public class UserPermission implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator="USER_PERM_ID_SEQ")
#SequenceGenerator(name="USER_PERM_ID_SEQ", sequenceName="USER_PERM_ID_SEQ")
#Column(name = "USER_PERM_ID")
protected Long id;
#Column(name = "PERM", unique = true, length = 255, nullable = false)
private String authority;
// getters and setters...
}
Now when I create an object of UserAccount and try to save it using the session factory it gives me the following error:
org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.rpm.domain.UserPermission
Shouldn't the UserPermission class be saved by itself??
This is the code that is used to persist:
#Transactional
public void addUser(){
Set<UserPermission> permissions = new HashSet<UserPermission>();
permissions.add(new UserPermission("ROLE_ADMIN"););
sessionFactory.getCurrentSession().save(new UserAccount("admin", "d033e22ae348aeb5660fc2140aec35850c4da997", permissions));
}
Not unless you specify the cascade options.

Resources