How do I insert data into 2 tables in the same database using Spring Boot Crudrepository? - spring

I want to be able to create a new account for my application. I have an account class which represents one entity and another class that represents personal information of the account. In order to create the new account and have it be in the database I want to add some information into the account table and some information into the PersonalInfo table as detailed in the classes below. How do I do this with a CrudRespository interface. As I understand it, the crudrepository can interact with one table in the database. In my example that would be Accounts. This is fine because most of my checking and communicating will be with the accounts table. But for when I am creating a new account I need to add the data that will be given into two tables. Do I have to make manual queries and add it as a method in there?
#Entity
#Component
public class Account {
#Id
private int accountNum;
private String accountType;
private int accountBalance;
private String accountStatus;
#Entity
#Component
public class PersonalInfo {
#Id
private int accountNum;
private String firstName;
private String lastName;
private String SSN;
private String streetName;
private String city;
private String state;
private String zipcode;
#RepositoryRestResource(collectionResourceRel="accounts",path="accounts")
public interface AccountsDB extends CrudRepository<Account, Integer>{
}

Just create a repository for PersonalInfo and invoke two save() methods (of the two different repositories respectively) with the two created entities respectively.
Just make sure to set the identical ids (accountNum) for these two entities.
Or, you could create a service to do it for you, like so:
public interface AccountAndPersonalInfoService {
void save(Account account, PersonalInfo personalInfo);
}
#Service
public class AccountAndPersonalInfoServiceImpl implements AccountAndPersonalInfoService {
#Autowired
private AccountsDB accountsDB;
#Autowired
private PersonalInfoDB personalInfoDB;
#Override
void save(Account account, PersonalInfo personalInfo) {
if (account.getAccountNum() == personalInfo.getAccountNum()) {
accountsDB.save(account);
personalInfoDB.save(personalInfo);
} else throw new IllegalArgumentException("The ids of the entities do not match.");
}
}

Related

Filter based on Integer Comparison in Spring data redis

I am using spring-data-redis to communicate with database.
I have entity class like below
#RedisHash(value = "employee")
public class Employee
{
#Id
private long id;
#Indexed
private String name;
#Indexed
private int age;
private Address address;
...... ...... ......
}
I want to filter the employees based on age group. For example, age lesser than 35 (age<35). How to achieve this in below repository?
#Repository
public interface EmployeeRepo extends CrudRepository<Employee, Long>
{
public Employee findByName(String name);
}
I dont prefer to load complete data from table and do search using any loop/stream.
I don't think it does. I tried to implement what you tried to do using
#Index
long lastUpdatedOn;
when I checked the redis it gives a key entity:lastUpdatedOn:160.... and I tried searching for it using ZRANGE which gives no results.

How can I access the data from a table in another schema

I have to get data from a table in another schema, which I do have grant permission.
Tried select query from my current database. I am able to acess the table in other schema(USERAUTH)
Entity had created with schema attribute
#Entity
#Table(name="PESRSON", schema=USERAUTH)
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name="CODE")
private Long code;
#Column(name="TITLE")
private String title;
.....
.....
.....
}
Created Repository
#Repository
public interface PersonRepo extends JpaRepository<Person, Long> {
}
In service, to get the record.
#Autowired
private PersonRepo personRepo;
.....
.....
.....
Person per = personRepo.getOne(663L);
Exception on server start.
ERROR ORA-00942: table or view does not exist
How can I access the data from a table in another schema.
I was facing the same problem and after doing a bit of Google I find out below two options. You can use either way to achieve the same.
#Entity
#Table(name="PESRSON", schema="USERAUTH", catalog="USERAUTH")
public class Person implements Serializable { }
or
#Entity
#Table(name="USERAUTH.PESRSON")
public class Person implements Serializable { }

Redis #Reference does not work in Spring Data Redis

I am facing issues while implemeting #Reference in Spring Boot + Spring Data Redis. Address is a List in Employee and when I saved the office and home address and I was expecting the data to be saved with the Employee. But data did not get saved and hence unable to search the Address using street.
Employee.java
#Builder
#Data
#AllArgsConstructor
#NoArgsConstructor
#RedisHash("employees")
public class Employee {
#Id #Indexed
private String id;
private String firstName;
private String lastName;
#Reference
private List<Address> addresses;
}
Address.java
#Builder
#Data
#AllArgsConstructor
#NoArgsConstructor
#RedisHash("address")
public class Address {
#Id
private String id;
#Indexed
private String street;
private String city;
}
Test class
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest
public class EmployeeAdressTest extends RepositoryTestSupport{
#Autowired private EmployeeRepository employeeRepository;
#Before
public void setUp() throws JsonProcessingException {
Address home = Address.builder().street("ABC Street").city("Pune").build();
Address offc = Address.builder().street("XYZ Street").city("Pune").build();
Employee employee1 = Employee.builder().firstName("Raj").lastName("Kumar").addresses(Arrays.asList(home, offc)).build();
employeeRepository.save(employee1);
List<Employee> employees = employeeRepository.findByAddresses_Street("XYZ Street");
System.out.println("EMPLOYEE = "+employees);
}
#Test
public void test() {
}
}
Spring Doc:
8.8. Persisting References
Marking properties with #Reference allows storing a simple key reference instead of copying values into the hash itself. On loading from Redis, references are resolved automatically and mapped back into the object, as shown in the following example:
Example 30. Sample Property Reference
_class = org.example.Person
id = e2c7dcee-b8cd-4424-883e-736ce564363e
firstname = rand
lastname = al’thor
mother = people:a9d4b3a0-50d3-4538-a2fc-f7fc2581ee56
Reference stores the whole key (keyspace:id) of the referenced object.
?
Spring Data Redis requires you to save the objects stored in home and office separately from the referencing object employee1.
This is (now) stated in the official documentation at the very end of chapter 8.8: https://docs.spring.io/spring-data-redis/docs/current/reference/html/#redis.repositories.references
So if you save home and office to the database before saving employee1 you should be fine.
The same btw holds valid for updates you make to referenced objects later on. Just saving the referencing object alone does not save the updates on the referenced objects.

Spring JPA saving distinct entities with composite primary key not working as expected, updates same entity

I have a logic that saves some data and I use spring boot + spring data jpa.
Now, I have to save one object, and after moment, I have to save another objeect.
those of object consists of three primary key properties.
- partCode, setCode, itemCode.
let's say first object has a toString() returning below:
SetItem(partCode=10-001, setCode=04, itemCode=01-0021, qty=1.0, sortNo=2, item=null)
and the second object has a toString returning below:
SetItem(partCode=10-001, setCode=04, itemCode=01-0031, qty=1.0, sortNo=2, item=null)
there is a difference on itemCode value, and itemCode property is belonged to primary key, so the two objects are different each other.
but in my case, when I run the program, the webapp saves first object, and updates first object with second object value, not saving objects seperately.
(above image contains different values from this post question)
Here is my entity information:
/**
* The persistent class for the set_item database table.
*
*/
#Data
#DynamicInsert
#DynamicUpdate
#Entity
#ToString(includeFieldNames=true)
#Table(name="set_item")
#IdClass(SetGroupId.class)
public class SetItem extends BasicJpaModel<SetItemId> {
private static final long serialVersionUID = 1L;
#Id
#Column(name="PART_CODE")
private String partCode;
#Id
#Column(name="SET_CODE")
private String setCode;
#Id
#Column(name="ITEM_CODE")
private String itemCode;
private Double qty;
#Column(name="SORT_NO")
private int sortNo;
#Override
public SetItemId getId() {
if(BooleanUtils.ifNull(partCode, setCode, itemCode)){
return null;
}
return SetItemId.of(partCode, setCode, itemCode);
}
#ManyToMany(fetch=FetchType.LAZY)
#JoinColumns(value = {
#JoinColumn(name="PART_CODE", referencedColumnName="PART_CODE", insertable=false, updatable=false)
, #JoinColumn(name="ITEM_CODE", referencedColumnName="ITEM_CODE", insertable=false, updatable=false)
})
private List<Item> item;
}
So the question is,
how do I save objects separately which the objects' composite primary keys are partially same amongst them.
EDIT:
The entity extends below class:
#Setter
#Getter
#MappedSuperclass
#DynamicInsert
#DynamicUpdate
public abstract class BasicJpaModel<PK extends Serializable> implements Persistable<PK>, Serializable {
#Override
#JsonIgnore
public boolean isNew() {
return null == getId();
}
}
EDIT again: embeddable class.
after soneone points out embeddable class, I noticed there are only just two properties, it should be three of it. thank you.
#Data
#NoArgsConstructor
#RequiredArgsConstructor(staticName="of")
#Embeddable
public class SetGroupId implements Serializable {
//default serial version id, required for serializable classes.
private static final long serialVersionUID = 1L;
#NonNull
private String partCode;
#NonNull
private String setCode;
}
Check howto use #EmbeddedId & #Embeddable (update you might need to use AttributeOverrides in id field, not sure if Columns in #Embeddable works).
You could create class annotated #Embeddable and add all those three ID fields there.
#Embeddable
public class MyId {
private String partCode;
private String setCode;
private String itemCode;
}
Add needed getters & setters.
Then set in class SetItem this class to be the id like `#EmbeddedId´.
public class SetItem {
#EmbeddedId
#AttributeOverrides({
#AttributeOverride(name="partCode",
column=#Column(name="PART_CODE")),
#AttributeOverride(name="setCode",
column=#Column(name="SET_CODE"))
#AttributeOverride(name="itemCode",
column=#Column(name="ITEM_CODE"))
})
MyId id;
Check also Which annotation should I use: #IdClass or #EmbeddedId
Be sure to implement equals and hashCode in SetGroupId.
Can you provide that class?

How to handle two database insertions fom a single form in spring/ hibernate?

I have 3 model classes,
User.java
public class UserData {
private Integer userID;
private String userName;
private String userPassword;
//getters and setters..
and Permission class like..
Permission.java
public class PermissionsData {
private Integer permissionID;
private Integer userID;
private Integer moduleID;
private boolean permissionIsReadOnly;
private boolean permissionIsModify;
private boolean permissionIsFull;
//getters and setters
amd module class like,
module.java
public class ModuleData {
private Integer modId;
private String modName;
I have some modules in my database. When i am creating a new user, i had listed those modules and had added checkboxes to set permissions. When submitting the form, i need to insert user data to user table and his permissions for each module to the Permission table.
Now i had implemented only inserting roles to the database.. my controller is like..
#RequestMapping(value = "/addRole")
public ModelAndView addNewRole()
{
ModelAndView mav = new ModelAndView("addNewRole");
RoleData role = new RoleData();
mav.getModelMap().put("roleDataObj", role);
List<ModuleData> moduleList = moduleService.getAllModules();
mav.getModelMap().addAttribute("ModuleList", moduleList);
return mav;
}
How can i achieve to add data to two tables on one submit?? i would also like to know about the mapping betwewen modules and permission
I am really new to this spring and hibernate. So plz guide me with sample codes..
Thanks in advance.
if you have set cascading in the mapping
#Cascade(Cascade.all)
private List<Permission> permissions;
it is as simple as
public void saveNewUser(...)
{
User user = new User();
// fill properties
Permission p = new Permission();
// fill properties
user.getPermissions().add(p);
session.save(user);
}
Update: the code above would be possible using a class structure like. the important part is the collection/map of permissions each user has per modul
public class Permission {
private boolean IsReadOnly;
private boolean IsModify;
private boolean IsFull;
}
public class Module {
private Integer id;
private String name;
}
public class User {
private Integer id;
private String name;
private String password;
private Map<Module, Permission> permissions;
}
and mapping
<class name="User">
...
<map name="permissions" cascade="all">
<key column="UserId"/>
<index-many-to-many column="ModuleId" class="Module"/>
<composite-element class="Permission">
<property name="IsReadOnly"/>
<property name="IsModify"/>
<property name="IsFull"/>
</composite-element>
</map>

Resources