For example let's see work with Trades managed some Users who can cteates Trades, makes Offers and signing Contracts.
First - let's initialize Datascooter: We must to download org.datascooter-..plugin-pack.zip and unzip it into any
directory. Start Eclipse and in the PackageExplorer - from context menu select - Import - Existing projects into workspace
and select the directory with unpacked plugins, check Copy projects into workspace. After completing import open plugin
org.datascooter.test and in the package org.datascooter.test select a class TradeTest. In the file TradeTest you
must to change "[you file path]/datascooter.properties" according with file path in you computer. And make RunAs...
JUnit Plugin Test. And Datascooter makes a couple of hundred complicated database operations in tenth of second.
If you wos not tuch datasource.properties in the root directory of plugin-
name=h2
contextId=h2
url=jdbc:h2:file:C:/my/test/data;LOCK_TIMEOUT=20000
user=sa
password=
current=true
It will be a small and fast database - H2.
Now let's to see under the hood:
1.First - we must to initialize datascooter:
If it is used in the eclipse environment - we should use Eclipse... providers
DataScooter.start(
true,
"[you file path]/datascooter.properties",
new EclipseBuilderProvider(),
new EclipseConnectorProvider(),
new EclipseDataSourceProvider(),
new EclipseMappingProvider());
If in the simple java project- XML... providers
DataScooter.start(
true,
"[you file path]/datascooter.properties",
new XMLBuilderProvider("[you file path].xml"),
new XMLConnectorProvider("[you file path].xml"),
new XMLDataSourceProvider("[you file path].xml"),
new XMLMappingProvider("[you file path].xml"));
Parameter 'true' talks datascooter to validate tables after start - check existence and compliance
of the fields and mapped attributes and existence getters and setters and to create it if it not exists. Sure-
datascooter it is not purposed as replacement of the database admin, so it use only minimum required set of SQL DDL
clauses and precision customization it is you obligation.
TestUtils.dropAll(DataScooter.getDefault());
Drops all tables for clear experimet. Under the hood it looks like:
public static void clearAll(IDataManager manager) throws EntityNotMappedException,
SQLException, BuildClauseException, IOException {
manager.clear(Trade.class.getName());
manager.clear(Contract.class.getName());
manager.clear(Offer.class.getName());
manager.clear(User.class.getName());
}
Here we command to drop all tables for some entities
DataScooter.getDefault().verifyTables(true);
We verify tables - it will be created over again.
public void createUsers() {
user1 = new User("aa", "aaa");
user2 = new User("aa", "sss");
user3 = new User("aa", "aaa");
user4 = new User("aa", "aaa");
DataScooter.getDefault().save(user1);
DataScooter.getDefault().save(user2);
DataScooter.getDefault().save(user3);
DataScooter.getDefault().save(user4);
}
Создаем пользователей и сохраняем их в базу
public void createTrades() {
trade1 = new Trade("trade1", "cart", 10L, new Date(), new Date(), user1.getId());
trade2 = new Trade("trade2", "car", 10L, new Date(), new Date(), user4.getId());
trade3 = new Trade("trade3", "track", 10L, new Date(), new Date(), user2.getId());
trade4 = new Trade("trade4", "car", 10L, new Date(), new Date(), user3.getId());
DataScooter.getDefault().save(trade1);
DataScooter.getDefault().save(trade2);
DataScooter.getDefault().save(trade3);
DataScooter.getDefault().save(trade4);
DataScooter.getDefault().save(new ChildTrade(trade1, "177"));
DataScooter.getDefault().save(new ChildTrade(trade2, "2"));
DataScooter.getDefault().save(new ChildTrade(trade2, "2"));
DataScooter.getDefault().save(new ChildTrade(trade4, "0"));
DataScooter.getDefault().save(new ChildTrade(trade4, "44"));
}
Create trades and save it again in the last strings creates special types of trades for illustration
mapping if inheritance. Let's tald about it later.
public void createOffers() {
offer1 = new Offer("off1", trade1.getId(), 55L, new Date(), new Date(), user4.getId());
offer2 = new Offer("off2", trade1.getId(), 55L, new Date(), new Date(), user2.getId());
offer3 = new Offer("off3", trade2.getId(), 55L, new Date(), new Date(), user2.getId());
offer4 = new Offer("off4", trade4.getId(), 55L, new Date(), new Date(), user2.getId());
DataScooter.getDefault().save(offer1);
DataScooter.getDefault().save(offer2);
DataScooter.getDefault().save(offer3);
DataScooter.getDefault().save(offer4);
}
Create and save offers for a trades a code of class 'Offer' looks like:
package org.datascooter.test.example;
import java.util.Date;
import org.datascooter.impl.Data;
public class Offer extends Data {
private static final long serialVersionUID = -7688647132004333854L;
public String name;
public String tradeId;
public Long price;
public Date start;
public Date stop;
public String userId;
public Offer() {
}
public Offer(String name, String tradeId, Long price, Date start, Date stop, String userId) {
this.name = name;
this.tradeId = tradeId;
this.price = price;
this.start = start;
this.stop = stop;
this.userId = userId;
}
@Override
public String toString() {
return name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTradeId() {
return tradeId;
}
public void setTradeId(String tradeId) {
this.tradeId = tradeId;
}
public Long getPrice() {
return price;
}
public void setPrice(Long price) {
this.price = price;
}
public Date getStart() {
return start;
}
public void setStart(Date start) {
this.start = start;
}
public Date getStop() {
return stop;
}
public void setStop(Date stop) {
this.stop = stop;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
}
This is a mapping of it class:
You must not hard work with XML tags - just fill a form. Here you may to see how
to map a simple attributes and a references to another classes
public void createContracts() {
contract1 = new Contract("text1", trade1.getId(), offer1.getId());
contract2 = new Contract("text2", trade3.getId(), offer2.getId());
contract3 = new Contract("text3", trade2.getId(), offer3.getId());
contract4 = new Contract("text4", trade4.getId(), offer4.getId());
DataScooter.getDefault().save(contract1);
DataScooter.getDefault().save(contract2);
DataScooter.getDefault().save(contract3);
DataScooter.getDefault().save(contract4);
}
Create and to save contracts between a owners of a trades and owners of a winned offer
public void testReferenceInvoke() {
assertTrue(trade1.getUser().equals(user1));
List list = trade1.getOfferList();
List contractList = trade1.getContractList();
}
Here we check a ReferenceInvoker - standart method for invoking a referenced objects.
It call may be take place inside method of object or in the aspect(AspectJ) intercepts this call.
It let invoke referenced entities if it are mapped via 'ReferenceAttribute' or
'CrossReferenceAttribute'.
By example method of the trade may raturn all offers received for a trade - this items are stored in the database,
not in this trade.
public void testList() throws EntityNotMappedException, WrongMethodException,
SQLException, BuildClauseException, IOException {
assertTrue("Count of trades: " + DataScooter.getDefault().list
(Trade.class.getName()).size(), (DataScooter.getDefault().list(
Trade.class.getName()).size() == 4));
assertTrue((DataScooter.getDefault().list(Offer.class.getName()).size() == 4));
assertTrue((DataScooter.getDefault().list(Contract.class.getName()).size() == 4));
assertTrue((DataScooter.getDefault().list(User.class.getName()).size() == 4));
}
Here we test invoking a list of objects
public void testFirst() throws EntityNotMappedException, WrongMethodException,
SQLException, BuildClauseException, IOException {
assertTrue(((Trade) DataScooter.getDefault().first(Trade.class.getName(),
"userId", user1.getId())).equals(trade1));
}
Here we test invoking the first object satisfying some conditions
public void testSelectCross() throws EntityNotMappedException, WrongMethodException,
SQLException, BuildClauseException, IOException {
DataSnip dataSnip = DataSnip.select(Offer.class.getName());
dataSnip.join(Contract.class.getName()).join(Trade.class.getName()).where("userId", user1.getId());
assertTrue(((Offer) DataScooter.getDefault().first(dataSnip)).getId().equals(offer1.getId()));
dataSnip = DataSnip.select(Trade.class.getName());
dataSnip.join(Contract.class.getName()).join(Offer.class.getName()).where("userId", user2.getId());
List dataList = DataScooter.getDefault().list(dataSnip);
assertTrue(dataList.contains(trade2));
assertTrue(dataList.contains(trade3));
assertTrue(dataList.contains(trade4));
}
Here we test invoking offer on the trade with contract from trade owner 'user1'. Or trade
for which yet signed a contract by offer from 'user2'.
public void testFetchByResult() throws EntityNotMappedException {
DataSnip dataSnip = DataSnip.select(Trade.class.getName());
dataSnip.whereId(trade1.getId());
dataSnip.fetchByResult(Contract.class.getName()).fetchByResult(Offer.class.
getName()).fetchByResult(User.class.getName());
Snip snip = DataScooter.getDefault().retrieve(dataSnip);
assertTrue("Wrong name: " + snip.getData()[0][1], snip.getData()[0][1].equals("trade1"));
assertTrue(snip.getFetch()[0].getData()[0][1].equals("text1"));
assertTrue(snip.getFetch()[0].getFetch()[0].getData()[0][1].equals("off1"));
assertTrue(snip.getFetch()[0].getFetch()[0].getFetch()[0].getData()[0][1].equals("aa"));
DataScooter.getDefault().deleteSnip(snip);
Snip snipDeleted = DataScooter.getDefault().retrieve(dataSnip);
assertTrue(snipDeleted.getData().length == 0);
DataScooter.getDefault().saveSnip(snip);
snip = DataScooter.getDefault().retrieve(dataSnip);
assertTrue(snip.getData()[0][1].equals("trade1"));
assertTrue(snip.getFetch()[0].getData()[0][1].equals("text1"));
assertTrue(snip.getFetch()[0].getFetch()[0].getData()[0][1].equals("off1"));
assertTrue(snip.getFetch()[0].getFetch()[0].getFetch()[0].getData()[0][1].equals("aa"));
}
And here we want invoke a trade with id 'trade1.getId()' and invoke all the contracts for this trade,
all offers with contracts to this trade and all users who made this offers-
Snip snip = DataScooter.getDefault().retrieve(dataSnip);
And we receive all it hierarchy of objects inside of object 'Snip' - only one request to datascooter!
DataScooter.getDefault().deleteSnip(snip);
Now let's delete this hierarchy whole from a database by one click...
DataScooter.getDefault().saveSnip(snip);
Here let's again to save this hierarchy into database by one click and check all this objects -
it are again on-site! It is unique possibility only from datascooter!
public void testFetch() throws EntityNotMappedException {
DataSnip dataSnip = DataSnip.select(Trade.class.getName());
dataSnip.whereId(trade1.getId());
dataSnip.fetch(Contract.class.getName());
dataSnip.fetch(Offer.class.getName());
dataSnip.fetch(User.class.getName());
Snip snip = DataScooter.getDefault().retrieve(dataSnip);
assertTrue(snip.getData()[0][1].equals("trade1"));
assertTrue(snip.getFetch()[0].getData()[0].length == 4);
assertTrue(snip.getFetch()[0].getData()[1].length == 4);
assertTrue(snip.getFetch()[0].getData()[2].length == 4);
}
Here we just to select from databse specified trade and all required for a remote working - a list of contracts,
list of offers and list of users - binded or not with this trade
public void testUpdate() throws EntityNotMappedException, WrongMethodException,
SQLException, BuildClauseException, IOException {
DataScooter.getDefault().update(trade1, "goods", "Toyota");
DataScooter.getDefault().update(trade2, "goods", "BMW");
assertTrue(((Trade) DataScooter.getDefault().firstById(Trade.class.getName(),
trade1.getId())).getGoods().equals("Toyota"));
assertTrue(((Trade) DataScooter.getDefault().firstById(Trade.class.getName(),
trade2.getId())).getGoods().equals("BMW"));
}
Here we test update of trades
public void testDelete() throws EntityNotMappedException, WrongMethodException,
SQLException, BuildClauseException, IOException {
DataScooter.getDefault().delete(trade1);
DataScooter.getDefault().delete(Trade.class.getName(), "goods", "BMW");
assertTrue(DataScooter.getDefault().firstById(Trade.class.getName(),
trade1.getId()) == null);
assertTrue(DataScooter.getDefault().first(Trade.class.getName(), "goods", "BMW") == null);
}
Here we test a deletion objects from database
Тестируем удаление объектов из базы
public void testECount() {
assertTrue(DataScooter.getDefault().count(Trade.class.getName()) == 2);
assertTrue(DataScooter.getDefault().count(Offer.class.getName()) == 4);
}
Let's count items in database
Подсчитываем количество объектов в базе
public void testSaveOrUpdate() throws EntityNotMappedException,
WrongMethodException, SQLException, BuildClauseException, IOException {
DataScooter.getDefault().saveOrUpdate(trade1);
trade1.setGoods("Subaru");
DataScooter.getDefault().saveOrUpdate(trade1);
assertTrue(DataScooter.getDefault().first(Trade.class.getName(),
"goods", "Subaru") != null);
}
Here we make save or update - for cases when we do not know about existence object in the databse
public void testSaveAll() throws EntityNotMappedException,
WrongMethodException, SQLException, BuildClauseException, IOException {
list.add(new Offer("List", trade1.getId(), 55L, new Date(), new Date(), user4.getId()));
list.add(new Offer("List", trade1.getId(), 55L, new Date(), new Date(), user2.getId()));
list.add(new Offer("List", trade2.getId(), 55L, new Date(), new Date(), user2.getId()));
list.add(new Offer("List", trade4.getId(), 55L, new Date(), new Date(), user2.getId()));
DataScooter.getDefault().saveAll(list);
assertTrue("Offers in the db: " + DataScooter.getDefault().list
(Offer.class.getName(), "name", "List").size(), DataScooter.getDefault().list(
Offer.class.getName(),
"name",
"List").size() == 4);
}
Test saving a list of objects
public void testDeleteAll() throws EntityNotMappedException, WrongMethodException,
BuildClauseException, SQLException, IOException {
DataScooter.getDefault().deleteAll(list);
assertTrue(DataScooter.getDefault().list(Offer.class.getName(), "name", "List").size() == 0);
}
Test deleting a list of objects
public void testPagination() throws EntityNotMappedException, WrongMethodException,
SQLException, BuildClauseException, IOException {
Date start = new Date();
list1.add(new Offer("List2", trade1.getId(), 55L, start, start, user4.getId()));
list1.add(new Offer("List2", trade1.getId(), 55L, start, start, user2.getId()));
list1.add(new Offer("List2", trade2.getId(), 55L, start, start, user2.getId()));
list1.add(new Offer("List2", trade4.getId(), 55L, start, start, user2.getId()));
list1.add(new Offer("List2", trade1.getId(), 55L, start, start, user4.getId()));
list1.add(new Offer("List2", trade1.getId(), 55L, start, start, user2.getId()));
list1.add(new Offer("List2", trade2.getId(), 55L, start, start, user2.getId()));
list1.add(new Offer("List2", trade4.getId(), 55L, start, start, user2.getId()));
DataScooter.getDefault().saveAll(list1);
assertTrue("Pagination error " + DataScooter.getDefault().list(Offer.class.getName(),
1, 2).size(), DataScooter.getDefault().list(
Offer.class.getName(),
1,
2).size() == 2);
assertTrue("Pagination error " + DataScooter.getDefault().list(Offer.class.getName(),
"name", "List2", 2, 18).size(), DataScooter
.getDefault().list(Offer.class.getName(), "name", "List2", 2, 18).size() == 6);
}
Here we test pagination - invoking a big count of objects by part
public void testGroupFetch() throws EntityNotMappedException {
DataSnip dataSnip = DataSnip.group();
dataSnip.fetch(Contract.class.getName());
dataSnip.fetch(Offer.class.getName());
dataSnip.fetch(User.class.getName());
Snip snip = DataScooter.getDefault().retrieve(dataSnip);
assertTrue(snip.getData() == null);
assertTrue(snip.getFetch()[0].getData()[0].length == 4);
assertTrue(snip.getFetch()[0].getData()[1].length == 4);
assertTrue(snip.getFetch()[0].getData()[2].length == 4);
}
Here we test invoking a arbitary set of objects
public void testPipe() throws SnipManagerException, EntityNotMappedException,
SQLException, BuildClauseException, IOException {
DataScooter.getInstance().putSource(new DataSource("mysql-1",
"jdbc:mysql://localhost/testtest", "root", "root", "mysql", false));
IDataManager manager = DataScooter.getInstance().getManager("mysql-1");
manager.verifyTables(true);
TestUtils.clearAll(manager);
int count1 = DataScooter.getDefault().count(Trade.class.getName());
manager.saveSnip(DataScooter.getDefault().retrieve(DataSnip.select(Trade.class.getName())));
int count = manager.count(Trade.class.getName());
assertTrue("Size: " + count + "---" + count1, count == count1);
}
And here we test pumping a list of objects from one database from other
manager.saveSnip(DataScooter.getDefault().retrieve(DataSnip.select(Trade.class.getName())));
Only one string makes saving and invoking
public void testDataSet() throws SnipManagerException, EntityNotMappedException,
SQLException, BuildClauseException, IOException {
String entity = "someObject";
EntityBundle bundle = new EntityBundle(entity, null, "SomeTable", null, null);
bundle.setId(new SimpleAttribute("id", "id", DBType.CHAR, new Integer(36), null, Boolean.TRUE));
bundle.addSimpleAttribute(new SimpleAttribute("first", "first", DBType.STRING, new Integer(55), null, null));
bundle.addSimpleAttribute(new SimpleAttribute("second", "second", DBType.INT, null, null, null));
DataScooter.getInstance().addBundle(bundle, true);
DataScooter.getDefault().clear(entity);
int i = 5555;
String string = "atom";
DataScooter.getDefault().saveSet(entity, UUID.randomUUID().toString(), string, i);
Snip snip = DataScooter.getDefault().retrieve(DataSnip.select(entity));
assertTrue("Size: " + snip.getData().length, snip.getData().length == 1);
assertTrue("Attribute: " + snip.getData()[0][1], snip.getData()[0][1].equals(string));
BigDecimal bb = new BigDecimal(snip.getData()[0][2] + "");
assertTrue("Attribute: " + snip.getData()[0][2], bb.intValue() == i);
snip.getData()[0][1] = string + "bbb";
snip.getData()[0][2] = i + 1;
DataScooter.getDefault().updateSnip(snip);
snip = DataScooter.getDefault().retrieve(DataSnip.select(entity));
assertTrue("Size: " + snip.getData().length, snip.getData().length == 1);
assertTrue("Attribute: " + snip.getData()[0][1], snip.getData()[0][1].equals(string + "bbb"));
bb = new BigDecimal(snip.getData()[0][2] + "");
assertTrue("Attribute: " + snip.getData()[0][2], bb.intValue() == i + 1);
DataScooter.getDefault().deleteSnip(snip);
snip = DataScooter.getDefault().retrieve(DataSnip.select(entity));
assertTrue("Size not empty : " + snip.getData().length, snip.getData().length == 0);
String entity1 = "someObject1";
EntityBundle bundle1 = new EntityBundle(entity1, null, "d_trade", null, null);
bundle1.setId(new SimpleAttribute("id", "s_id", DBType.CHAR, new Integer(36), null, Boolean.TRUE));
bundle1.addSimpleAttribute(new SimpleAttribute("name", "s_name",
DBType.STRING, new Integer(36), null, null));
bundle1.addSimpleAttribute(new SimpleAttribute("goods", "s_goods", DBType.STRING, null, null, null));
bundle1.addSimpleAttribute(new SimpleAttribute("type", "s_type", DBType.INT, null, null, null));
bundle1.setDiscriminator(new Condition(new LogicValue("type", Constraint.EQUAL.name(), 0)));
DataScooter.getInstance().addBundle(bundle1, false);
Snip snip1 = DataScooter.getDefault().retrieve(DataSnip.select(entity1));
assertTrue("Size of trades substitutor: " + snip1.getData().length, snip1.getData().length == 3);
}
This a long example shows use a sets of data - i.e. mappings without objects(classes). The mapping without class -
it is just a named set of data from one table and you may to make with it all datascooter operations - save,update,invoke,
delete.
String entity = "someObject";
EntityBundle bundle = new EntityBundle(entity, null, "SomeTable", null, null);
bundle.setId(new SimpleAttribute("id", "id", DBType.CHAR, new Integer(36), null, Boolean.TRUE));
bundle.addSimpleAttribute(new SimpleAttribute("first", "first",
DBType.STRING, new Integer(55), null, null));
bundle.addSimpleAttribute(new SimpleAttribute("second", "second", DBType.INT, null, null, null));
DataScooter.getInstance().addBundle(bundle, true);
EntityBundle - this is a mapping holder - here we create it and in the last string insert in to
datascooter. Now we can to manipulate it object.
DataScooter.getDefault().saveSet(entity, UUID.randomUUID().toString(), string, i);
Here we create a set of data - just a sequence of fields
snip = DataScooter.getDefault().retrieve(DataSnip.select(entity));
И извлекаем его же.
public void testLogicAttributes() throws SnipManagerException,
EntityNotMappedException, SQLException, BuildClauseException, IOException {
List list2 = DataScooter.getDefault().list(ChildTrade.class.getName());
assertTrue("Subset count wrong: " + list2.size(), (list2.size() == 1));
}
And here we test invoking a list of descendants of trade stored in the same table - datascooter will newer
mix it - it may invoke it by logic clause('logic_condition') of any complexity.
It is a complex discriminator - i've never seen similar. Here may be it looks not clear but it is not
a problem - in the standart editor of a extension points you will just fillup forms.
So it looks in the extension points editor:
public void testSnipQuery() throws SnipManagerException, EntityNotMappedException,
SQLException, BuildClauseException, IOException {
EclipseQueryProvider provider = new EclipseQueryProvider();
provider.explore();
DataSnip query = provider.getItem("selectOffer");
assertTrue(query != null);
Snip snip = DataScooter.getDefault().retrieve(query);
assertTrue("First offer " + snip.getData()[0][1], snip.getData()[0][1].equals("off4"));
assertTrue("First contract " + snip.getFetch()[0].getData()[0][1],
snip.getFetch()[0].getData()[0][1].equals("text1")
|| snip.getFetch()[0].getData()[0][1].equals("text2")
|| snip.getFetch()[0].getData()[0][1].equals("text3")
|| snip.getFetch()[0].getData()[0][1].equals("text4"));
assertTrue("Second contract " + snip.getFetch()[0].getData()[1][1],
snip.getFetch()[0].getData()[1][1].equals("text1")
|| snip.getFetch()[0].getData()[1][1].equals("text2")
|| snip.getFetch()[0].getData()[1][1].equals("text3")
|| snip.getFetch()[0].getData()[1][1].equals("text4"));
assertTrue("First trade " + snip.getFetch()[0].getFetch()[0].getData()[0][1],
snip.getFetch()[0].getFetch()[0].getData()[0][1]
.equals("trade1")
|| snip.getFetch()[0].getFetch()[0].getData()[0][1].equals("trade3")
|| snip.getFetch()[0].getFetch()[0].getData()[0][1].equals("trade4"));
assertTrue("s" + snip.getFetch()[0].getFetch()[0].getData()[1][1],
snip.getFetch()[0].getFetch()[0].getData()[1][1].equals("trade4")
|| snip.getFetch()[0].getFetch()[0].getData()[1][1].equals("trade3")
|| snip.getFetch()[0].getFetch()[0].getData()[1][1].equals("trade1"));
}
It is too very interesting thing - SnipQuery - it is made with extension points tool for
a writing predefined hierarchical queries holds all the possibilities of datascooter.
So it looks in the extension points editor:
|