package org.easyframe.tutorial.lessona;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import jef.codegen.EntityEnhancer;
import jef.common.log.LogUtil;
import jef.common.wrapper.IntRange;
import jef.common.wrapper.Page;
import jef.database.Condition.Operator;
import jef.database.DbClient;
import jef.database.NativeQuery;
import jef.database.ORMConfig;
import jef.database.QB;
import jef.database.datasource.MapDataSourceLookup;
import jef.database.datasource.RoutingDataSource;
import jef.database.datasource.SimpleDataSource;
import jef.database.query.Query;
import jef.database.query.Selects;
import jef.database.query.SqlExpression;
import jef.database.wrapper.ResultIterator;
import jef.tools.DateUtils;
import jef.tools.ThreadUtils;
import jef.tools.string.RandomData;
import org.easyframe.tutorial.lessona.entity.Customer;
import org.easyframe.tutorial.lessona.entity.Device;
import org.easyframe.tutorial.lessona.entity.OperateLog;
import org.easyframe.tutorial.lessona.entity.Person2;
import org.junit.BeforeClass;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;
/**
*
* 分库分表后的对象操作演示(基本)
*
* @author jiyi
*
*/
@SuppressWarnings("rawtypes")
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class Case2 extends org.junit.Assert {
private static DbClient db;
private static boolean doinit = true;
/**
* 准备测试数据
*
* @throws SQLException
*/
@BeforeClass
public static void setup() throws SQLException {
// 准备多个数据源
Map<String, DataSource> datasources = new HashMap<String, DataSource>();
// 创建三个数据库。。。
datasources.put("datasource1", new SimpleDataSource("jdbc:derby:./db;create=true", null, null));
datasources.put("datasource2", new SimpleDataSource("jdbc:derby:./db2;create=true", null, null));
datasources.put("datasource3", new SimpleDataSource("jdbc:derby:./db3;create=true", null, null));
MapDataSourceLookup lookup = new MapDataSourceLookup(datasources);
lookup.setDefaultKey("datasource1");// 指定datasource1是默认的操作数据源
// 构造一个带数据路由功能的DbClient
db = new DbClient(new RoutingDataSource(lookup));
if (doinit) {
//现在删表,删表时会自动扫描目前存在的分表。
db.dropTable(Customer.class, Device.class, OperateLog.class, Person2.class);
System.err.println("现在开始为Customer对象建表。Customer对象按“年_月”方式分表,并且按customerNo除以3的余数分库");
db.createTable(Customer.class);
System.out.println();
System.err.println("现在开始为Device对象建表。Device对象按“IndexCode的头两位数字”分表,当头两位数字介于10~20时分布于ds1;21~32时分布于ds2;33~76时分布于ds3;其他情形时分布于默认数据源");
db.createTable(Device.class);
System.out.println();
System.err.println("现在开始为OperateLog对象建表。OperateLog对象按“年_月_日”方式分表,不分库");
db.createTable(OperateLog.class);
System.out.println();
System.err.println("现在开始为Person2对象建表。Person2对象是垂直拆分,因此所有数据都位于datasource2上。不分表");
db.createTable(Person2.class);
System.out.println();
System.err.println("======= 建表操作完成,对于分区表只创建了可以预测到的若干表,实际操作中需要用到的表会自动按需创建=========");
}
}
@Test
public void ddlTest() throws SQLException{
Customer customer=new Customer();
customer.setCustomerNo(1234);
customer.setCreateDate(DateUtils.getDate(2016,12,10));
db.createTable(customer);
db.dropTable(customer);
Device d=new Device();
d.setIndexcode("123456");
db.createTable(d);
db.dropTable(d);
}
/**
* 当分表结果计算后,对比数据库中实际存在的表。不存在的表不会参与查询。
*
* @throws SQLException
*/
@Test
public void testTableFilter() throws SQLException {
Device d=new Device();
d.setIndexcode("665565");
db.createTable(d);
ThreadUtils.doSleep(1000);
System.out.println("第一次查询,表Device_6存在,故会查询此表");
Query<Device> query = QB.create(Device.class);
List<Device> device=db.select(query);
db.dropTable(d);
ThreadUtils.doSleep(500);
System.out.println("第二次查询,由于表Device_6被删除,因此不会查此表");
device=db.select(query);
}
/**
* 当分表结果计算后,发现没有需要查询的表的时候,会直接返回
*
* @throws SQLException
*/
@Test
public void testNoMatchTables() throws SQLException {
Query<Device> d = QB.create(Device.class);
//当Device_9表还不存在时,这个查询直接返回空
if(!db.getMetaData(null).existTable("DEVICE_9")){
d.addCondition(Device.Field.indexcode, "9999999");
List<Device> empty=db.select(d);
assertTrue(empty.isEmpty());
}
}
/**
* 当采用垂直拆分时, Person2的所有操作都集中在DB2上。
*
* @throws SQLException
*/
@Test
public void test1() throws SQLException {
// 插入
Person2 p2 = new Person2();
p2.setName("Jhon smith");
db.insert(p2);
// 查询
Person2 loaded = db.load(Person2.class, p2.getId());
// 更新
loaded.setName("Kingstone");
assertEquals(1, db.update(loaded));
// 查询数量
assertEquals(1, db.count(QB.create(Person2.class)));
// 删除
assertEquals(1, db.delete(loaded));
// 删除后
assertEquals(0, db.count(QB.create(Person2.class)));
System.out.println("=============== In Native Query ============");
{
String sql="insert into person2(name,data_desc,created,modified) values(:name,:data,sysdate,sysdate)";
NativeQuery query=db.createNativeQuery(sql, Person2.class).withRouting();
query.setParameter("name", "测试111");
query.setParameter("data", "备注信息");
query.executeUpdate();
}
{
String sql="select * from person2";
NativeQuery<Person2> query=db.createNativeQuery(sql, Person2.class).withRouting();
query.getResultCount();
query.getResultList();
}
{
String sql="update person2 set name=:name where id=:id";
NativeQuery query=db.createNativeQuery(sql).withRouting();
query.setParameter("id", 1);
query.setParameter("name", "测试222");
query.executeUpdate();
}
{
String sql="delete person2 where id=:id";
NativeQuery query=db.createNativeQuery(sql).withRouting();
query.setParameter("id", 2);
query.executeUpdate();
}
{
String sql="select * from person2 order by id limit 1,3";
NativeQuery query=db.createNativeQuery(sql).withRouting();
query.getResultList();
}
{
String sql="select * from person2 order by id limit 3 offset 1";
NativeQuery query=db.createNativeQuery(sql).withRouting();
query.getResultList();
}
}
/**
* Customer对象按创建记录created字段时的“年_月”方式分表,并且按customerNo除以3的余数分库
*
* @throws SQLException
*/
@Test
public void testCustomer() throws SQLException {
// 插入
Customer c = new Customer();
c.setLastName("Hession");
c.setFirstName("Obama");
c.setDOB(DateUtils.getDate(1904, 3, 4));
c.setDOD(DateUtils.getDate(1991, 7, 12));
c.setEmail("obama@hotmail.com");
db.insert(c);
/*
* 这个案例中,用作分库分表的customerNo和created这两个字段都没赋值,但是记录却成功的插入了。
* 因为customerNo是自增值,created是系统自动维护的当前时间值。系统自动维护了这两个字段,从而使得分库分表的路由条件充分了。
* 此外,注意自增值的生成方式变化了。在本例中,使用TABLE来实现自增值。因为分库分表后,表的自增值已经无法保证唯一了,
* 而Derby不支持Sequence,所以采用TABLE方式生成自增值。(DERBY实际上支持,但兼容性有些问题,故关闭了)
*/
System.out.println("====将会按需建表====");
Customer c2 = new Customer();
c2.setLastName("Joe");
c2.setFirstName("Lei");
c2.setDOB(DateUtils.getDate(1981, 3, 4));
c2.setEmail("joe@hotmail.com");
c2.setCreateDate(DateUtils.getDate(2013, 5, 1));
db.insert(c2);
/*
* 这里指定记录创建时间为2013-5-1,也就是说该条记录需要插到表 CUSTOMER_201305这张表中。
* 这张表虽然现在不存在,但是EF-ORM会在需要用到时,自动创建这张表。
*/
// 路由维度充分时的查询
System.out.println("当分表条件充分时,只需要查一张表即可...");
Customer loaded1 = db.load(c);
// 查询。
System.out.println("当分表条件不完整时,需要查询同一个库上的好几张表。");
Customer loaded = db.load(Customer.class, c.getCustomerNo());
// 更新
loaded.setLastName("King");
assertEquals(1, db.update(loaded));
// 查询数量,由于有没分库分表条件,意味着要查询所有库上,一定时间范围内的所有表
assertEquals(1, db.count(QB.create(Customer.class)));
// 删除
assertEquals(1, db.delete(loaded));
// 删除后
assertEquals(0, db.count(QB.create(Customer.class)));
}
/**
* 演示Batch操作在分库分表后发生的变化
*
* @throws SQLException
*/
@Test
public void testCustomerBatch() throws SQLException {
System.out.println("testCustomerBatch");
db.truncate(Customer.class);
List<Customer> list = new ArrayList<Customer>();
// 批量插入
Customer c = new Customer();
c.setLastName("Hession");
c.setFirstName("Obama");
c.setDOB(DateUtils.getDate(1904, 3, 4));
c.setDOD(DateUtils.getDate(1991, 7, 12));
c.setEmail("obama@hotmail.com");
list.add(c);
c = new Customer();
c.setLastName("Joe");
c.setFirstName("Lei");
c.setDOB(DateUtils.getDate(1981, 3, 4));
c.setEmail("joe@hotmail.com");
c.setCreateDate(DateUtils.getDate(2013, 5, 1));
list.add(c);
c = new Customer();
c.setCustomerNo(4);
c.setLastName("Yang");
c.setFirstName("Fei");
c.setDOB(DateUtils.getDate(1976, 12, 15));
c.setEmail("fei@hotmail.com");
c.setCreateDate(DateUtils.getDate(2013, 5, 1));
list.add(c);
System.out.println("当Batch操作遇到分库分表——\n所有记录将会重新归类后,相同的表的划为一批,进行批量插入。");
db.batchInsert(list);
// 跨表跨库的搜索
Query<Customer> query = QB.create(Customer.class);
query.addCondition(QB.between(Customer.Field.createDate, DateUtils.getDate(2013, 4, 30), DateUtils.getDate(2018, 12, 31)));
// 艰难的查找——
// 由于条件只有一个时间范围,因此会搜索所有可能出现记录的表。包括——三个数据库上所有时段在13年4月到14年12月的表。理论上所有可能的组合。
// 但由于大部分表不存在。EF-ORM只会查找实际存在的表,实际上不存在的表不会被查找。
list = db.select(query);
assertEquals(3, list.size());
// 批量更新
for (int i = 0; i < list.size(); i++) {
list.get(i).setEmail("mail" + i + "@hotmail.com");
}
// 虽然是Batch更新,但实际上所有记录分散在不同的库的不同的表中,重新分组后,每张表构成一个批来更新
db.batchUpdate(list);
// 批量删除
db.executeBatchDeletion(list);
}
/**
* 演示若干复杂的跨库Cirteria操作。这些操作虽然会涉及多个数据库的多张表,但在框架封装下,几乎对开发者做到了完全透明。
*
* 案例说明:<br>
* 1、用批模式插入50条记录,这些记录将会分布在三个数据库的10张表中。由于分库维度和分表维度一致,因此实际情况为,表1,8,9位于DB,表2,3位于DB2,表4,5,6,7位于DB3。
* 2、跨库查询总数 (看点:跨库记录数汇总)
* 3、查询index 为4开头的记录 (看点:条件解析与精确路由)
* 4、查询indexcode含0的记录,并按创建日期排序 (看点: 跨库排序)
* 5、查询indexcode含0的记录,并按创建日期排序,每页10条,显示第二页(看点: 跨库排序+分页)
* 6、所有记录,按type字段group by,并计算总数。(看点:跨库+聚合计算)
* 7、所有记录,按type字段group by,并计算总数。并按总数排序(看点:跨库+聚合计算+排序)
* 8、查询所有记录的type字段,并Distinct。 (看点:跨库 distinct)
* 9、跨数据库查询所有记录,并排序分页 (看点:跨库+分页)
* 10、跨数据库查询所有记录,按type分组后计算总数,通过having条件过滤掉总数在9以上的记录,最后排序 (看点:跨库+聚合+Having+排序)
* 11、跨数据库查询所有记录,按type分组后计算总数,通过having条件过滤掉总数在9以上的记录,最后排序,取结果的第3~5条。 (看点:跨库+聚合+Having+排序+分页)
* @throws SQLException
*/
@Test
public void testDeviceSelect() throws SQLException {
List<Device> list = generateDevice(50);
ORMConfig.getInstance().setMaxBatchLog(2);
db.batchInsert(list);
System.err.println("=====1. 数据准备:插入50条记录完成=====");
System.err.println("=====2. 跨库查询总数=====");
System.out.println("当前总数是:" + db.count(QB.create(Device.class)));
{
System.err.println("=====3. 查询indexCode 4开头的记录完成=====");
Query<Device> query = QB.create(Device.class);
query.addCondition(QB.matchStart(Device.Field.indexcode, "4"));
List<Device> results = db.select(query);
LogUtil.show(results);
}
{
System.err.println("=====4. 查询indexcode含0的记录,并按创建日期排序=====");
// 分库分表后的难点之一——跨库查询并且并且排序
Query<Device> query = QB.create(Device.class);
query.addCondition(QB.matchAny(Device.Field.indexcode, "0"));// 显然这个查询意味着要调动好几个数据库上的好几张表
query.orderByDesc(Device.Field.createDate); // 更麻烦的是,要对这些数据按日期进行排序。
List<Device> results = db.select(query);
for (Device ss : results) {
System.out.println(ss);
}
System.err.println("=====5. 查询indexcode含0的记录,并按创建日期排序,每页10条,显示第二页=====");
// 更麻烦一点——[跨库查询]并且并且[排序]还要[分页]——每页10条,从第二页开始显示
Page<Device> page = db.pageSelect(query, Device.class, 10).setOffset(10).getPageData();
System.out.println("总数:" + page.getTotalCount() + " 每页:" + page.getPageSize());
LogUtil.show(page.getList());
}
{
System.out.println("=====6. 跨数据库 聚合查询=====");
// 分库分表后的难点之二——聚合查询
Query<Device> query = QB.create(Device.class);
Selects select = QB.selectFrom(query);
select.column(Device.Field.type).group();
select.column(Device.Field.indexcode).count().as("ct");
select.column(Device.Field.indexcode).min().as("mins");
select.column(Device.Field.indexcode).max().as("maxs");
List<String[]> strs = db.selectAs(query, String[].class);
for (String[] ss : strs) {
System.out.println(Arrays.toString(ss));
}
}
{
System.out.println("=====7. 跨数据库 聚合+重新排序 查询=====");
// 分库分表后的难点之二——聚合查询+再加上排序
Query<Device> query = QB.create(Device.class);
Selects select = QB.selectFrom(query);
select.column(Device.Field.type).group();
select.column(Device.Field.indexcode).count().as("ct");
query.orderByDesc(new SqlExpression("ct")); // 除了聚合以外,再添加聚合后排序
List<String[]> strs = db.selectAs(query, String[].class);
for (String[] ss : strs) {
System.out.println(Arrays.toString(ss));
}
}
{
System.out.println("=====8. 跨数据库 Distinct 查询=====");
// 分库分表后的难点之三——Distinct操作
Query<Device> query = QB.create(Device.class);
Selects select = QB.selectFrom(query);
select.column(Device.Field.type);
select.setDistinct(true);
List<Device> results = db.select(query);
for (Device ss : results) {
System.out.println(ss.getType());
}
assertTrue(results.size() > 0);
assertNotNull(results.get(0).getType());
}
{
System.out.println("=====9. 跨数据库查询并带排序分页=====");
Query<Device> query = QB.create(Device.class);
query.orderByDesc(Device.Field.indexcode);
List<Device> results = db.select(query, new IntRange(11, 20));
for (Device ss : results) {
System.out.println(ss);
}
assertTrue(results.size() > 0);
assertNotNull(results.get(0).getType());
}
{
System.out.println("=====10. 跨数据库 聚合+Having +重新排序=====");
Query<Device> query = QB.create(Device.class);
Selects select = QB.selectFrom(query);
select.column(Device.Field.type).group();
select.column(Device.Field.indexcode).count().as("ct").having(Operator.LESS_EQUALS, 9);
query.orderByDesc(new SqlExpression("ct")); // 除了聚合以外,再添加聚合后排序
List<String[]> strs = db.selectAs(query, String[].class);
for (String[] ss : strs) {
System.out.println(Arrays.toString(ss));
}
}
{
System.out.println("=====11. 跨数据库 聚合+Having +重新排序 + 分页=====");
//反正已经够复杂了,分页也一起上吧!
Query<Device> query = QB.create(Device.class);
Selects select = QB.selectFrom(query);
select.column(Device.Field.type).group();
select.column(Device.Field.indexcode).count().as("ct").having(Operator.LESS_EQUALS, 12);
query.orderByDesc(new SqlExpression("ct")); // 除了聚合以外,再添加聚合后排序
List<Map> strs = db.selectAs(query, Map.class, new IntRange(3,5));
for (Map ss : strs) {
System.out.println(ss);
}
}
}
/**
* 不仅仅是Criteria API支持分库分表,SQL语句也可以自动分库分表
* 案例说明:<br>
* 1、用批模式插入50条记录,这些记录将会分布在三个数据库的10张表中。由于分库维度和分表维度一致,因此实际情况为,表1,8,9位于DB,表2,3位于DB2,表4,5,6,7位于DB3。
* 2、用SQL插入记录 x2
* 3、用SQL更新记录 x3
* 4、用SQL删除记录 x2
* 5、用SQL查询记录 x4
*
* @throws SQLException
*/
@Test
public void testNativeQuery() throws SQLException{
List<Device> list = generateDevice(50);
ORMConfig.getInstance().setDebugMode(false);
db.batchInsert(list);
ORMConfig.getInstance().setDebugMode(true);
System.err.println("=====数据准备:插入50条记录完成=====");
/**
* 使用SQL语句插入记录,根据传入的indexcode分布到不同数据库上
*/
{
NativeQuery nq=db.createNativeQuery("insert into DeVice(indexcode,name,type,createDate) values(:indexcode, :name, :type, sysdate)").withRouting();;
nq.setParameter("indexcode", "122346");
nq.setParameter("name", "测试插入数据");
nq.setParameter("type", "办公用品");
nq.executeUpdate();
nq.setParameter("indexcode", "7822346");
nq.setParameter("name", "非官方的得到");
nq.setParameter("type", "大家电");
nq.executeUpdate();
nq.setParameter("indexcode", "452346");
nq.setParameter("name", "萨菲是方式飞");
nq.setParameter("type", "日用品");
nq.executeUpdate();
}
/**
* 使用SQL语句更新记录,使用Between条件,这意味着indexcode在1000xxx到6000xxx段之间的所有表会参与更新操作。
*/
{
System.out.println("===Between条件中携带的路由条件,正确操作表: 1,2,3,4,5,6");
NativeQuery nq=db.createNativeQuery("update DeVice xx set xx.name='ID:'||indexcode,createDate=sysdate where indexcode between :s1 and :s2").withRouting();;
nq.setParameter("s1", "1000");
nq.setParameter("s2", "6000");
nq.executeUpdate();
}
/**
* 使用SQL语句更新记录,使用In条件,这将精确定位到这些记录所在的表上。
*/
{
System.out.println("===用IN条件更新==");
NativeQuery nq=db.createNativeQuery("update Device set createDate=sysdate, name=:name where indexcode in (:codes)").withRouting();;
nq.setParameter("name", "Updated value");
nq.setParameter("codes", new String[]{"6000123","567232",list.get(0).getIndexcode(),list.get(1).getIndexcode(),list.get(2).getIndexcode()});
nq.executeUpdate();
}
/**
* 使用SQL语句更新记录。由于where条件中没有任何用来缩小记录范围的条件,因此所有的表上都将执行更新操作
*/
{
System.out.println("===正确操作表: 2==");
NativeQuery nq=db.createNativeQuery("update Device set createDate=sysdate where type='办公用品' or indexcode='2002345'").withRouting();;
nq.executeUpdate();
}
/**
* 删除记录。根据indexcode可以准确定位到三张表上。
*/
{
System.out.println("===正确操作表: 1,6,5==");
NativeQuery nq=db.createNativeQuery("delete Device where indexcode in (:codes)").withRouting();;
nq.setParameter("codes", new String[]{"6000123","567232","110000"});
nq.executeUpdate();
}
/**
* 删除记录,indexCode上的大于和小于条件以及OR关系勾勒出了这次查询的表,将会是DEVICE_2,DEVICE_3,DEVICE_4、DEVICE_7、DEVICE_8。(5张表)
*/
{
System.out.println("===正确操作表: 2,3,4,5,7,8==");
NativeQuery nq=db.createNativeQuery("delete Device where indexcode >'200000' and indexcode<'5' or indexcode >'700000' and indexcode <'8'").withRouting();;
nq.executeUpdate();
}
/**
* 查询,所有表,跨库排序
*/
{
System.out.println("查询,所有表,跨库排序");
String sql="select t.* from device t where createDate is not null order by createDate";
NativeQuery<Device> query=db.createNativeQuery(sql,Device.class).withRouting();;
long total=query.getResultCount();
System.out.println("预计查询结果总数Count:"+ total);
List<Device> devices=query.getResultList();
assertEquals(total, devices.size());
int n=0;
for(Device d: devices){
System.out.println(d);
if(n++>10)break;
}
}
{
System.out.println("查询,所有表,跨库排序并分页");
String sql="select t.* from device t where createDate is not null order by createDate limit 5,6";
NativeQuery<Device> query=db.createNativeQuery(sql,Device.class).withRouting();;
long total=query.getResultCount();
System.out.println("预计查询结果总数Count:"+ total);
List<Device> devices=query.getResultList();
assertEquals(total, devices.size());
int n=0;
for(Device d: devices){
System.out.println(d);
if(n++>10)break;
}
}
/**
* 查询两个条件时,
*/
{
System.out.println("======查询,Like条件,后一个条件无参数被省略,正确操作表 3==");
String sql="select t.* from device t where createDate is not null and (t.indexcode like '3%' or t.indexcode in (:codes)) order by createDate";
NativeQuery<Device> query=db.createNativeQuery(sql,Device.class).withRouting();;
long total=query.getResultCount();
System.out.println("预期查询总数Count:"+ total);
int count=0;
//使用迭代器方式查询
ResultIterator<Device> devices=query.getResultIterator();
for (;devices.hasNext();) {
System.out.println(devices.next());
count++;
}
devices.close();
assertEquals(count, total);
query.setParameter("codes", new String[]{"123456","8823478","98765"});
System.out.println("======查询,Like条件 OR IN条件,正确操作表:1,3,8,9==");
total=query.getResultCount();
System.out.println("预期查询总数Count:"+ total);
List<Device> rst=query.getResultList();
assertEquals(total, rst.size());
int n=0;
for(Device d: rst){
System.out.println(d);
if(n++>10)break;
}
}
/**
* 查询记录、如果SQL语句中带有Group条件...
* 跨库条件下的Group实现尤为复杂
*/
{
System.out.println("查询——分组查询,正确操作表:4,1,6");
String sql="select type,count(*) as count,max(indexcode) max_id from Device tx where indexcode like '4%' or indexcode like '1123%' or indexcode like '6%' group by type ";
NativeQuery<Map> query=db.createNativeQuery(sql,Map.class).withRouting();;
System.out.println("预期查询总数Count:"+ query.getResultCount());
List<Map> devices=query.getResultList();
for (Map ss : devices) {
System.out.println(ss);
}
}
/**
* 查询,SQL语句中带有distinct条件
*/
{
String sql="select distinct type from device";
NativeQuery<String> query=db.createNativeQuery(sql,String.class).withRouting();;
long total=query.getResultCount();
System.out.println("预期查询总数Count:"+ total);
List<String> devices=query.getResultList();
for (String ss : devices) {
System.out.println(ss);
}
assertEquals(6, total);
assertEquals(6, devices.size());
}
}
/*
* 生成一些随机的数据
*/
private List<Device> generateDevice(int i) {
List<Device> result = Arrays.asList(RandomData.newArrayInstance(Device.class, i));
String[] types = { "耗材", "大家电", "办公用品", "日用品", "电脑配件", "图书" };
for (Device device : result) {
device.setIndexcode(String.valueOf(RandomData.randomInteger(100000, 990000)));
device.setCreateDate(RandomData.randomDate(DateUtils.getDate(2000, 1, 1), DateUtils.getDate(2014, 12, 31)));
device.setType(types[RandomData.randomInteger(0, 6)]);
}
return result;
}
}