Migrations
Yleistä
Migraatiotyökalulla voidaan toteuttaa tietokanta siten, että muutokset ovat hallittuja ja ne on helppo toistaa uudestaan. Tällä kurssilla käytämme Knex-työkalua migraatioiden tekemisessä MySQL-tietokantaan.
Docker
Tehdään paikallinen Docker-ympäristö tietokannalle. Tee itsellesi alikansio docker ja tallenna sinne tiedosto docker-compose.yml
version: '3.1'
services:
db:
image: mysql:8.0.27
restart: always
environment:
MYSQL_ROOT_PASSWORD: mypass123
ports:
- 3306:3306
phpmyadmin:
image: phpmyadmin
restart: always
ports:
- 8081:80
Avaa kansiossa komentokehote (terminal) ja suorita komento
docker-compose up -d
Näet phpMyAdmin-sivun osoitteessa http://localhost:8081. Käyttäjätunnus on root ja salasana yllä määritelty mypass123.
Lisää phpMyAdminin avulla itsellesi tietokanta notesdeno_db.
Knex
Tehdään tietokannan migraatiot projektin alle. Lisää notesdemo-projektille alikansio database. Avaa komentokehote tässä kansiossa.
npm init npm install knex --save
Tehdään seuraavaksi knexfile.js suorittamalla komento
npx knex init
Korvataan oletustiedot käyttämällämme Docker-ympäristön tiedoilla
module.exports = {
development: {
client: 'mysql2',
connection: {
host: 'localhost',
user: 'root',
password: 'mypass123',
database: 'notesdemo_db'
}
}
}
Asenna mysql2
npm install mysql2 --save
Taulujen luonti
Luo uusi migraatio-tiedosto suorittamalla komento
npx knex migrate:make create_notesdb
Määritellään aluksi users-taulu:
exports.up = function(knex, Promise) {
return knex.schema
.createTable('users', t => {
t.increments('id').primary()
t.string('username').notNullable().unique()
t.string('email').notNullable().unique()
t.string('password').notNullable()
t.timestamps(false, true)
})
};
exports.down = function(knex, Promise) {
return knex.schema
.dropTableIfExists('users')
};
Kokeile ajaa migraatio:
npx knex migrate:latest
Tietokannassa tulisi nyt olla taulu users sekä migraatioille luodut taulut.

Voit peruuttaa muutokset suorittamalla komennon
npx knex migrate:rollback
Lisätään mukaan toinen taulu notes. Taulussa notes on luotu relaatio users-tauluun. Taulujen luonti ja poistaminen tulee tehdä oikeassa järjestyksessä. Koska notes tarvitsee users-taulua tulee notes tehdä ensin. Samoin ensin tulee poistaa notes ja sitten vasta users.
exports.up = function(knex, Promise) {
return knex.schema
.createTable('users', t=> {
t.increments('id').primary()
t.string('username').notNullable().unique()
t.string('email').notNullable().unique()
t.string('password').notNullable()
t.timestamps(false, true)
})
.createTable('notes', t => {
t.increments('id').primary()
t.string('content').notNullable()
t.datetime('date').notNullable()
t.boolean('important').notNullable()
t.integer('user_id').unsigned().references('id').inTable('users').notNull()
.onDelete('cascade')
})
};
exports.down = function(knex) {
return knex.schema
.dropTableIfExists('notes')
.dropTableIfExists('users')
};
Seeds
Tietokantaan voidaan lisätä tietoja ajamalla sinne seed-tiedostot. Luodaan uusi tyhjä tiedosto:
npx knex seed:make 01_users
Tiedoston sisällöksi tulee kaksi testikäyttäjää
exports.seed = function(knex, Promise) {
return knex('users').del()
.then(function () {
return knex('users').insert([
{id: 1, username: 'tester1', email: 'tester1@test.com', password: "salasana"},
{id: 2, username: 'tester2', email: 'tester2@test.com', password: "salasana"},
]);
});
};
Nyt salasanat eivät ole vielä salattu. Asennetaan bcryptjs-kirjasto jonka avulla voidaan korvata "salasana" salatulla merkkijonolla.
npm install bcryptjs --save
Lisää tiedoston alkuun salaus ja korvaa "salasana" muuttujalla hashedPassword.
const testPassword = "salasana"
var bcrypt = require('bcryptjs');
var salt = bcrypt.genSaltSync(10);
var hashedpassword = bcrypt.hashSync(testPassword, salt);
seed-tiedosto ajetaan näin:
npx knex seed:run
Lisää toinen tiedosto 02_notes ja lisää siellä kolme muistiinpanoa. seed-tiedostot ajetaan aakkosjärjestyksessä, suunnittele nimeäminen tietokannan rakenteen mukaisesti.
exports.seed = function(knex) {
// Deletes ALL existing entries
return knex('notes').del()
.then(function () {
// Inserts seed entries
return knex('notes').insert([
{
id: 1,
content: "Keep it fast - optimize assets, minimize requests, use caching",
date: new Date("2025-11-10T17:30:31.000Z"),
important: true,
user_id: 1
},
{
id: 2,
content: "Make it accessible - semantic HTML, proper contrast, keyboard-friendly",
date: new Date("2025-11-10T18:39:34.000Z"),
important: false,
user_id: 1
},
{
id: 3,
content: "Design for all devices - responsive layout, fluid elements, test on real screens",
date: new Date("2025-11-10T19:20:14.000Z"),
important: true,
user_id: 2
}
]);
});
};
Jos haluat ajaa vain tietyn seed-tiedoston niin se onnistuu näin:
npx knex seed:run --specific=filename.js