Я изучал проект liquibase и анализировал его преимущества как инструмента управления базами данных.
Мы создаем приложение под названием LiquibaseTryOuts. Структура проектов следующая:
Зависимости перечислены ниже
Я заметил, что документации по настройке liquibase с помощью ant-скриптов не так много. Поэтому я создал ant-скрипт для нашего приложения. Вот сценарий муравья:
<?xml version="1.0" encoding="UTF-8"?>
<project name="liquibase-sample">
<property file="liquibase.properties"/>
<path id="lib.path" >
<fileset dir="lib1" />
</path>
<target name="update-database">
<taskdef name="updateDatabase" classname="liquibase.ant.DatabaseUpdateTask"
classpathref="lib.path" />
<updateDatabase
changeLogFile="${changeLogFile}"
driver="${driver}"
url="${url}"
username="${username}"
password="${password}"
dropFirst="${dropfirst}"
classpathref="lib.path"/>
</target>
<target name="rollback-database">
<taskdef name="rollbackDatabase" classname="liquibase.ant.DatabaseRollbackTask"
classpathref="lib.path" />
<rollbackDatabase
changeLogFile="${changeLogFile}"
driver="${driver}"
url="${url}"
username="${username}"
password="${password}"
classpathref="lib.path"
rollbackTag="${tag}"
>
</rollbackDatabase>
</target>
<target name="tag">
<taskdef name="tagDatabase" classname="liquibase.ant.TagDatabaseTask"
classpathref="lib.path" />
<tagDatabase
changeLogFile="${changeLogFile}"
driver="${driver}"
url="${url}"
username="${username}"
password="${password}"
classpathref="lib.path"
tag="${tag}"
>
</tagDatabase>
</target>
<target name="generateChangeLog">
<taskdef name="generateChangeLogDatabase" classname="liquibase.ant.GenerateChangeLogTask"
classpathref="lib.path" />
<tagDatabase
outputFile="${outputFile}"
driver="${driver}"
url="${url}"
username="${username}"
password="${password}"
classpathref="lib.path"
>
</tagDatabase>
</target>
<target name="diff-database">
<taskdef name="diffDatabase" classname="liquibase.ant.DiffDatabaseTask"
classpathref="lib.path" />
<tagDatabase
driver="${driver}"
url="${url}"
username="${username}"
password="${password}"
baseUrl="${url}"
baseUsername="${username}"
baseUassword="${password}"
outputDiffFile="${outputDiffFile}"
classpathref="lib.path"
>
</tagDatabase>
</target>
</project>
Затем мы используем hibernate теперь, как и мой блог 30 мая мы используем hibernate с аннотациями JPA. Вот файл конфигурации:
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/liquibasetestdb</property>
<property name="connection.username">monty</property>
<property name="connection.password">some_pass</property>
<!– JDBC connection pool (use the built-in) –>
<property name="connection.pool_size">1</property>
<!– SQL dialect –>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!–<mapping package="liquibase.database.pojo"/>–>
<mapping class="liquibase.database.pojo.Users"/>
<!– <mapping resource="test/animals/orm.xml"/>–>
</session-factory>
</hibernate-configuration>
Теперь файлы классов для этого проекта совпадают с файлами, которые использовались для блога 30 мая с одним или двумя дополнительными файлами. Вот диаграмма UML:
Теперь нам нужны некоторые журналы изменений, которые соответствуют спецификациям ликвазы, они будут следующими
included.changelog.xml
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog/1.7"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog/1.7 http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-1.7.xsd">
<preConditions>
<dbms type="mysql"/>
</preConditions>
<changeSet id="1" author="gabriel">
<createTable tableName="news">
<column name="id" type="int" autoIncrement="true">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="title" type="varchar(50)"/>
</createTable>
</changeSet>
<changeSet id="2" author="gabriel" context="test">
<insert tableName="news">
<column name="title" value="Liquibase 0.8 Released"/>
</insert>
<insert tableName="news">
<column name="title" value="Liquibase 0.9 Released"/>
</insert>
</changeSet>
<changeSet id="3" author="gabriel" context="demo">
<insert tableName="news">
<column name="title" value="Liquibase 1.0 Released"/>
</insert>
</changeSet>
</databaseChangeLog>
Далее включено2.changelog.xml
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog/1.7"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog/1.7 http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-1.7.xsd">
<preConditions>
<dbms type="mysql"/>
</preConditions>
<changeSet id="1" author="gabriel">
<createTable tableName="records">
<column name="id" type="int" autoIncrement="true">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="title" type="varchar(50)"/>
</createTable>
</changeSet>
<changeSet id="2" author="gabriel" context="test">
<insert tableName="records">
<column name="title" value="Liquibase 0.8 Released"/>
</insert>
<insert tableName="records">
<column name="title" value="Liquibase 0.9 Released"/>
</insert>
</changeSet>
<changeSet id="3" author="gabriel" context="demo">
<insert tableName="records">
<column name="title" value="Liquibase 1.0 Released"/>
</insert>
</changeSet>
</databaseChangeLog>
included3.changelog.xml
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog/1.7"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog/1.7 http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-1.7.xsd">
<preConditions>
<dbms type="mysql"/>
</preConditions>
<changeSet id="1" author="gabriel">
<createTable tableName="register">
<column name="id" type="int" autoIncrement="true">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="title" type="varchar(50)"/>
<column name="name" type="varchar(100)"/>
</createTable>
</changeSet>
<changeSet id="2" author="gabriel">
<dropTable tableName="register"/>
<rollback changeSetId="1" changeSetAuthor="gabriel"/>
</changeSet>
</databaseChangeLog>
И включенный4.changelog.xml
И нам нужен файл liquibase.properties:
changeLogFile=included4.changelog.xml
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/liquibasetestdb
username=monty
password=some_pass
#for diff between two databases
baseUrl=jdbc:mysql://localhost:3306/liquibasetestdb
baseUsername=monty
basePassword=some_pass
dropFirst=false
tag=version 1.4
outputFile=outputFile.xml
outputDiffFile=outputFile.txt
Когда мы добавим файл в наш редактор мувиков затмения, это будет вид:
Теперь, запустив откат-базу данных, в качестве примера получаем:
Buildfile: /home/gabriel/eclipse/eclipse/opensource-workspace/LiquibaseTryOuts/build.xml
rollback-database:
[rollbackDatabase] Lock Database
[rollbackDatabase] Successfully acquired change log lock
[rollbackDatabase] included4.changelog.xml is using schema version 1.7 rather than version 1.9
[rollbackDatabase] Reading from `DATABASECHANGELOG`
[rollbackDatabase] Release Database Lock
[rollbackDatabase] Successfully released change log lock
BUILD SUCCESSFUL
Total time: 6 seconds
Теперь в моем проекте (который имеет классы, аналогичные проекту моего последнего блога 30 мая), я добавил два дополнительных класса HibernateSchemaTests и LiquibaseSchemaTests.
Вот полный список HibernateSchemaTests:
Here is the full listing of HibernateSchemaTests:
/**
*
*/
package liquibase.database.tests;
import java.util.ArrayList;
import java.util.List;
import junit.framework.TestCase;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.cfg.Configuration;
import org.hibernate.dialect.Dialect;
import org.hibernate.tool.hbm2ddl.DatabaseMetadata;
/**
* @author gabriel
*
*/
public abstract class HibernateSchemaTests extends TestCase {
private AnnotationConfiguration ac;
public void assertDatabaseSchema() throws Exception {
String[] script = generateScript();
List differences = getSignificantDifferences(script);
assertTrue(differences.toString(), differences.isEmpty());
}
private String[] generateScript() throws Exception {
// Configuration cfg = getConfiguration();
// SessionFactory sessionFactory = cfg.buildSessionFactory();
// Session session = sessionFactory.openSession();
ac = new AnnotationConfiguration().configure();
SessionFactory sessionFactory = ac.buildSessionFactory();
Session session = sessionFactory.openSession();
try {
Dialect dialect = getDatabaseDialect();
DatabaseMetadata dbm = new DatabaseMetadata(session.connection(),
dialect);
String[] existingScript = ac.generateSchemaCreationScript(dialect);
for (String s : existingScript)
System.out.println(s);
String[] script = ac.generateSchemaUpdateScript(dialect, dbm);
return script;
} finally {
session.close();
}
}
protected Dialect getDatabaseDialect() throws Exception {
return (Dialect) Class.forName(
getConfiguration().getProperty("hibernate.dialect"))
.newInstance();
}
private List getSignificantDifferences(String[] script) {
List differences = new ArrayList();
for (int i = 0; i < script.length; i++) {
String line = script[i];
if (line.indexOf("add constraint") == -1)
differences.add(line);
}
return differences;
}
protected Configuration getConfiguration() throws HibernateException {
return ac;
}
}
Now we have the listing of LiquibaseSchemaTests:
/**
*
*/
package liquibase.database.tests;
/**
* @author gabriel
*
*/
public class LiquibaseSchemaTest extends HibernateSchemaTests {
/**
*
*/
public LiquibaseSchemaTest() {
// TODO Auto-generated constructor stub
}
public void test() throws Exception {
assertDatabaseSchema();
}
}
Теперь запуск этих тестов может также дать нам diff-log между схемой из наших файлов отображения (где мы использовали аннотации) и фактически базой данных.
Так в чем же разница между двумя методами? Хорошо, Liquibase дает вывод XML и может пометить базу данных. это с открытым исходным кодом. Использование hibernate является мощным, но только для разработчиков, а как насчет администраторов баз данных и других пользователей? Также при использовании liquibase разработчики должны поддерживать связь с администратором баз данных, чтобы обеспечить бесперебойную работу. Liquibase обладает преимуществом множества стабильных встроенных функций.
Интеграция муравьиных сценариев для liquibase в maven может дать хорошую функциональность
Смотрите этот пост в блоге Габриэля Джеремии Кэмпбелла:
http://gabrieljeremiahcampbell.wordpress.com/2010/06/06/liquibase-and-hibernate/