Skip Navigation
InitialsDiceBearhttps://github.com/dicebear/dicebearhttps://creativecommons.org/publicdomain/zero/1.0/„Initials” (https://github.com/dicebear/dicebear) by „DiceBear”, licensed under „CC0 1.0” (https://creativecommons.org/publicdomain/zero/1.0/)TH
TheDarkBanana87 @lemmy.world
Posts 6
Comments 63

Need Guidance for Springboot and JPA

cross-posted from: https://lemmy.world/post/16301329

> Hello Java Community. > > Sorry if there's any grammar / spelling mistakes in this post. I'll try to convey my questions as clear as possible. > > # Introduction > I have basic knowledge about Java Programming. I took Programming Courses at my Uni and somewhat familiar with Java and OOP concepts in general ( barely ). > > So for the last few weeks, I've been watching a great course from BouAli Free Code Camp Springboot Full Course on Youtube. > > After completing the course, I challenge my self to create a basic E-Commerce Application with Springboot as the Framework, in order to practice my self with the knowledge i got from the course. > > This Application will be a Simple Multi Tenant Application, where each tenant can create a product page, and a customer can purchase. Mind you i create this app to challenge my understanding about Springboot, and will not be a complex app for use. > > # Set Up > In the tutorial, there's a usage of @ManyToMany to map Many to Many Relationship. I thought that i could use Many To Many Mapping on Tenants <-> Users Relationship. In my understanding, A tenantEntity could have multiple users assigned, and multiple usersEntity could belong to a tenantEntity > > With that understanding, i try to create my tenantEntity and userEntity as follow > java tenantEntity > // tenantEntity.java > // Import Ommited for simplicity > // Using Lombok Setter, Getter, AllArgs, NoArgs > @Entity > @Table(name = "T_TENANT") > public class TenantEntity { > @Id > @GeneratedValue(strategy = GenerationType.UUID) > private UUID id; > > @Column(nullable = false) > private String tenantName; > > @Column(length = 2000) > private String tenantDescription; > > private String website; > > @Column(nullable = false) > private Boolean isEnabled; > > private Instant subscriptionExpiryDate; > > @Column(length = 10) > private int gracePeriodDays; > > @ManyToMany(mappedBy = "tenants", fetch = FetchType.LAZY) > private Set<UserEntity> users = new HashSet<>(); > > @Column(updatable = false, nullable = false) > @CreationTimestamp > private Instant createdAt; > > @Column > @UpdateTimestamp > private Instant updatedAt; > } > > > java userEntity > // userEntity.java > // Import Ommited for simplicity > // Using Lombok Setter, Getter, AllArgs, NoArgs > @Entity > @Table(name = "T_USER") > public class UserEntity { > @Id > @GeneratedValue(strategy = GenerationType.IDENTITY) > private Long id; > > @Column(nullable = false, unique = true) > private String username; > > @Column(nullable = false, unique = true) > private String email; > > @Column(nullable = false) > private String firstName; > > private String lastName; > > @Column(nullable = false) > private String password; > > @Column(nullable = false) > private boolean isEnabled; > > @ManyToMany(cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH}) > @JoinTable( > name = "t_users_tenants_mapping", > joinColumns = @JoinColumn( > name = "fk_user_id", referencedColumnName = "id" > ), > inverseJoinColumns = @JoinColumn( > name = "fk_tenant_id", referencedColumnName = "id" > ) > ) > private Set<TenantEntity> tenants = new HashSet<>(); > > @Column(updatable = false, nullable = false) > @CreationTimestamp > private Instant createdAt; > > @Column > @UpdateTimestamp > private Instant updatedAt; > } > > > Generating this relationship in the database > ! > > ## Creating New User > When creating new user, i could assign the Tenant to the User, resulting in these data > json > // POST api/v1/users > { > "username": "newuser01", > "first_name": "new", > "last_name": "user", > "email": "newuser@localhost", > "password": "<P@ssw0rd/>", > "is_enabled": true, > "tenant_id": [ > "79cf0ecf-976a-472c-b250-2192e630a4e4", > "ac5b5786-c467-4dd6-b74d-7f70c83e1827" > ] > } > > > > fk_user_id|fk_tenant_id | > ----------+------------------------------------+ > 6|79cf0ecf-976a-472c-b250-2192e630a4e4| > 6|ac5b5786-c467-4dd6-b74d-7f70c83e1827| > > # Problem(s) > Now, how does one updates the data for the ManyToMany relationship? > Say, i want to modify the membership of a user. i want to add new tenant or remove existing tenant? > > I try creating update method on my userRepository > > // userRepository > public interface UserEntityRepository extends JpaRepository<UserEntity, Long> { > > @Transactional > @Modifying @Query(""" > update UserEntity u set u.username = :username, u.email = :email, u.firstName = :firstName, u.lastName = :lastName, u.isEnabled = :isEnabled, u.tenants = :tenants, u.updatedAt = :updatedAt where u.id = :id""") > int updateUsernameAndEmailAndFirstNameAndLastNameAndIsEnabledAndTenantsAndUpdatedAtById( > @Param("username") String username, > @Param("email") String email, > @Param("firstName") String firstName, > @Param("lastName") String lastName, > @Param("isEnabled") boolean isEnabled, > @Param("tenants") Set<TenantEntity> tenants, > @Param("updatedAt") Instant updatedAt, > @Param("id") Long id > ); > } > > which being called by userService > > public UserResponseDTO updateUser(Long userId, UserRequestDto dto){ > Instant updateAt = Instant.now().atZone(ZoneId.of("Continent/Ciy")).toInstant(); > Set<TenantEntity> tenantEntitySet = getTenantEntitiesFromUserRequestDTO(dto); > > int updateRows = userEntityRepository.updateUsernameAndEmailAndFirstNameAndLastNameAndIsEnabledAndTenantsAndUpdatedAtById( > dto.username(), > dto.email(), > dto.first_name(), > dto.last_name(), > dto.is_enabled(), > tenantEntitySet, > updateAt, > userId > ); > > UserResponseDTO userResponseDTO; > UserEntity userEntity; > if (updateRows == 1) { > userEntity = userEntityRepository.findById(userId).orElse(new UserEntity()); > } else { > userEntity = new UserEntity(); > } > return userMapper.mapUserEntityToUserResponseDto(userEntity); > } > > > resulting in a NullPointerException java.lang.NullPointerException: Cannot invoke "org.hibernate.sql.ast.tree.expression.Expression.getColumnReference()" because "pathSqlExpression" is null > > in which resulted in a Hibernate Forum that states Updating *-to-many collections is not possible, but please submit a bug report to our issue tracker([https://hibernate.atlassian.net 14](https://hibernate.atlassian.net)) to improve the error message. > > # Questions > So what is the best practice of doing things with ManytoMany associations? I've found many tutorials that state the use of @ManyToMany Annotations, but left after they're done inserting things to the database. How can i update the join table relations when the need to modify the data arises? > > Is there a knowledge gap between me and Springboot especially with JPA? should i take another approach? > > Any kind of feedback and suggestions are welcome > > Thank You :D > > > # Resources > 1. Free Code Camp | Springboot Full Course Youtube > 2. Baledung Explenation of ManyToMany > 3. vladmihalcea -> Just found out today, will read it later > 4. GeeksForGeeks ManyToMany

1

Need Guidance for Springboot and JPA

Hello Java Community.

Sorry if there's any grammar / spelling mistakes in this post. I'll try to convey my questions as clear as possible.

Introduction

I have basic knowledge about Java Programming. I took Programming Courses at my Uni and somewhat familiar with Java and OOP concepts in general ( barely ).

So for the last few weeks, I've been watching a great course from BouAli Free Code Camp Springboot Full Course on Youtube.

After completing the course, I challenge my self to create a basic E-Commerce Application with Springboot as the Framework, in order to practice my self with the knowledge i got from the course.

This Application will be a Simple Multi Tenant Application, where each tenant can create a product page, and a customer can purchase. Mind you i create this app to challenge my understanding about Springboot, and will not be a complex app for use.

Set Up

In the tutorial, there's a usage of @ManyToMany to map Many to Many Relationship. I thought that i could use Many To Many Mapping on Tenants <-> Users Relationship. In my understanding, A tenantEntity could have multiple users assigned, and multiple usersEntity could belong to a tenantEntity

With that understanding, i try to create my tenantEntity and userEntity as follow ``` java tenantEntity // tenantEntity.java // Import Ommited for simplicity // Using Lombok Setter, Getter, AllArgs, NoArgs @Entity @Table(name = "T_TENANT") public class TenantEntity { @Id @GeneratedValue(strategy = GenerationType.UUID) private UUID id;

@Column(nullable = false) private String tenantName;

@Column(length = 2000) private String tenantDescription;

private String website;

@Column(nullable = false) private Boolean isEnabled;

private Instant subscriptionExpiryDate;

@Column(length = 10) private int gracePeriodDays;

@ManyToMany(mappedBy = "tenants", fetch = FetchType.LAZY) private Set<UserEntity> users = new HashSet<>();

@Column(updatable = false, nullable = false) @CreationTimestamp private Instant createdAt;

@Column @UpdateTimestamp private Instant updatedAt; } ```

``` java userEntity // userEntity.java // Import Ommited for simplicity // Using Lombok Setter, Getter, AllArgs, NoArgs @Entity @Table(name = "T_USER") public class UserEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id;

@Column(nullable = false, unique = true) private String username;

@Column(nullable = false, unique = true) private String email;

@Column(nullable = false) private String firstName;

private String lastName;

@Column(nullable = false) private String password;

@Column(nullable = false) private boolean isEnabled;

@ManyToMany(cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH}) @JoinTable( name = "t_users_tenants_mapping", joinColumns = @JoinColumn( name = "fk_user_id", referencedColumnName = "id" ), inverseJoinColumns = @JoinColumn( name = "fk_tenant_id", referencedColumnName = "id" ) ) private Set<TenantEntity> tenants = new HashSet<>();

@Column(updatable = false, nullable = false) @CreationTimestamp private Instant createdAt;

@Column @UpdateTimestamp private Instant updatedAt; } ```

Generating this relationship in the database !

Creating New User

When creating new user, i could assign the Tenant to the User, resulting in these data json // POST api/v1/users { "username": "newuser01", "first_name": "new", "last_name": "user", "email": "newuser@localhost", "password": "<P@ssw0rd/>", "is_enabled": true, "tenant_id": [ "79cf0ecf-976a-472c-b250-2192e630a4e4", "ac5b5786-c467-4dd6-b74d-7f70c83e1827" ] }

fk_user_id|fk_tenant_id | ----------+------------------------------------+ 6|79cf0ecf-976a-472c-b250-2192e630a4e4| 6|ac5b5786-c467-4dd6-b74d-7f70c83e1827|

Problem(s)

Now, how does one updates the data for the ManyToMany relationship? Say, i want to modify the membership of a user. i want to add new tenant or remove existing tenant?

I try creating update method on my userRepository ``` // userRepository public interface UserEntityRepository extends JpaRepository<UserEntity, Long> {

@Transactional @Modifying @Query(""" update UserEntity u set u.username = :username, u.email = :email, u.firstName = :firstName, u.lastName = :lastName, u.isEnabled = :isEnabled, u.tenants = :tenants, u.updatedAt = :updatedAt where u.id = :id""") int updateUsernameAndEmailAndFirstNameAndLastNameAndIsEnabledAndTenantsAndUpdatedAtById( @Param("username") String username, @Param("email") String email, @Param("firstName") String firstName, @Param("lastName") String lastName, @Param("isEnabled") boolean isEnabled, @Param("tenants") Set<TenantEntity> tenants, @Param("updatedAt") Instant updatedAt, @Param("id") Long id ); } which being called by userService public UserResponseDTO updateUser(Long userId, UserRequestDto dto){ Instant updateAt = Instant.now().atZone(ZoneId.of("Continent/Ciy")).toInstant(); Set<TenantEntity> tenantEntitySet = getTenantEntitiesFromUserRequestDTO(dto);

int updateRows = userEntityRepository.updateUsernameAndEmailAndFirstNameAndLastNameAndIsEnabledAndTenantsAndUpdatedAtById( dto.username(), dto.email(), dto.first_name(), dto.last_name(), dto.is_enabled(), tenantEntitySet, updateAt, userId );

UserResponseDTO userResponseDTO; UserEntity userEntity; if (updateRows == 1) { userEntity = userEntityRepository.findById(userId).orElse(new UserEntity()); } else { userEntity = new UserEntity(); } return userMapper.mapUserEntityToUserResponseDto(userEntity); } ```

resulting in a NullPointerException java.lang.NullPointerException: Cannot invoke "org.hibernate.sql.ast.tree.expression.Expression.getColumnReference()" because "pathSqlExpression" is null

in which resulted in a Hibernate Forum that states Updating *-to-many collections is not possible, but please submit a bug report to our issue tracker([https://hibernate.atlassian.net 14](https://hibernate.atlassian.net)) to improve the error message.

Questions

So what is the best practice of doing things with ManytoMany associations? I've found many tutorials that state the use of @ManyToMany Annotations, but left after they're done inserting things to the database. How can i update the join table relations when the need to modify the data arises?

Is there a knowledge gap between me and Springboot especially with JPA? should i take another approach?

Any kind of feedback and suggestions are welcome

Thank You :D

Resources

  1. Free Code Camp | Springboot Full Course Youtube
  2. Baledung Explenation of ManyToMany
  3. vladmihalcea -> Just found out today, will read it later
  4. GeeksForGeeks ManyToMany
0
Partitioning mixed media
  • In my oppinion

    You can use the ssd as the root partition, then mount the hdd as your home partition.

    If you meed to store large file, you can dump it to the home partition

    Then mount the nvme as /data01 or something else

    Then when in steam, you can add new location to tell steam where to put / searchf for your game

    Ill post a screenshot later

  • Bell curve with no bell curve
  • Well, i used to be a gentoo user for 2 years or more. But after a while, it kinda bothersome to compile everything on my current pc. So i switched to fedora and its been great :D

    Sorry if i didnt get your point, english is not my first langauge

  • Bell curve with no bell curve
  • Ill try downgrading the driver

    But currently im fine with xorg tho

    I just want to play my games lol

    Thats another reason i switch from gentoo to fedora. I do learned a lot from gentoo, but sometimes its just tiring to build everything and i just want something that works

    I've been daily driving gentoo for 2 years :D

  • Bell curve with no bell curve
  • Switch from gentoo to fedora recently and use wayland as the default with nvidia

    Everythings works fine until i fire up some games. All the games have this weird screen flickering and screen tearing which render a black box and literally unplayable. Tried rebooting, upgrading, downgrading and no avail.

    Then i tried to use Xorg and everythings fine.

    Ita frustating tho

  • Lemmy World Error

    Hello, I've encountered this Error when accessing https://lemmy.world/c/suspiciouslyspecific communities from lemmy.world

    Sorry if this is not the right place, because i dont know where to put it

    Occurred on 24 Jun 2023 ( DD-MM-YY ) at approx 21:00 GMT + 7

    Thank you

    !

    2

    Getting steamclient64 error

    Hello, just downloaded Metal Gear Solid V: The Phantom Pain from Dodi and Fit Girl Repacks

    When trying to launch the game, i got this error

    unable to load library steamclient64.dll

    I've tried to copy steamclient64.dll from another installation, and got another error

    cannot find steam_emu.ini ( even though the file already exists )

    Currently running 6.3.5-gentoo-dist, with Lutris version 0.5.12

    Got the same behavior when using FitGirl-Repacks and from DODI Repacks

    Hardware:

    • CPU: Intel i7 7-6700 (8) @ 4.000GHz
    • GPU: NVIDIA GeForce GTX 1070
    • Ram: 15933MiB
    • Using X server, with KDE Plasma

    Please reply if i miss any info

    Thank you

    ! The error i got

    Edit:

    • Add more context
    • Add Hardware Descriptions
    • Add Image
    11

    Jerboa Android App

    Hello, i want to ask about the current Jerboa Android Client ( v 0.0.34 )

    On the menu bar at the bottom of the screen, the description of the search button and the one beside the profile are the same "search"

    Is it supposed to be like this?

    Thank you

    Edit: Adding Jerboa Version

    14