Apply migration on multiple schemas using Java and Liquibase - postgresql

I'm trying to apply migration over my multi tenant system where I have one database with multiple schemas,
And I do so by first getting all the tenants then loop over them and execute the update on liquibase after changing the schema, but it seems that the schema is not changed cause after performing the migration on the first tenant the second tenant throws an error complaining about table already exist.
#Override
#SneakyThrows
public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
Connection connection = null;
Statement statement = null;
Liquibase liquibase = null;
try {
connection = dataSource.getConnection();
statement = connection.createStatement();
ResultSet result = statement.executeQuery("SELECT nspname FROM pg_namespace WHERE nspname like 'tenant_%'");
List<String> schemas = new ArrayList<>();
while (result.next()) {
schemas.add(result.getString(1));
}
for (String schemaName:schemas) {
connection.setSchema(schemaName);
Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(connection));
database.setDefaultSchemaName(schemaName);
log.info("Schema Name: {}",connection.getSchema());
liquibase = new Liquibase(CHANGE_LOG_FILE, new ClassLoaderResourceAccessor(), database);
liquibase.update(new Contexts(), new LabelExpression());
}
} catch (SQLException | DatabaseException e) {
e.printStackTrace();
}finally {
if(liquibase!=null) {
liquibase.close();
}
if(statement!=null&&!statement.isClosed()) {
statement.close();
}
if(connection!=null&&!connection.isClosed()){
connection.close();
}
}
}
Note: the reason I made it in different loops and not using `try-with-resource` is that the connection closes after getting the first row of the result set and updating the database so I had to close it myself

Related

Column <<column_name>> not found when using ADO-NET connection for Postgresql in insert query

I have problem when using ADO.NET connection for PostgreSQL. I have tried this query using PSQLODBC driver 12.000.000 both ANSI and Unicode. I use PostgreSQL v.9.5. I notice the column name has "_" in its name.
When I use the Select query, the connection successfully execute it. The query return variables as I want.
using (OdbcConnection conn = (OdbcConnection)Dts.Connections["XXX"].AcquireConnection(Dts.Transaction))
{
try
{
if (conn.State != ConnectionState.Open)
{
conn.Open();
}
}
catch (Exception e)
{
String err = e.Message.ToString();
Console.WriteLine(err);
}
try
{
OdbcCommand cmd = new OdbcCommand();
cmd.Connection = conn;
cmd.CommandType = CommandType.Text;
cmd.CommandText = "SELECT XX FROM <<table>> where <<params>>";
...
OdbcDataReader rdd = cmd.ExecuteReader();
while (rdd.Read())
{
<<read operation here>>;
}
conn.Close();
}
catch (Exception ers)
{
<<catch operation here>>;
}
}
But when I use Insert query, it failed to check the column name, even the column are exist in my PostgreSQL tables:
using (OdbcConnection conn2 = (OdbcConnection)Dts.Connections["OJK_REPORTING_DEV"].AcquireConnection(Dts.Transaction))
{
try
{
if (conn2.State != ConnectionState.Open)
{
conn2.Open();
}
}
catch (Exception e)
{
string x = e.Message.ToString();
}
try
{
OdbcCommand cmd = new OdbcCommand();
cmd.Connection = conn2;
cmd.CommandType = CommandType.Text;
cmd.CommandText = "INSERT INTO <<table>>(<<column>>)VALUES(<<params>>)";
<<cmd.Parameters.AddWithValue here>>;
cmd.ExecuteNonQuery();
conn2.Close();
}
catch (Exception e)
{
<<exception catch here>>;
}
}
When I debug this line, I get this error:
ERROR[42703] ERROR: column <> not found, error while executing the query
Right, after several research, I've got an answer. Since i use PostgreSQL ODBC, the query parameters are not using #<name> inside the query, but using ?, so you need to formulate the query like
INSERT INTO <TABLE_NAME> (<COLUMNS>) VALUE ?
and call the parameters
cmd.AddWithValue("#<name>",<value>)

How to commit a transaction on multiple sql queries in Rx-java2 jdbc?

I am trying to insert sql records into multiple records with rxjava2-jdbc. Please let me know how can I achieve that. I tried below steps but it was unsuccessful.
Case 1)
public class DatabaseRepository {
private Database db;
public DatabaseRepository() throws Exception{
NonBlockingConnectionPool pool =
Pools.nonBlocking()
.maxPoolSize(Runtime.getRuntime().availableProcessors() * 5)
.connectionProvider(ConnectionProvider.from("jdbc:oracle:thin:#//rcld19-scan.test.com:1522/TGCD01", "test", "testPassword"))
.build();
this.db = Database.from(pool);
}
public Flowable<Integer> insertIntoMultipleTables() {
Flowable<Integer> insertIntoEmployee=db.update(insert into employee(name, designation) values ("Employee_1","Manager"))
.counts()
.doOnError(e -> {
log.error("Exception while inserting record to employee table: {}", e.getMessage());
});
return db.update(insert into department(name, no_of_employees) values("Management",1))
.dependsOn(insertIntoEmployee)
.counts()
.doOnError(e -> {
log.error("Exception while inserting record to department table: {}", e.getMessage());
});
}
}
I am trying to insert into multiple tables as part of a single transaction. In this case, failure on insertion of record into department table will not rollback data from first table
Case 2)
public class DatabaseRepository {
private Database db;
public DatabaseRepository() throws Exception{
NonBlockingConnectionPool pool =
Pools.nonBlocking()
.maxPoolSize(Runtime.getRuntime().availableProcessors() * 5)
.connectionProvider(ConnectionProvider.from("jdbc:oracle:thin:#//rcld19-scan.test.com:1522/TGCD01", "test", "testPassword"))
.build();
this.db = Database.from(pool);
}
public Flowable<Tx<Integer>> insertIntoMultipleTables(){
Flowable<Tx<Integer>> insertIntoEmployee= db.update(insert into employee(name, designation) values ("Employee_1","Manager"))
.transacted()
.counts()
.flatMap(tx ->{
return tx.update(insert into department(name, no_of_employees) values("Management",1))
.counts()
.doOnError(e -> log.error("Exception while inserting record to department table: {}",
e.getMessage()));
})
.doOnError(e -> {
log.error("Exception while inserting record to employee table: {}", e.getMessage());
});
}
}
This code is not working as a transaction. Any SQL error in one of the insertion, is not rolling back the records inserted into other table
My requirement is using reactive java2-jdbc i need to insert records into multiple database tables, I am not able to find any valid examples in Git. Please let me know if I need to do anything differently.

Duplicate primary key when inserting using EF5

When I am trying to insert some value using this code I am getting the error below:
{"ORA-00001: unique constraint (NCOREDB.PK_NCORE_CASH_IN) violated"}
I am using EF5 and Oracle as Database.It was working fine a while ago. I can not update my EF because of some dependency issue.
using (TransactionScope transactionScope = new TransactionScope())
{
try
{
NCORE_TRN_CASH_IN_INFO OBJ_NCORE_TRN_CASH_IN_INFO = new NCORE_TRN_CASH_IN_INFO();
int id = Convert.ToInt32(Obj_nCoreEntities.NCORE_TRN_CASH_IN_INFO.Max(t => (int?)t.CASH_IN_ID)) + 1;
OBJ_NCORE_TRN_CASH_IN_INFO.CASH_IN_ID = id;
//Inserting other value here
Obj_nCoreEntities.NCORE_TRN_CASH_IN_INFO.Add(OBJ_NCORE_TRN_CASH_IN_INFO);
Obj_nCoreEntities.SaveChanges();
transactionScope.Complete();
}
catch (DbEntityValidationException dbEx)
{
transactionScope.Dispose();
string inner = ExceptionExtendedMethods.GetDBInnerExceptions(dbEx);
return inner;
}
catch (Exception ex)
{
transactionScope.Dispose();
string inner4 = ExceptionExtendedMethods.GetInnerExceptions(ex);
return inner4;
}
}

Entity code first migration try to drop old table

I added some entities to my context.And then i migrate them as a below with my tool
using (var db = new TourismContext())
{
if (db.Database.CompatibleWithModel(true))
return;
var initializer = new MigrateDatabaseToLatestVersion<TourismContext, TourismContextConfiguration>();
initializer.InitializeDatabase(db);
//and other code.....
it drop tables which i removed them from my context.And it works.it is compatible.But after 20 minutes it says non compatible.it want to drop some tables but this tables are not existing
what should i do?
although i remove that tables from context and migrate it(migration tool drop that tables from database) why it want to drop them again and again?the tables that migration want to drop is not existing in database.because i migrate them so migration tool drop them.Where migration get that tables info to drop?
this is my __MigrationHistory
SELECT TOP 1000 [MigrationId]
,[Model]
,[ProductVersion]
,[CreatedOn]
FROM [TOURISM_new1].[dbo].[__MigrationHistory]
there is no droping tables info here
here is my migration tool.There is two buton.one show scritp which will show executed script(script button) other is micration buton.it migrate
private void MigrateButton_Click(object sender, EventArgs e)
{
try
{
using (var db = new TourismContext())
{
if (db.Database.CompatibleWithModel(true))
return;
var initializer = new MigrateDatabaseToLatestVersion<TourismContext, TourismContextConfiguration>();
initializer.InitializeDatabase(db);
foreach (Constants.SecurityFeatureIdentifier securityFeatureIdentifier in Enum.GetValues(typeof(Constants.SecurityFeatureIdentifier)))
{
if (db.SecurityFeatures.All(sf => sf.SecurityFeatureIdentifierID != (int)securityFeatureIdentifier))
{
db.SecurityFeatures.Add(new SecurityFeature { SecurityFeatureIdentifier = securityFeatureIdentifier });
db.SaveChanges();
}
}
}
statusLabel.Text = "Compatible";
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
private void ScriptButton_Click(object sender, EventArgs e)
{
try
{
using (var db = new TourismContext())
{
if (db.Database.CompatibleWithModel(true))
return;
var migrator = new DbMigrator(new TourismContextConfiguration());
var scriptor = new MigratorScriptingDecorator(migrator);
scriptControl.Text = scriptor.ScriptUpdate(null, null);
foreach (Constants.SecurityFeatureIdentifier securityFeatureIdentifier in Enum.GetValues(typeof(Constants.SecurityFeatureIdentifier)))
{
if (db.SecurityFeatures.All(sf => sf.SecurityFeatureIdentifierID != (int)securityFeatureIdentifier))
{
db.SecurityFeatures.Add(new SecurityFeature { SecurityFeatureIdentifier = securityFeatureIdentifier });
db.SaveChanges();
}
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
You need to get your database model in sync with your code first model. You could either comment out the obsolete code from the Up() method of the migration and do an update-database or you can remove the pending migration and do Add-Migration MyBaseline –IgnoreChanges with an update-database. Now you should be compatible until you change your model.
https://msdn.microsoft.com/en-us/data/dn579398.aspx?f=255&MSPPError=-2147217396#option1

How update DB table with DataSet

I am begginer with ADO.NET , I try update table with DataSet.
O client side I have dataset with one table. I send this dataset on service side (it is ASP.NET Web Service).
On Service side I try update table in database, but it dont 't work.
public bool Update(DataSet ds)
{
SqlConnection conn = null;
SqlDataAdapter da = null;
SqlCommand cmd = null;
try
{
string sql = "UPDATE * FROM Tab1";
string connStr = WebConfigurationManager.ConnectionStrings["Employees"].ConnectionString;
conn = new SqlConnection(connStr);
conn.Open();
cmd=new SqlCommand(sql,conn);
da = new SqlDataAdapter(sql, conn);
da.UpdateCommand = cmd;
da.Update(ds.Tables[0]);
return true;
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (conn != null)
conn.Close();
if (da != null)
da.Dispose();
}
}
Where can be problem?
It is better to look how really ADO.Net dataset works.
http://support.microsoft.com/kb/308507