@ManyToMany, błąd tworzenia relacji

0

Dobry wieczór,
robię prosty prosty formularz rejestracyjny w spring boot używając security i jpa,
podczas odpalania Spring Boota wywala mi szereg błędów związanych najpewniej z DDL, poniżej wrzucam spis błędów,
Trochę je skróciłem żeby nie dorzucać wam do przeglądania >300 linijek:

org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL "create table user (id int8 generated by default as identity, email varchar(255), > first_name varchar(255), lastt_name varchar(255), password varchar(255), primary key (id))" via JDBC Statement

Caused by: org.postgresql.util.PSQLException: BŁĄD: błąd składni w lub blisko "user"
Pozycja: 14

org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL "alter table if exists user_roles add constraint FK55itppkw3i07do3h7qoclqd4k >foreign key (user_id) references user" via JDBC Statement

Caused by: org.postgresql.util.PSQLException: BŁĄD: błąd składni w lub blisko "user"
Pozycja: 110

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Initialization of bean failed; nested exception is org.springframework.jdbc.datasource.init.ScriptStatementFailedException: Failed to execute SQL script statement #1 of URL [file:/C:/Users/Kiano/Desktop/Registration/target/classes/data.sql]: insert into user_role(role, description) values ("ROLE_USER", "default role for user"); nested exception is org.postgresql.util.PSQLException: BŁĄD: kolumna "ROLE_USER" nie istnieje
Pozycja: 50

Caused by: org.springframework.jdbc.datasource.init.ScriptStatementFailedException: Failed to execute SQL script statement #1 of URL [file:/C:/Users/Kiano/Desktop/Registration/target/classes/data.sql]: insert into user_role(role, description) values ("ROLE_USER", "default role for user"); nested exception is org.postgresql.util.PSQLException: BŁĄD: kolumna "ROLE_USER" nie istnieje
Pozycja: 50

Caused by: org.postgresql.util.PSQLException: BŁĄD: kolumna "ROLE_USER" nie istnieje

Tyle by było z błędu, teraz wrzucę wam encje także w skróconej wersji bez getterów i setterów, zachodzi tutaj relacja wiele do wielu między użytkownikiem a jego rolą np. w firmie

    public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String firstName;
    private String lasttName;
    @NotEmpty
    private String email;
    @NotEmpty
    private String password;
    @ManyToMany(cascade = CascadeType.PERSIST, fetch = FetchType.LAZY)
    private Set<UserRole> roles = new HashSet<>();



```@Entity
    public class UserRole {

        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
        private String role;
        private String description;

Teraz czas na skrypt SQL który znajduję się w resources a ma po prostu dodawać dane do encji,

insert into user_role(role, description) values ("ROLE_USER", "default role for user");

application.properties

spring.datasource.url=jdbc//localhost:5432/postgres
spring.datasource.username=postgres
spring.datasource.password=postgres
spring.jpa.hibernate.ddl-auto=update
spring.datasource.initialization-mode=always

Liczę na waszą pomoc.

1

Nazwa user jest zarezerwowana w postgresie. Użyj innej nazwy encji lub zmapuj na inną nazwę tabeli.

@Table(name = "table_name")
0

Dzięki zadziałało, zapomniałem o słowach kluczowych w postgresie,

Jeden błąd odszedł ale przyszedł następny, tym razem związany ze SpringSecurity,
Nie wiem dlaczego ale IntelliJ wykrywa mi błąd przy DI PasswordEncoder przez co wywala mi błąd:


APPLICATION FAILED TO START


Description:

Parameter 0 of constructor in org.spring.service.UserService required a bean of type 'org.springframework.security.crypto.password.PasswordEncoder' that could not be found.

Action:

Consider defining a bean of type 'org.springframework.security.crypto.password.PasswordEncoder' in your configuration.

Process finished with exit code 1

0

Podeślij jak wygląda konstruktor UserService i czy masz gdzies zdefiniowany PasswordEncoder.

0

Tylko w UserService wykorzystuje PasswordEncoder

@Service
public class UserService {

    private static final String DEFAULT_ROLE = "ROLE_USER";
    private UserRepository userRepository;
    private UserRoleRepository roleRepository;
    public PasswordEncoder passwordEncoder;

    @Autowired
    public UserService(PasswordEncoder passwordEncoder){
        this.passwordEncoder = passwordEncoder;
    }
    @Autowired
    public void setUserRepository(UserRepository userRepository){
        this.userRepository = userRepository;
    }
    @Autowired
    public void setUserRoleRepository(UserRoleRepository roleRepository){
        this.roleRepository = roleRepository;
    }

   
    public void addWithDefaultRole(User user){
        UserRole defaultRole = roleRepository.findByRole(DEFAULT_ROLE);
        user.getRoles().add(defaultRole);
        String passwordHash = passwordEncoder.encode(user.getPassword());
        user.setPassword(passwordHash);
        userRepository.save(user);
    }

}

1

Zdaje się, że brakuje ci klasy odpowiedzialnej za konfigurację. Niepotrzebnie też ręcznie hashujesz hasło, lepiej zapewnić tu użycie PasswordTokenRepository w konstruktorze UserService.
Z kolei klasa konfiguracji, w wersji z użyciem bazy danych i customowych przyjmuje np. taką postać:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private final BCryptPasswordEncoder passwordEncoder;
    private final DataSource dataSource;

    @Autowired
    SecurityConfig(BCryptPasswordEncoder passwordEncoder, DataSource dataSource) {
        this.passwordEncoder = passwordEncoder;
        this.dataSource = dataSource;
    }

    @Value("${spring.queries.users-query}")
    private String usersQuery;

    @Value("${spring.queries.roles-query}")
    private String rolesQuery;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.jdbcAuthentication().usersByUsernameQuery(usersQuery)
                .authoritiesByUsernameQuery(rolesQuery)
                .dataSource(dataSource).passwordEncoder(passwordEncoder);
    }
}

Oraz w application.properties:

spring.queries.users-query=select email, password, active from user where email=?
spring.queries.roles-query=select u.email, r.role from user u inner join user_role ur on(u.user_id=ur.user_id) inner join role r on(ur.role_id=r.role_id) where u.email=?

Polecam poparzeć również na przykłady małego projektu z użyciem Spring Boot + Spring Security, to na pewno bardziej rozjaśni działanie całego modułu. Tutaj jakiś pierwszy lepszy przykład z opisem: https://medium.com/@gustavo.ponce.ch/spring-boot-spring-mvc-spring-security-mysql-a5d8545d837d

0

Możesz też dodać takiego beana do konfiguracji:

@Bean
public PasswordEncoder passwordEncoder(){
	return new BCryptPasswordEncoder();
}
0

Czego na 'chwile' przed zaczęciem pracy ogarnąć bardziej, Spring Security czy OAuth2?

0

Oba. Jak nie będziesz używał OAuth, to możesz doczytać później 😎

1 użytkowników online, w tym zalogowanych: 0, gości: 1