-6

Here's what I want Hibernate to do:

  • First, to check the existence of the required table. If it's absent, create it according to my schema.sql file. If it's present, update it according to the code in the @Entity class.

  • Second, to fill the users tables with sample rows if it's empty, and ensure the roles table has at least one row with role = 'USER', and one row with role = 'ADMIN'.

  • Also, fill the @JoinTable so that every user is a USER except the first user, who should be an ADMIN.

To do that, I added these properties in my application.properties file (as per this Baeldung article):

# url, username, password

spring.jpa.defer-datasource-initialization=true
spring.jpa.hibernate.ddl-auto=update
spring.sql.init.mode=always

and put schema.sql and data.sql files in my resources/sql directory. These are the trimmed versions of my tables:

-- schema.sql

CREATE TABLE users
(
    id         INT          NOT NULL AUTO_INCREMENT,
    username   VARCHAR(15)  NOT NULL UNIQUE,
    password   VARCHAR(200) NOT NULL,
    enabled    TINYINT      NOT NULL,
    PRIMARY KEY (id)
);

CREATE TABLE roles
(
    id   INT         NOT NULL AUTO_INCREMENT,
    role VARCHAR(15) NOT NULL UNIQUE,
    PRIMARY KEY (id)
);

CREATE TABLE user_role
(
    user_id  INT         NOT NULL,
    role_id  INT         NOT NULL,
    PRIMARY KEY (user_id, role_id),
    FOREIGN KEY (user_id) REFERENCES users (id),
    FOREIGN KEY (role_id) REFERENCES roles (id)
);
-- data.sql

-- inserting sample rows if empty

INSERT INTO users(username, password, enabled)
SELECT *
FROM (VALUES ROW ('mickey_m',
              -- ↓ it's "mickey" in a bcrypted form
             '$2y$10$i5SJc2KAriHGn7Dz2rRQHuQ3JfBxlzMaPVKP1YdEJCukryDY9NbVC',
               1),

              -- and so on

               ) AS sample_rows

WHERE NOT EXISTS(SELECT NULL FROM users);

-- ensuring the required roles exist

INSERT IGNORE INTO roles(role)
VALUES ('USER'),
       ('ADMIN');

-- filling the @JoinTable: all users must be USERs

INSERT IGNORE INTO user_role
SELECT users.id, roles.id
FROM users
         JOIN roles ON roles.role = 'USER';

-- filling the @JoinTable: the first user must also be an ADMIN

INSERT IGNORE INTO user_role
SELECT users.id, roles.id
FROM users
         JOIN roles ON roles.role = 'ADMIN' ORDER BY users.id LIMIT 1;

It doesn't work – data.sql doesn't have any effect as the first user in the users table is still not an ADMIN after the application's startup.

The first user is still not ADMIN.

I skimmed the console for any INSERT-related logs – no luck.

The SQL works as expected on dbfiddle. The only apparent difference is that on dbfiddle the tables are first explicitly created. (I already have them in my database.) However, I expected data.sql to be executed regardless of whether the tables exist.

Did I miss some pieces of configuration?

  • If you run `SELECT users.id, users.username, roles.id, roles.role FROM users JOIN roles ON roles.role = 'ADMIN' ORDER BY users.id LIMIT 1;` then what results do you get ? – Scary Wombat Apr 19 '23 at 00:58
  • @ScaryWombat I don't _run_ it, I just put the files in the `resources/sql` folder and hope that Hibernate will – Sergey Zolotarev Apr 19 '23 at 01:19
  • 1
    Yeah but that is not what I am asking. I suspect that your sql is incorrect, hence asking what debugging you have done and what the results are. Your question is very unclear. Whata data are you starting with? What parts are failng (all/last part only)? – Scary Wombat Apr 19 '23 at 01:21
  • 1
    @ScaryWombat I have no idea how to debug it. The best thing I could do is to test it on _dbfiddle_ and check the logs with the `logging.level.org.springframework.security=DEBUG` property being present (I mentioned it in the question) – Sergey Zolotarev Apr 19 '23 at 01:32
  • 3
    I can see that you are using mysql workbench. Why can you not run the query? Why can you not answer the questions I am asking? – Scary Wombat Apr 19 '23 at 01:34
  • 2
    _Your question is very unclear. Whata data are you starting with? What parts are failng (all/last part only)?_ I believe the answers to those questions are above. I'm starting with the data as described in `data.sql` (it's supposed to create the tables and the rows I have, except for the last `ADMIN` insert which diverts from my data). The failing part is that `data.sql` doesn't seem to be working (the first user is not made `ADMIN`). I have a suspicion `data.sql` is not taken into account by Hibernate at all for some reason – Sergey Zolotarev Apr 19 '23 at 01:38
  • 2
    _Why can you not run the query?_ I can, but, again, it's not about bad SQL (as proven on _dbfiddle_ I mentioned). It's about Hibernate. It's true that I can manually make those inserts in Workbench (they work). But it's not what I want. I want Hibernate to do it – Sergey Zolotarev Apr 19 '23 at 01:42
  • 4
    Please clarify via edits, not comments. Please delete & flag obsolete comments. Please avoid social & meta commentary in posts. (Please don't talk about what you think you are and/or are not asking, just ask clearly.) Please pu all & only what is relevant to asking in your post & relate to your question. [Why should I not upload images of code/data/errors when asking a question?](https://meta.stackoverflow.com/q/285551/3404097) [mre] [ask] [Help] – philipxy Apr 19 '23 at 08:04
  • 2
    Debug questions require a [mre]--cut & paste & runnable code including initialization; desired & actual output (including verbatim error messages); tags & versions; clear specification & explanation. For SQL include DDL & tabular initialization code. For debug that includes the least code you can give that is code that you show is OK extended by code that you show is not OK. [ask] [Help] When you get a result you don't expect, pause your overall goal, chop to the 1st subexpression with unexpected result & say what you expected & why, justified by documentation. (Debugging fundamental.) – philipxy Apr 19 '23 at 08:04
  • 1
    @Scary Wombat, in response to [If you run …](https://stackoverflow.com/q/76049942#comment134124920_76049942) – I tried your suggested query by making a slight change to [the setup provided by the asker](https://dbfiddle.uk/K7MZdKFI). The result was a title row of `id | username | id | role`, and the query returned exactly one row, containing `1 | mickey_m | 2 | ADMIN`. That query is [here](https://dbfiddle.uk/tZNg49SO). -- But the question is about ***hibernate*** and not about SQL, as is clear from [this comment](https://stackoverflow.com/q/76049942#comment134125154_76049942). – Henke Apr 19 '23 at 13:09
  • 3
    This question is [discussed at Meta Stack Overflow](https://meta.stackoverflow.com/q/424255). – Henke Apr 19 '23 at 13:28
  • Or wait, it still works. Somehow the keywords `ROW` got removed so I put them back in their place – Sergey Zolotarev Apr 20 '23 at 01:10
  • Though, I still don't understand why it didn't look into the subdirectories. It's unusual. For example, `@ComponentScan` does scan subdirectories. So I expected the same here – Sergey Zolotarev Apr 20 '23 at 04:02

1 Answers1

0

Make sure you specify the directories of your initialization scripts inside your application.properties file in case they are not directly in resources

spring.sql.init.data-locations=classpath:/sql/data.sql
spring.sql.init.schema-locations=classpath:/sql/schema.sql