Created
April 19, 2018 17:45
-
-
Save DanyelMorales/a3389e7ecda0e5b9adf7adddb09b002e to your computer and use it in GitHub Desktop.
Junit Rule to save ORACLE SEQUENCES
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class FooTest { | |
/** | |
* Sequence saving | |
*/ | |
public static SequenceJunitRule sequences = new SequenceJunitRule(); | |
/** | |
* Restore the sequences on Class DIE. | |
*/ | |
@AfterClass | |
public static void tearDownClass() { | |
if (sequences.isConfigured() && !sequences.validateOnce()) { | |
sequences.restoreSequences(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package YOUR_PACK; | |
import java.util.ArrayList; | |
import java.util.HashMap; | |
import org.hibernate.Query; | |
import org.hibernate.Session; | |
import org.hibernate.SessionFactory; | |
import org.hibernate.cfg.AvailableSettings; | |
import org.hibernate.cfg.Configuration; | |
import org.junit.rules.ExternalResource; | |
/** | |
* JUNIT Rule to preserve ORACLE SEQUENCES | |
* | |
* This RULE can be used for each test cases using @Rule or as @ClassRule, it's | |
* possible to use this rule as a single POJO too. | |
* @author Daniel Vera | |
*/ | |
public class SequenceJunitRule extends ExternalResource { | |
private final HashMap<String, String> sequenceBuffer = | |
new HashMap<String, String>(); | |
private final ArrayList<String> sequenceName = new ArrayList<String>(); | |
private Configuration config; | |
private String ddldefmode = "create"; | |
private Session temporalSession; | |
private SessionFactory temporalFactory; | |
private boolean saveOnce = false; | |
private boolean isAlreadySaved = false; | |
/** | |
* For static tear downs it's wise to set this flag as true. | |
* | |
* @param val | |
* true if we need to execute the after and before rules just one | |
* time. Otherwise for each test case will be invoked the before | |
* and after methods. | |
*/ | |
public SequenceJunitRule isOnce(Boolean val) { | |
this.saveOnce = val; | |
return this; | |
} | |
/** | |
* @param config | |
* Configuration from the factory of Rules, the config will | |
* handle | |
* the configuration for hibernate. | |
*/ | |
public SequenceJunitRule setConfiguration(Configuration config) { | |
config.setProperty(AvailableSettings.HBM2DDL_AUTO, "validate"); | |
this.config = config; | |
temporalFactory = config.buildSessionFactory(); | |
temporalSession = temporalFactory.openSession(); | |
return this; | |
} | |
/** | |
* @param ddldefmode | |
* Default mode for ddl operations on hibernate | |
*/ | |
public SequenceJunitRule setDDLMode(String ddldefmode) { | |
this.ddldefmode = ddldefmode; | |
return this; | |
} | |
/** | |
* @param name | |
* Collection of existing sequence names | |
*/ | |
public SequenceJunitRule addSequence(ArrayList<String> name) { | |
this.sequenceName.addAll(name); | |
return this; | |
} | |
/** | |
* @param name | |
* Sequence name to be saved | |
*/ | |
public SequenceJunitRule addSequence(String name) { | |
this.sequenceName.add(name); | |
return this; | |
} | |
/** | |
* @return true if the the once flag is not turned on and at the same time | |
* the sequences are not already saved. | |
*/ | |
public boolean validateOnce() { | |
if (this.saveOnce && this.isAlreadySaved) { | |
return false; | |
} | |
return true; | |
} | |
/** | |
* @return the sequence container | |
*/ | |
public ArrayList<String> getSequence() { | |
return this.sequenceName; | |
} | |
/** | |
* @return the sequence buffer used to store values | |
*/ | |
public HashMap<String, String> getSequenceBuffer() { | |
return this.sequenceBuffer; | |
} | |
/** | |
* Restore the sequences stored in buffer. | |
*/ | |
public SequenceJunitRule restoreSequences() { | |
this.verifySession(); | |
for (String sequence : this.sequenceName) { | |
if (!this.sequenceBuffer.containsKey(sequence)) { | |
continue; | |
} | |
String val = this.sequenceBuffer.get(sequence); | |
this.restoreSequence(sequence, val, this.temporalSession); | |
} | |
temporalSession.close(); | |
return this; | |
} | |
/** | |
* Create the sequences backup before hibernate drop operations. | |
*/ | |
private SequenceJunitRule backupSequences(Session tmp) { | |
this.sequenceBuffer.clear(); | |
for (String sequence : this.sequenceName) { | |
System.out.println("SAVING SEQUENCE: " + sequence); | |
this.backupSequence(sequence, tmp); | |
} | |
return this; | |
} | |
/** | |
* Verify if the current session factory has a session open. Other wise the | |
* session is open and assigned to the temporalSession flag. | |
*/ | |
public void verifySession() { | |
if (!this.temporalSession.isOpen()) { | |
this.temporalSession = this.temporalFactory.openSession(); | |
} | |
} | |
/** | |
* @param seqname | |
* Sequence name to be saved | |
* @param session | |
*/ | |
public SequenceJunitRule backupSequence(String seqname, Session session) { | |
if (seqname == null || seqname.equals("")) { | |
return null; | |
} | |
String sqquery = | |
String.format("select %s.nextval as num from dual", seqname); | |
Query query = session.createSQLQuery(sqquery); | |
String result = query.uniqueResult() + ""; | |
this.sequenceBuffer.put(seqname, result + ""); | |
return this; | |
} | |
/** | |
* Restore the sequence | |
* | |
* @param seqname | |
* sequence name to be restored | |
* @param seqval | |
* Sequence value to be injected | |
*/ | |
public SequenceJunitRule restoreSequence(String seqname, String seqval, | |
Session session) { | |
String drop = "DROP SEQUENCE %s"; | |
String create = | |
"CREATE SEQUENCE %s START WITH %s INCREMENT BY 1 MINVALUE 0 NOCACHE "; | |
Query q = session.createSQLQuery(String.format(drop, seqname)); | |
q.executeUpdate(); | |
Query q2 = | |
session.createSQLQuery(String.format(create, seqname, seqval)); | |
q2.executeUpdate(); | |
System.out.println("RESTORING SEQUENCE: " + seqname + " value: " | |
+ seqval); | |
return this; | |
} | |
/** | |
* @return true if the required configurations are setted otherwise false. | |
*/ | |
public boolean isConfigured() { | |
if (this.ddldefmode == null || this.config == null | |
|| this.temporalSession == null | |
|| this.sequenceName.size() == 0) { | |
return false; | |
} | |
return true; | |
} | |
/** | |
* Before any test case Backup the sequences on the container. | |
*/ | |
@Override | |
public void before() throws Throwable { | |
if (!isConfigured() || !validateOnce()) { | |
return; | |
} | |
this.backupSequences(this.temporalSession); | |
config.setProperty(AvailableSettings.HBM2DDL_AUTO, ddldefmode); | |
this.isAlreadySaved = true; | |
} | |
/** | |
* After a test case, restore the sequences. | |
*/ | |
@Override | |
protected void after() { | |
if (!isConfigured() || !validateOnce()) { | |
return; | |
} | |
this.restoreSequences(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment