Grails est un framework complet développé pour résoudre de nombreux défis du développement Web grâce à la technologie de base et aux plugins associés.
Alors que de nombreux frameworks Web dans le monde Java sont complexes et n'embrassent pas les principes DRY, Grails s'appuie sur des concepts de framework dynamiques qui ont conduit à une réflexion moderne sur les applications Web telles que Rails et Django. , Repose sur les technologies Java existantes telles que Spring et Hibernate.
Référence http://docs.grails.org/latest/guide/single.html#requirements
Dans l'article, j'ai utilisé la version suivante.
Nous avons confirmé l'opération uniquement sur Ubuntu 16. Consultez la documentation SDKMAN (https://sdkman.io/) pour plus d'informations.
Installez SDKMAN (voir Installation de SDKMAN (https://sdkman.io/install))
Installez Java
$ sdk install java
Installer Grails
$ sdk install grails
C: \ grails
etc.)GRAILS_HOME
( GRAILS_HOME = C: \ grails
)% GRAILS_HOME% \ bin
à la variable d'environnement PATH
grails -version
et si la version Grails est affichée, l'installation est terminée.Lors de la création d'une application Grails, utilisez la commande grails create-app pour créer les fichiers requis en bloc.
$ cd ${Répertoire de destination d'enregistrement de l'application}
$ grails create-app grails-sample-app
# grails-sample-Remplacez l'application par le nom de l'application le cas échéant.
# "grails-sample-app"Un répertoire est créé
#Le nom du package de l'application est"grails.sample.app"Sera.
Grails Vous pouvez également utiliser un mode qui vous permet d'exécuter chaque commande de manière interactive. Le mode interactif est disponible lorsque vous exécutez la commande grails
sans options, et vous pouvez terminer la commande avec la touche Tab en mode interactif.
Exécutez la commande run-app
pour exécuter l'application.
Exécutez l'application Grails(Lorsque vous n'utilisez pas le mode interactif Grails)
$ cd ${create-répertoire de destination d'enregistrement de l'application}
$ grails run-app
Exécutez l'application Grails(Lors de l'utilisation du mode interactif Grails)
$ cd ${create-répertoire de destination d'enregistrement de l'application}
$ grails #Lancez Grails en mode interactif
grails> run-app
grails help
, et si vous spécifiez une option après help comme grails help run-app
, une aide pour l'exécution de cette option est affichée.Après avoir exécuté l'application avec run-app, accédez à http: // localhost: 8080 / et vous verrez l'écran d'introduction Grails comme indiqué ci-dessous. (L'écran affiche le HelloController créé en plus du fichier créé par create-app)
.gradle/
.idea/ ...Fichier de configuration pour IntelliJ IDE
build/ ...Créer un fichier(create-N'existe pas immédiatement après l'exécution de l'application)
gradle/
grails-app/ ...Code source de l'application
assets/ ...Stockage des ressources d'actifs(Fichiers traités par le pipeline d'actifs)
conf/ ...Paramètres d'exécution
controllers/ ...manette(MVC modèle C)
${nom de l'application}/ ...nom de l'application(Si des tirets sont inclus, le répertoire est séparé pour chaque tiret)
UrlMappings.groovy ...Mappage d'URL
domain/ ...Classe de domaine(MVC modèle M)
i18n/ ... internationalization(i18n)Prise en charge de la configuration
init/ ...Traitement au démarrage de l'application
services/ ...Couche de service
taglib/ ...Bibliothèque de balises(Balises personnalisées définies pouvant être utilisées dans View)
utils/ ...Utilitaire spécifique aux Grails
views/ ... Groovy Server Page(GSP) or JSON Views (MVC modèle V)
src/
integration-test/ ...Test d'intégration
main/ ...Fichier statique qui ne passe pas par le traitement du pipeline d'actifs
groovy/ ...Classe de domaine que vous ne souhaitez pas associer à la table DB
webapp/ ...Fichier statique(Inclus dans WAR, pas dans JAR)
resources/public ...Fichier statique(/static/x/y/Accès avec z)
test/ ...Test de l'unité
groovy/
${nom de l'application}/
${***Spec}.groovy
.gitignore ...Paramètres de fichier non géré VCS pour Git
build.gradle ...Paramètres de construction
gradle.properties ...Paramètres Gradle
gradlew ...Script de lancement Gradle(UN*Pour X)
gradlew.bat ...Script de lancement Gradle(Pour les fenêtres)
grails-wrapper.jar
grailsw ...Script de lancement Grails(UN*Pour X)
grailsw.bat ...Script de lancement Grails(Pour les fenêtres)
README.md ... README
Des informations détaillées
Affiche «Hello World!» Sous forme de chaîne de caractères.
Dans Grails, lorsque vous créez un contrôleur et décrivez une action dans cette classe, elle est mappée à une URL unique et est accessible par un navigateur.
La règle de mappage sera / <appname> / <controller> / <action>
, et <controller>
sera la classe du contrôleur moins Class
.
Par exemple, pour créer un HelloController
et que l'action ʻindex` affiche" HelloWorld ", procédez comme suit:
Exécutez l'application Grails
grails> create-controller hello #La classe HelloController est créée
Modifiez la classe HelloController créée dans grails-app / controllers / grails / sample / app / HelloController.groovy
avec le contenu suivant.
grails-app/controllers/grails/sample/app/HelloController.groovy
package grails.sample.app
class HelloController {
def index() {
render "Hello World!"
}
}
Lorsque vous exécutez l'application et accédez à http: // localhost: 8080 / hello / index ou http: // localhost: 8080 / hello /, la chaîne "Hello World!" S'affiche. (L'action d'indexation peut être omise sur l'URL)
Le domaine est M de MVC dans Grails.
Vous pouvez créer des contrôleurs et des vues individuels, comme dans l'exemple précédent d'affichage HelloWorld, mais vous pouvez utiliser l'option generate-all
pour créer des contrôleurs et des vues avec la fonctionnalité CRUD pour votre domaine (plus pour les tests). Vous pouvez créer une classe).
Créer une classe de domaine d'employé, un contrôleur pour CRUD, une vue et un test
#Créer une classe de domaine Employee
$ grails create-domain-class employee
| Created grails-app/domain/grails/sample/app/Employee.groovy
| Created src/test/groovy/grails/sample/app/EmployeeSpec.groovy
#Créer des classes de contrôleur, de vue et de test dans les classes de domaine des employés CRUD
$ grails generate-all grails.sample.app.Employee
| Rendered template Controller.groovy to destination grails-app\controllers\grails\sample\app\EmployeeController.groovy
| Rendered template Service.groovy to destination grails-app\services\grails\sample\app\EmployeeService.groovy
| Rendered template Spec.groovy to destination src\test\groovy\grails\sample\app\EmployeeControllerSpec.groovy
| Rendered template ServiceSpec.groovy to destination src\integration-test\groovy\grails\sample\app\EmployeeServiceSpec.groovy
| Scaffolding completed for grails-app\domain\grails\sample\app\Employee.groovy
| Rendered template create.gsp to destination grails-app\views\employee\create.gsp
| Rendered template edit.gsp to destination grails-app\views\employee\edit.gsp
| Rendered template index.gsp to destination grails-app\views\employee\index.gsp
| Rendered template show.gsp to destination grails-app\views\employee\show.gsp
| Views generated for grails-app\domain\grails\sample\app\Employee.groovy
Vous avez maintenant créé la possibilité de CRUD la classe de domaine Employé.
La classe de domaine n'a pas encore d'attributs, alors éditez le fichier grails-app / domain / grails / sample / app / Employee.groovy
et ajoutez les attributs appropriés.
grails-app/domain/grails/sample/app/Employee.groovy
package grails.sample.app
class Employee {
String name
static constraints = {
}
}
Lorsque j'exécute à nouveau run-app pour afficher l'écran TOP de l'application dans le navigateur, grails.sample.app.EmployeeController
est ajouté aux contrôleurs disponibles:.
La chaîne de caractères grails.sample.app.EmployeeController est un lien, et en cliquant dessus, vous serez redirigé vers l'écran de la liste des employés (http: // localhost: 8080 / employee / index).
Écran de la liste des employés |
---|
Comme vous pouvez le voir avec certaines opérations, les itinéraires suivants ont été ajoutés.
racine | une fonction |
---|---|
GET /employee/index | Afficher l'écran de la liste des employés |
GET /employee/create | Afficher l'écran de création d'un nouvel employé |
GET /employee/show/:id | Écran des détails de l'employé(:id est l'ID de la classe de domaine)Spectacle |
GET /employee/edit/:id | Écran d'édition des employés(:id est l'ID de la classe de domaine)Spectacle |
POST /employee/save | Nouvelle création d'employé |
PUT /employee/update/:id | Mise à jour des employés(:id est l'ID de la classe de domaine) |
DELETE /employee/delete/:id | Employé supprimé(:id est l'ID de la classe de domaine) |
La base de données utilisée par l'application peut être modifiée pour chaque variable d'environnement telle que le développement, le test et la production. Grails est configuré pour utiliser H2 Database par défaut dans tous les environnements.
Vous remarquerez également que la base de données est initialisée lorsque vous avez terminé l'opération CRUD, quittez run-app et réexécutez l'application. Cela est dû au fait que H2 est une base de données en mémoire et que la base de données dans l'environnement de développement est définie pour DROP la base de données à la fin de l'application et la crée au démarrage.
Ces paramètres sont définis dans grails-app / conf / application.yml. (Voir The Grails Framework> The DataSource pour plus de détails sur les paramètres.)
Cette fois, nous nous mettrons à ne pas détruire la base de données créée dans l'environnement de développement.
Réécrivez grails-app / conf / application.yml
avec le contenu suivant.
grails-app/conf/application.yml
environments:
development:
dataSource:
# create-Passer d'une goutte à l'autre
dbCreate: update
# mem:de devDb./Changer en devDb
url: jdbc:h2:./devDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
Les valeurs qui peuvent être définies avec dbCreate sont les suivantes.
Paramètres dbCreate | La description |
---|---|
create | Schéma existant au démarrage(table,indice,autre)Déposer et recréer |
create-drop | Identique à créer, mais supprimer la table en quittant l'application |
update | Créez ou mettez à jour une table ou un index qui n'existe pas. Ne supprimez pas les tables ou les données existantes.(Notez que les anciennes colonnes et données resteront car les modifications de nom de colonne ne peuvent pas être gérées correctement.) |
validate | Générer un avertissement en comparant le schéma et les paramètres existants sans apporter de modifications à la base de données |
any other value | ne fais rien |
def p = new Person(name: "Fred", age: 40, lastVisit: new Date())
p.save()
def p = Person.get(1)
println('name: ' + p.name)
def p = Person.get(1)
p.name = 'Bob'
p.save()
def p = Person.get(1)
p.delete()
Étendons un peu plus la classe de domaine Employee et rendons-la plus pratique.
grails-app/domain/grails/sample/app/Employee.groovy
package grails.sample.app
class Employee {
String name
String department
String gender
Date birth
Date joinedDate
Long payment
String note
static constraints = {
name blank: false, unique: true
department blank: false
gender blank: false, inList: ['male', 'female', 'other']
birth blank: false
joinedDate blank: false
payment min: new Long(0), blank: false
note blank: true
}
/**
*La durée du service
*/
public int serviceYears() {
def today = new Date()
return Math.max(0, today.year - this.joinedDate.year)
}
}
Pour le moment, sauf pour la note, j'ai défini nullable: false
(puisque c'est par défaut, il n'est pas spécifié dans les contraintes) et blank: false
.
Si vous définissez blank: true
comme indiqué dans la note, vous devez désactiver le processus de conversion en null si les données sont vides.
Le paramètre peut être désactivé en définissant ʻapplication.groovycomme suit. Si le fichier n'existe pas, créez-le sous
grails-app / conf /`.
grails-app/conf/application.groovy
// the default value for this property is true
grails.databinding.convertEmptyStringsToNull = false
Maintenant, changez l'écran de liste et l'écran d'édition pour afficher l'employé comme suit.
Affichage de l'écran de liste(grails-app/views/employee/index.gsp)
<!DOCTYPE html>
<html>
<head>
<meta name="layout" content="main" />
<g:set var="entityName" value="${message(code: 'employee.label', default: 'Employee')}" />
<title><g:message code="default.list.label" args="[entityName]" /></title>
<script type="text/javascript">
/*Définir l'état du bouton d'édition en fonction de l'état du bouton radio*/
function setEditButtonStatusByRadioButton() {
var edit_button_id = "edit_button";
var radios = document.getElementsByName('id');
var checkedNum = 0;
radios.forEach(e => e.checked && checkedNum++);
if (checkedNum > 0) {
document.getElementById(edit_button_id).disabled = false;
} else {
document.getElementById(edit_button_id).disabled = true;
}
}
</script>
</head>
<body>
<a href="#list-employee" class="skip" tabindex="-1"><g:message code="default.link.skip.label" default="Skip to content…"/></a>
<div class="nav" role="navigation">
<ul>
<li><a class="home" href="${createLink(uri: '/')}"><g:message code="default.home.label"/></a></li>
<li><g:link class="create" action="create"><g:message code="default.new.label" args="[entityName]" /></g:link></li>
</ul>
</div>
<div id="list-employee" class="content scaffold-list" role="main">
<h1><g:message code="default.list.label" args="[entityName]" /></h1>
<g:if test="${flash.message}">
<div class="message" role="status">${flash.message}</div>
</g:if>
<g:form action="edit">
<table class="table table-striped">
<thead>
<tr>
<th>Edit</th>
<g:each in="${['id', 'name', 'department', 'gender']}" var="p">
<g:sortableColumn property="${p}" title="${p}" />
</g:each>
</tr>
</thead>
<tbody>
<g:each in="${employeeList}" var="employee">
<tr>
<td><input name="id" type="radio" value="${employee.id}" onclick="setEditButtonStatusByRadioButton()" /></td>
<g:each in="${['id', 'name', 'department', 'gender']}" var="p">
<g:if test="${p=='id'}">
<td><g:link method="GET" resource="${employee}">${employee.properties[p]}</g:link></td>
</g:if>
<g:else>
<td>${employee.properties[p]}</td>
</g:else>
</g:each>
</tr>
</g:each>
</tbody>
</table>
<button disabled="false" id="edit_button"><g:message code="default.edit.label" args="[entityName]" /></button>
</g:form>
<div class="pagination">
<g:paginate total="${employeeCount ?: 0}" />
</div>
</div>
</body>
</html>
Vue d'écran détaillée(grails-app/views/employee/show.gsp)
<!DOCTYPE html>
<html>
<head>
<meta name="layout" content="main" />
<g:set var="entityName" value="${message(code: 'employee.label', default: 'Employee')}" />
<title><g:message code="default.show.label" args="[entityName]" /></title>
</head>
<body>
<a href="#show-employee" class="skip" tabindex="-1"><g:message code="default.link.skip.label" default="Skip to content…"/></a>
<div class="nav" role="navigation">
<ul>
<li><a class="home" href="${createLink(uri: '/')}"><g:message code="default.home.label"/></a></li>
<li><g:link class="list" action="index"><g:message code="default.list.label" args="[entityName]" /></g:link></li>
<li><g:link class="create" action="create"><g:message code="default.new.label" args="[entityName]" /></g:link></li>
</ul>
</div>
<div id="show-employee" class="content scaffold-show" role="main">
<h1><g:message code="default.show.label" args="[entityName]" /></h1>
<g:if test="${flash.message}">
<div class="message" role="status">${flash.message}</div>
</g:if>
<ol class="property-list employee">
<li class="fieldcontain">
<g:each in="${['id', 'name', 'department', 'gender', 'birth', 'serviceYears', 'payment', 'note']}" var="p">
<span id="name-label" class="property-label">${p}</span>
<g:if test="${p=='serviceYears'}">
<div class="property-value" aria-labelledby="name-label">${employee.serviceYears()}</div>
</g:if>
<g:else>
<div class="property-value" aria-labelledby="name-label">${employee.properties[p]}</div>
</g:else>
</g:each>
</li>
</ol>
<g:form resource="${this.employee}" method="DELETE">
<fieldset class="buttons">
<g:link class="edit" action="edit" resource="${this.employee}"><g:message code="default.button.edit.label" default="Edit" /></g:link>
<input class="delete" type="submit" value="${message(code: 'default.button.delete.label', default: 'Delete')}" onclick="return confirm('${message(code: 'default.button.delete.confirm.message', default: 'Are you sure?')}');" />
</fieldset>
</g:form>
</div>
</body>
</html>
C'est un peu plus pratique.
La vue est décrite dans Groovy Server Pages (GSP), et «<g: link>», «<g: form>», etc. sont des balises GSP. (Voir Groovy Server Pages (GSP) pour plus d'informations)
Grails 3.3.5 a introduit Bootstrap 3.3.6 par défaut.
Il semble y avoir twitter-bootstrap-grails-plugin du plugin Grails, mais la version actuelle est 3.3.5 le 18 septembre '18. Il semble que le commit final date d'il y a deux ans, il ne semble donc pas bien entretenu, j'ai donc décidé d'installer Bootstrap v4 manuellement.
grails-app / assets / javascripts / application.js
--Change de // = require jquery-2.2.0.min
à // = require jquery-3.3.1.min
--Changer de // = require bootstrap
à // = require bootstrap.bundle
Réexécutez l'application et vous avez terminé. (La barre de navigation s'effondre, mais je ne l'utilise pas, alors ignorez-la)
Modifions la vue index.gsp décrite précédemment.
grails-app/views/layouts/main.gsp
<head>
: <snip>
<asset:stylesheet src="application.css"/>
<asset:javascript src="application.js"/> <!--Déplacez la ligne écrite dans le corps dans la tête-->
: <snip>
</head>
: <snip>
grails-app/views/employee/index.gsp
: <snip>
<button class="btn btn-secondary" disabled="false" id="edit_button"><g:message code="default.edit.label" args="[entityName]" /></button>
: <snip>
Ce n'est pas grave si le bouton a le style Bootstrap 4 appliqué.
Ajoutons une fonction de filtre à l'écran de la liste des employés pour le rendre un peu plus pratique.
J'utiliserai DataTables pour ajouter la fonction de recherche au tableau affiché sur l'écran de liste cette fois.
Il y avait grails-datatables comme plugin Grails, mais installez la dernière version de DataTables comme bootstrap et jquery. Je déciderai.
Sélectionnez les éléments suivants sur la Page de téléchargement de DataTables pour télécharger le fichier.
Copiez les fichiers suivants du fichier téléchargé dans grails-app / assets / (javascripts | stylesheets) / en fonction du type.
Enfin, éditez grails-app / assets / application (Js | css). Les fichiers de destination requis décrits dans l'application. (Js | css) sont lus dans l'ordre à partir du haut, faites donc attention à l'ordre de description des packages avec des dépendances.
grails-app/assets/javascripts/application.js
: <snip>
//= require jquery-3.3.1.min
//= require bootstrap.bundle
//= require jquery.dataTables
//= require dataTables.bootstrap4
//= require_tree .
//= require_self
: <snip>
grails-app/assets/stylesheets/application.css
/*
: <snip>
*= require bootstrap
*= require dataTables.bootstrap4
*= require grails
*= require main
*= require mobile
*= require_self
: <snip>
*/
Vous êtes maintenant prêt à utiliser DataTables.
Appliquez DataTables aux tables sur l'écran de liste.
Pour appliquer DataTables, appliquez la méthode dataTable ()
au DOM qui pointe vers la table que vous souhaitez appliquer dans jQuery.
grails-app/views/employee/index.gsp
<!DOCTYPE html>
<html>
<head>
: <snip>
<script type="text/javascript">
/*Définir l'état du bouton d'édition en fonction de l'état du bouton radio*/
function setEditButtonStatusByRadioButton() {
var edit_button_id = "edit_button";
var radios = document.getElementsByName('id');
var checkedNum = 0;
radios.forEach(e => e.checked && checkedNum++);
if (checkedNum > 0) {
document.getElementById(edit_button_id).disabled = false;
} else {
document.getElementById(edit_button_id).disabled = true;
}
}
$(document).ready(function() {
$('#employeeindex').dataTable();
} );
</script>
</head>
<body>
: <snip>
<table id="employeeindex" class="display table table-striped">
: <snip>
</table>
: <snip>
</body>
</html>
Lorsque vous exécutez l'application, vous pouvez voir que DataTables a été appliqué.
Ici, vous pouvez voir que les fonctionnalités de pagination de DataTables et Grails sont devenues redondantes.
La fonctionnalité à activer dépend de la conception de l'application, mais cette fois, nous laisserons la fonction de pagination de Grails pour réduire la quantité de traitement des données.
Pour désactiver la fonction de pagination de DataTables, ajoutez le paramètre paging: true
à la méthode dataTable () comme décrit dans la page officielle (https://datatables.net/reference/option/paging). Je vais le passer.
#Appliquer DataTables au DOM Employeeindex sans pagination
$(document).ready(function() {
$('#employeeindex').dataTable({
"paging": false
});
} );
Enfin, modifiez la barre de navigation en haut de l'écran. De plus, modifiez le style en conséquence et ajoutez Font Awesome dans le CDN pour utiliser ICON.
grails-app/assets/stylesheets/main.css
/* NAVIGATION MENU */
.nav, nav {
zoom: 1;
}
.nav ul {
overflow: hidden;
padding-left: 0;
zoom: 1;
}
.nav li {
display: block;
float: left;
list-style-type: none;
margin-right: 0.5em;
padding: 0;
}
.nav a, nav a {
color: #666666;
display: block;
padding: 0.25em 0.7em;
text-decoration: none;
-moz-border-radius: 0.3em;
-webkit-border-radius: 0.3em;
border-radius: 0.3em;
}
.nav a:active, .nav a:visited, nav a:active, nav a:visited {
color: #666666;
}
.nav a:focus, .nav a:hover, nav a:focus, nav a:hover {
background-color: #999999;
color: #ffffff;
outline: none;
text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.8);
}
.no-borderradius .nav a:focus, .no-borderradius nav a:focus, .no-borderradius .nav a:hover, .no-borderradius nav a:hover {
background-color: transparent;
color: #444444;
text-decoration: underline;
}
.nav a.home, .nav a.list, .nav a.create, nav a.home, nav a.list, nav a.create {
background-position: 0.7em center;
background-repeat: no-repeat;
text-indent: 25px;
}
.nav a.home, nav a.home {
background-image: url(../images/skin/house.png);
}
.nav a.list, nav a.list {
background-image: url(../images/skin/database_table.png);
}
.nav a.create, nav a.create {
background-image: url(../images/skin/database_add.png);
}
.nav li.dropdown ul.dropdown-menu, nav li.dropdown ul.dropdown-menu {
background-color: #424649;
}
grails-app/assets/stylesheets/mobile.css
@media screen and (max-width: 480px) {
.nav, nav {
padding: 0.5em;
}
.nav li, nav li {
margin: 0 0.5em 0 0;
padding: 0.25em;
}
: <snip>
}
grails-app/views/layouts/main.gsp
<!doctype html>
<html lang="en" class="no-js">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<title>
<g:layoutTitle default="Grails"/>
</title>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<asset:link rel="icon" href="favicon.ico" type="image/x-ico" />
<asset:stylesheet src="application.css"/>
<asset:javascript src="application.js"/>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css" integrity="sha384-mzrmE5qonljUremFsqc01SB46JvROS7bZs3IO2EmfFsd15uHvIt+Y8vEf7N7fWAU" crossorigin="anonymous">
<g:layoutHead/>
</head>
<body>
<nav class="navbar-expand-lg pr-3 navbar navbar-default">
<a class="navbar-brand" href="/#">
<asset:image src="grails.svg" alt="Grails Logo"/>
</a>
<button class="navbar-toggler mx-2" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="fas fa-bars" style="font-size: 3rem;"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav ml-auto">
<g:pageProperty name="page.nav" />
</ul>
</div>
</nav>
<g:layoutBody/>
<div class="footer" role="contentinfo"></div>
<div id="spinner" class="spinner" style="display:none;">
<g:message code="spinner.alt" default="Loading…"/>
</div>
</body>
</html>
Large Display Size | Small Display Size |
---|---|
Jusqu'à présent, la base de données était mise à jour en définissant dbCreate: update
en référence au fichier modèle au démarrage de l'application, mais en raison des conditions limitées qui peuvent être modifiées et que les anciennes colonnes restent, plusieurs personnes Lors du développement d'une application, différentes personnes peuvent avoir des structures de base de données différentes.
Par conséquent, j'ai décidé de créer un fichier de migration et de créer une base de données à partir de celui-ci.
Utilisez le plug-in database-migration
pour effectuer la migration de la base de données dans Grails. (Le plugin database-migratation
utilise la bibliothèque Liquibase.)
La migration est gérée à l'aide d'un ou plusieurs fichiers journal des modifications écrits en Groovy DSL ou en XML Liquibase natif.
Les fichiers journaux des modifications ont un ID unique au niveau mondial. (L'ID contient le nom d'utilisateur de l'utilisateur qui a créé le journal des modifications)
Modifiez bundle.gradle
comme suit pour utiliser le plug-in database-migration
. (Modifiez la version de la fiche selon le cas)
Notez que bundle.gradle
est un fichier de configuration pour Gradle, et Gradle est un système d'automatisation de construction open source basé sur les concepts d'Apache Ant et d'Apache Maven. (Référence: Wikipedia> Gradle)
buildscript {
repositories {
: <snip>
}
dependencies {
: <snip>
classpath 'org.grails.plugins:database-migration:3.0.4' # database-Ajout du plug-in de migration
}
}
dependencies {
: <snip>
compile 'org.grails.plugins:database-migration:3.0.4'
compile 'org.liquibase:liquibase-core:3.5.5'
: <snip>
}
: <snip>
sourceSets {
main {
resources {
srcDir 'grails-app/migrations'
}
}
}
Définissez ensuite la base de données «dbCreate» sur «none».
Sinon, vous n'obtiendrez pas la différence lors de la création d'un fichier de migration avec l'option dbm-gorm-diff
.
grails-app/conf/application.yml
environments:
development:
dataSource:
dbCreate: none
url: jdbc:h2:./devDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
: <snip>
Ensuite, créez un fichier journal des modifications.
Vous pouvez choisir le format de description, mais j'utiliserai Groovy DSL.
Il existe deux façons de créer un journal des modifications, l'une provient de la base de données et l'autre de la classe de domaine. À l'heure actuelle, je pense que la base de données est automatiquement créée à partir de la classe de domaine au démarrage, alors sélectionnez la méthode pour créer le journal des modifications à partir de la base de données.
Comment créer un journal des modifications à partir d'une base de données au format Groovy DSL
$ grails dbm-generate-changelog changelog.groovy
: <snip>Les plugins seront téléchargés au besoin
:compileJava NO-SOURCE
:compileGroovy UP-TO-DATE
:buildProperties UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:findMainClass
:dbmGenerateChangelog
BUILD SUCCESSFUL
Total time: 16.478 secs
Ensuite, le journal des modifications suivant sera créé.
Journal des modifications(grails-app/migrations/changelog.groovy)
databaseChangeLog = {
changeSet(author: "tatsurou (generated)", id: "1537102923747-1") {
createTable(tableName: "EMPLOYEE") {
column(autoIncrement: "true", name: "ID", type: "BIGINT(19)") {
constraints(primaryKey: "true", primaryKeyName: "CONSTRAINT_7")
}
column(name: "VERSION", type: "BIGINT(19)") {
constraints(nullable: "false")
}
column(name: "NAME", type: "VARCHAR(255)") {
constraints(nullable: "false")
}
}
}
}
Vous pouvez maintenant créer la base de données en fonction du journal des modifications. (Seul le schéma de base de données est construit, aucune donnée n'est migrée)
À partir de maintenant, après avoir modifié la classe de domaine, vous créerez un journal des modifications manuellement ou automatiquement et exécuterez dbm-update
.
--add
, le journal des modifications sera enregistré séparément avec le nom de fichier spécifié, et il sera ajouté afin qu'il soit lu par include de changelog.groovy)
$ grails dbm-gorm-diff add_birth_column_to_employee.groovy --add
grails dbm-update
pour n'importe quel environnement (développement, test, production)La console Groovy est une application qui vous permet d'entrer et d'exécuter du code source Groovy. Vous pouvez également charger une classe de domaine implémentée dans une application Grails ou utiliser l'ORM de cette classe de domaine pour manipuler la base de données.
Vous pouvez démarrer la console Grails en exécutant la commande grails console.
Lancez la console groovy
$ cd ${répertoire des applications}
$ grails console
package grails.sample.app
def id = 1
def e = Employee.get(id)
if (e == null) {
println("Not found employee id " + id)
exit()
}
println("employee: " + e)
println("name: " + e.name)
e.name = 'test99'
e.save(flush: true)
Décrit les erreurs qui se produisent lors de l'exécution de la commande Grails et comment les traiter.
Could not acquire change log lock
Command execution error: Could not acquire change log lock. Currently locked by ${COMPUTER_NAME} (${IP_ADDRESS}) since 18/09/17 0:09
--Supprimer grails dbm-release-locks
ou DB
Recommended Posts