I know there is so much posts about this and i'm searching for this problem for hours. I assigned the data sources and got rid of other "Cannot resolve column ..." warnings but these 2 warnings just makes no sense because the referencedColumnName method is referencing the same column types in particular classes on the above lines:
Why i'm getting errors on the below 2 lines but not above 2 lines?
CarBrand entity:
package com.sbm.insurance.entities;
import lombok.*;
import javax.persistence.*;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import java.util.List;
#Entity
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#Builder
#Table(
uniqueConstraints = #UniqueConstraint(
name = "carBrand",
columnNames = "carBrand"
)
)
public class CarBrands {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#NotBlank(message = "Car Brand can't be null or empty")
private String carBrand;
#Min(1)
#Max(999999)
private float carBrandMultiplier;
#OneToMany(
mappedBy = "brand",
cascade = CascadeType.REMOVE,
fetch = FetchType.LAZY
)
private List<Car> car;
}
I would assume because classes Account and Proposal have a field called id, but CarBrands and CarTypes don't.
Related
I have this Coupon Class
package Kinn.College.CouponManagementSystem.entities;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.ArrayList;
import java.util.List;
#Entity
#Data
#AllArgsConstructor
#NoArgsConstructor
#Table (name = "companies")
public class Company {
#Id
#GeneratedValue (strategy = GenerationType.IDENTITY)
#Column (name = "company_id")
private int id; // id of the company
#Column (name = "company_name")
private String name; // name of the company
#Column (name = "company_email")
private String email; // email of the company
#Column (name = "company_password")
private String password; // password of the company
#OneToMany(mappedBy = "company_id", cascade = CascadeType.ALL)
private List<Coupon> coupons;
}
and I have this company class
package Kinn.College.CouponManagementSystem.entities;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.ArrayList;
import java.util.List;
#Entity
#Data
#AllArgsConstructor
#NoArgsConstructor
#Table (name = "companies")
public class Company {
#Id
#GeneratedValue (strategy = GenerationType.IDENTITY)
#Column (name = "company_id")
private int id; // id of the company
#Column (name = "company_name")
private String name; // name of the company
#Column (name = "company_email")
private String email; // email of the company
#Column (name = "company_password")
private String password; // password of the company
#OneToMany(mappedBy = "company_id", cascade = CascadeType.ALL)
private List<Coupon> coupons;
}
for some reason, the one to many - many to one relationship creates an error when I try to get a company from the DB with a list of coupons.
I'm using this syntax to get a copmany from DB.
{
Company company = companyService.getCompanyById(1);
System.out.println("Got company by id: " + company);
}
if I'm removing the list of coupons from every company, it works just fine.
This is the error message;
2023-01-16T11:59:33.266+02:00 ERROR 16808 --- [ main] j.LocalContainerEntityManagerFactoryBean : Failed to initialize JPA EntityManagerFactory: Collection 'Kinn.College.CouponManagementSystem.entities.Company.coupons' is 'mappedBy' a property named 'company_id' which does not exist in the target entity 'Kinn.College.CouponManagementSystem.entities.Coupon'
I've tried asking multiple people know Spring very well and all of them say it looks okay, that it should work.
mapped_by reference the property or the referenced class, not the column name:
#OneToMany(mappedBy = "id", cascade = CascadeType.ALL)
private List<Coupon> coupons;
BTW: Take care of java naming conventions. Package names should only contains lower case character
I am assuming that a company can relate to many coupons.
So in Coupon class, you can have a Company member which represents the company it belongs to :
#ManyToOne
#JoinColumn(name = "company_id")
private Company company;
Here, company_id would become the foreign key that points to primary key of company table
And in Company class, you can have List of coupons that it owns:
#OneToMany(mappedBy = "company", orphanRemoval = true)
private List<Coupon> coupons = new ArrayList<>();
The Company entity should have a field to point to all its coupons as shown below:
#OneToMany(mappedBy="company")
private Set<Coupon> coupons;
The mappedBy field is the instance variable name we'll use in Coupon entity to point to the associated Company.
The Coupon entity should have a field to point to all its coupons like:
#ManyToOne
#JoinColumn(name="company_id", nullable=false)
private Company company;
The name field refers to the name of the foreign key in the Coupon table that points to the Company table.
You can check this article https://www.baeldung.com/hibernate-one-to-many.
I've created 2 entities in Spring with JPA annotations:
Project:
package com.example.technologyradar.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;
#Entity
#Data
#AllArgsConstructor
#NoArgsConstructor
public class Project {
#Id
#GeneratedValue(strategy = GenerationType.AUTO, generator = "native")
#GenericGenerator(name="native", strategy = "native")
private Long id;
private String name;
#ManyToMany(mappedBy = "projects")
private Set<Technology> assignedTechnologies = new HashSet<Technology>();
}
Technology:
package com.example.technologyradar.model;
import com.example.technologyradar.dto.constant.TechnologyStatus;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;
#Entity
#Data
#AllArgsConstructor
#NoArgsConstructor
public class Technology {
#Id
#GeneratedValue(strategy = GenerationType.AUTO, generator = "native")
#GenericGenerator(name="native", strategy = "native")
private Long id;
private String name;
#Enumerated(EnumType.STRING)
private TechnologyStatus technologyStatus;
#OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST, targetEntity = Category.class)
#JoinColumn(name="category_id", referencedColumnName = "id", nullable = false)
private Category category;
#OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST, targetEntity = Coordinate.class)
#JoinColumn(name="coordinate_id", referencedColumnName = "id", nullable = false)
private Coordinate coordinate;
#ManyToMany
#JoinTable(
name = "projects_technologies",
joinColumns = #JoinColumn(name="technology_id"),
inverseJoinColumns = #JoinColumn(name="project_id")
)
private Set<Project> projects = new HashSet<Project>();
}
My goal is to get List of projects with technologies usage list with ignoring Coordinate and Category from Technology Entity. When I perform simply findAll():
public List<Project> getProjectsWithTechnologyUsage() {
return (List<Project>) projectRepository.findAll();
}
then I'm obtaining famous Infinite Recursion error:
Could not write JSON: Infinite recursion (StackOverflowError); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: java.util.ArrayList[0]->com.example.technologyradar.model.Project["assignedTechnologies"])]
I know that one of the solutions is to add #JsonManagedReference and #JsonBackRerefence annotations but I don't know how to do it correctly for my particular case.
I would be grateful for any suggestions.
Thanks!
If you use json serialization you can
https://github.com/mikebski/jackson-circular-reference
but anyway add to Project entity
#EqualsAndHashCode(of = "id")
#ToString(of = "id")
Actually, for your scenario, you probably just want #JsonIgnore on top of Technology.projects.
Alternatively, if you sometimes want to print Technology.projects, you can use #JsonView on top of Project.technologies instead, to modify the behavior just for this one scenario where Project is the top level object to serialize.
I have the following code, where I need to populate a set with multiple objects that are instances of the same class (User). The problem is, I only get the first object when I log.
user = User.builder()
.id(1L)
.username("2397047")
.nickname("test1")
.build();
anotherUser = User.builder()
.id(2L)
.username("23971948")
.nickname("test2")
.build();
Set<User> userSet = new HashSet<>();
userSet.add(user);
userSet.add(anotherUser);
System.out.println("User set from test " + userSet);
This code produces the following output
User set from test [User(id=1, nickname=test1, username= 2397047, password=null, roles=null, groups=null)]
Why am I unable to get the entire collection?
This is my User class
package com.chama.chamaservice.user;
import com.chama.chamaservice.BaseEntity;
import com.chama.chamaservice.Views;
import com.chama.chamaservice.config.ApplicationUserRole;
import com.chama.chamaservice.group.Group;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonView;
import lombok.*;
import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;
#Builder
#Entity
#NoArgsConstructor
#AllArgsConstructor
#Getter
#Setter
#ToString
public class User extends BaseEntity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#JsonView(Views.Public.class)
private Long id;
#JsonView(Views.Public.class)
private String nickname;
#JsonView(Views.Public.class)
private String username; // <- Unique user's phone number
private String password;
#ElementCollection(targetClass = ApplicationUserRole.class)
#CollectionTable(name = "user_role", joinColumns = #JoinColumn(name = "user_id"))
#Enumerated(EnumType.STRING)
#Column(name = "role")
private Set<ApplicationUserRole> roles;
#JsonIgnore
#ManyToMany(mappedBy = "groupMembers", fetch = FetchType.LAZY, targetEntity = Group.class)
private Set<Group> groups = new HashSet<>();
}
In the User class, #Data annotation which will implement #Getter, #Setter, #ToString method.
It will print all values in the Set.
Found an answer, although it may not be the optimal solution. I annotated the User class with #EqualsAndHashCode
I have an entity that looks like this:
import lombok.*;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Type;
import javax.persistence.*;
import java.util.List;
import java.util.UUID;
#Entity(name = "EnterpriseGroup")
#Data
#EqualsAndHashCode
#AllArgsConstructor
#NoArgsConstructor
#Builder
#Table(name = "enterprise_groups")
public class EnterpriseGroup {
#Id
#GeneratedValue(generator = "uuid4")
#GenericGenerator(name = "UUID", strategy = "uuid4")
#Type(type = "pg-uuid")
#Column(columnDefinition = "CHAR(36)")
private UUID groupId;
#Column(unique = true)
private String name;
private String description;
#ManyToMany(fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST})
#JoinTable(
name = "groups_roles",
joinColumns = {#JoinColumn(name = "groupId")},
inverseJoinColumns = {#JoinColumn(name = "roleId")})
private List<UserRole> roles;
}
I have a default JPA Repository:
import com.fadata.security.domain.entities.EnterpriseGroup;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.UUID;
#Repository
public interface EnterpriseGroupRepository extends JpaRepository<EnterpriseGroup, UUID> {
}
When I try calling repository.findAll() method, I get the following exception:
o.h.engine.jdbc.spi.SqlExceptionHelper: could not extract ResultSet [n/a]
org.postgresql.util.PSQLException: ERROR: operator does not exist: character = uuid
Hint: No operator matches the given name and argument types. You might need to add explicit type casts.
I've tried changing up the UUID type and generation strategies, the column definitions and name, and nothing has worked so far. I tried debugging it by putting a breakpoint on the repository method, but it is never hit, meaning there is some kind of validation that goes on before the method is hit, and that's where this issue originates from. I'm certain I'm passing a valid UUID, because a proper exception is thrown if I pass an invalid UUID format. Yet the exception I get makes me think there is some kind of issue with the way the UUID I pass in with the request is converted and hits the actual app. Any ideas are welcome! Thanks!
Try it UUIDCharType link
#Id
#Type(type = "org.hibernate.type.UUIDCharType")
#GeneratedValue(generator = "UUID")
#GenericGenerator(
name = "UUID",
strategy = "org.hibernate.id.UUIDGenerator"
)
#Column(name = "groupId", updatable = false, nullable = false)
private UUID groupId;
Note: not need generate UUID by UUID.randomUUID()
I have problem with adding users role during registration request
This is my DB diagram:
And I have the following classes: first is entity role:
package application.model;
import lombok.*;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import javax.persistence.*;
import java.util.List;
#NamedQueries({
#NamedQuery(name = User.GET_USERS, query = User.QUERY_GET_USERS),
})
#Getter
#Setter
#NoArgsConstructor
#Entity
#Table(name = "users")
public class User {
public static final String GET_USERS = "User.get_users";
public static final String QUERY_GET_USERS = "select u from User u";
#Id
#NotNull
#GeneratedValue(strategy = GenerationType.SEQUENCE)
#Column(name = "id")
public int id;
#NotNull
#NotEmpty
#Column(name="firstname")
private String firstname;
#NotNull
#Column(name="lastname")
private String lastname;
#NotNull
#Column(name="email")
private String email;
#NotNull
#Column(name="password")
private String password;
#JoinTable
#OneToMany
private List<Role> roles;
}
second entity is Role:
package application.model;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
#Getter
#Setter
#NoArgsConstructor
#Entity
#Table(name = "role")
public class Role {
#Id
#NotNull
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
public int id;
#NotNull
#Column(name="name")
private String name;
}
So, i have 3 roles in my application, when I register new user with post request:
{
"firstname": "imasdie5",
"lastname": "nazasdwisko5",
"email": "masdil",
"password": "pass",
"roles": [
{ "id":2 }
]
}
First user is registered correctly, but when i send second request with same roles.id=2, i have:
ERROR: duplicate key value violates unique constraint "uk_d9najy24fium4vkivgwjuf0hw"
Detail: Key (roles_id)=(2) already exists.
In dbeaver table users_role have constraint uk_d9najy24fium4vkivgwjuf0hw with type UNIQUE_KEY, so that's the problem, but how to change type to non-unique? Many users may have same role, so it is necessary for me
All tables are generated with hibernate.
Table users_role is not entity in my application, maybe it should be entity?
Do You have any advice what I should change to add one role for many users?
Try to use #ManyToMany annotation
#JoinTable
#ManyToMany
private List<Role> roles;