MentaBean

Compare Revisions

Ignore whitespace Rev 210 → Rev 215

/tags/menta-bean-2.2.2/src/test/java/org/mentabean/jdbc/AbstractMappingTest.java
New file
0,0 → 1,203
package org.mentabean.jdbc;
 
import java.util.List;
 
import junit.framework.Assert;
 
import org.junit.Test;
import org.mentabean.BeanConfig;
import org.mentabean.BeanManager;
import org.mentabean.BeanSession;
import org.mentabean.DBTypes;
import org.mentabean.util.OrderBy;
import org.mentabean.util.PropertiesProxy;
import org.mentabean.util.SQLUtils;
 
public class AbstractMappingTest extends AbstractBeanSessionTest {
 
public static abstract class Conta {
private int id;
public Conta(int id) {
this.id = id;
}
public Conta() {}
public abstract String realizaOperacao();
 
public int getId() {
return id;
}
 
public void setId(int id) {
this.id = id;
}
}
public static class ContaReceber extends Conta {
public ContaReceber() {}
public ContaReceber(int id) {
super(id);
}
 
@Override
public String realizaOperacao() {
return "Conta a Receber";
}
}
public static class ContaPagar extends Conta {
public ContaPagar() {}
public ContaPagar(int id) {
super(id);
}
 
@Override
public String realizaOperacao() {
return "Conta a Pagar";
}
}
public static abstract class Parcela {
private int numero;
private double valor;
private Conta conta;
public int getNumero() {
return numero;
}
public void setNumero(int numero) {
this.numero = numero;
}
public double getValor() {
return valor;
}
public void setValor(double valor) {
this.valor = valor;
}
public Conta getConta() {
return conta;
}
public void setConta(Conta conta) {
this.conta = conta;
}
public Parcela conta(Conta conta) {
this.conta = conta;
return this;
}
public Parcela numero(int numero) {
this.numero = numero;
return this;
}
public Parcela valor(double valor) {
this.valor = valor;
return this;
}
}
public static class ParcelaReceber extends Parcela {
}
public static class ParcelaPagar extends Parcela {
}
public BeanManager configure() {
BeanManager manager = new BeanManager();
ParcelaPagar ppPxy = PropertiesProxy.create(ParcelaPagar.class);
BeanConfig ppCfg = new BeanConfig(ParcelaPagar.class, "parcelas_pagar")
.pk(ppPxy.getNumero(), DBTypes.INTEGER)
.field(ppPxy.getConta().getId(), "idcontas_pagar", DBTypes.INTEGER)
.field(ppPxy.getValor(), DBTypes.DOUBLE)
.abstractInstance(ppPxy.getConta(), ContaPagar.class);
ParcelaReceber prPxy = PropertiesProxy.create(ParcelaReceber.class);
BeanConfig prCfg = new BeanConfig(ParcelaReceber.class, "parcelas_receber")
.pk(prPxy.getNumero(), DBTypes.INTEGER)
.field(prPxy.getConta().getId(), "idcontas_receber", DBTypes.INTEGER)
.field(prPxy.getValor(), DBTypes.DOUBLE)
.abstractInstance(prPxy.getConta(), ContaReceber.class)
;
manager.addBeanConfig(prCfg);
manager.addBeanConfig(ppCfg);
return manager;
}
@Test
public void test() {
BeanSession session = new H2BeanSession(configure(), getConnection());
session.createTables();
Parcela pr = new ParcelaReceber()
.numero(1)
.conta(new ContaReceber(1))
.valor(300);
session.insert(pr);
Parcela prDB = new ParcelaReceber().numero(1);
session.load(prDB);
Assert.assertNotNull(prDB.getConta());
Assert.assertTrue(prDB.getConta().realizaOperacao().equals("Conta a Receber"));
Assert.assertEquals(ContaReceber.class, prDB.getConta().getClass());
Assert.assertEquals(pr.getNumero(), prDB.getNumero());
prDB.getConta().setId(4);
session.update(prDB);
prDB = new ParcelaReceber().numero(1);
session.load(prDB);
Assert.assertEquals(4, prDB.getConta().getId());
ContaPagar cp = new ContaPagar(20);
Parcela pp1 = new ParcelaPagar()
.numero(1)
.conta(cp)
.valor(100);
Parcela pp2 = new ParcelaPagar()
.numero(2)
.conta(cp)
.valor(150);
Parcela pp3 = new ParcelaPagar()
.numero(3)
.conta(cp)
.valor(175);
session.insert(pp1);
session.insert(pp2);
session.insert(pp3);
Parcela ppProto = new ParcelaPagar().conta(cp);
List<Parcela> list = session.loadList(ppProto, new OrderBy().orderByAsc("numero"));
Assert.assertEquals(3, list.size());
Assert.assertEquals(1, list.get(0).getNumero());
Assert.assertEquals(2, list.get(1).getNumero());
Assert.assertEquals(3, list.get(2).getNumero());
Assert.assertEquals(175d, list.get(2).getValor());
Assert.assertNotNull(list.get(2).getConta());
SQLUtils.close(session.getConnection());
}
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/test/java/org/mentabean/jdbc/AdvancedQueryBuilderTest.java
New file
0,0 → 1,295
package org.mentabean.jdbc;
 
import java.sql.Connection;
import java.util.List;
 
import junit.framework.Assert;
 
import org.junit.Test;
import org.mentabean.BeanConfig;
import org.mentabean.BeanException;
import org.mentabean.BeanManager;
import org.mentabean.BeanSession;
import org.mentabean.DBTypes;
import org.mentabean.jdbc.QueryBuilder.Alias;
import org.mentabean.jdbc.QueryBuilder.Query;
import org.mentabean.sql.Sentence;
import org.mentabean.sql.conditions.Equals;
import org.mentabean.sql.conditions.GreaterThan;
import org.mentabean.sql.conditions.GreaterThanEquals;
import org.mentabean.sql.conditions.In;
import org.mentabean.sql.conditions.Like;
import org.mentabean.sql.functions.Count;
import org.mentabean.sql.functions.Lower;
import org.mentabean.sql.param.ParamField;
import org.mentabean.sql.param.ParamFunction;
import org.mentabean.sql.param.ParamSubQuery;
import org.mentabean.sql.param.ParamValue;
import org.mentabean.util.PropertiesProxy;
import org.mentabean.util.SQLUtils;
 
public class AdvancedQueryBuilderTest extends AbstractBeanSessionTest {
 
public static class Company {
private String id;
private long number;
private String name;
private int employeeCount;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public long getNumber() {
return number;
}
public void setNumber(long number) {
this.number = number;
}
public int getEmployeeCount() {
return employeeCount;
}
public void setEmployeeCount(int employeeCount) {
this.employeeCount = employeeCount;
}
@Override
public String toString() {
return "Company [id=" + id + ", number=" + number + ", name="
+ name + ", employeeCount=" + employeeCount + "]";
}
}
public static class Employee {
private Company company;
private long number;
private String name;
private double salary;
public Company getCompany() {
return company;
}
public void setCompany(Company company) {
this.company = company;
}
public long getNumber() {
return number;
}
public void setNumber(long number) {
this.number = number;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
@Override
public String toString() {
return "Employee [company=" + company + ", number=" + number
+ ", name=" + name + ", salary=" + salary + "]";
}
}
public static class Post {
private Employee employee;
private Company company;
private String description;
public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
public Company getCompany() {
return company;
}
public void setCompany(Company company) {
this.company = company;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@Override
public String toString() {
return "=== POST "+description+" ===\n"+
company+"\n"+employee;
}
}
private BeanManager configure() {
BeanManager manager = new BeanManager();
Company comPxy = PropertiesProxy.create(Company.class);
BeanConfig comConf = new BeanConfig(Company.class, "company")
.pk(comPxy.getId(), DBTypes.STRING)
.pk(comPxy.getNumber(), DBTypes.LONG)
.field(comPxy.getName(), DBTypes.STRING);
manager.addBeanConfig(comConf);
Employee empPxy = PropertiesProxy.create(Employee.class);
BeanConfig employeeConf = new BeanConfig(Employee.class, "employee")
.pk(empPxy.getNumber(), DBTypes.LONG)
.pk(empPxy.getCompany().getId(), "idcompany", DBTypes.STRING)
.pk(empPxy.getCompany().getNumber(), "ncompany", DBTypes.LONG)
.field(empPxy.getName(), DBTypes.STRING)
.field(empPxy.getSalary(), DBTypes.DOUBLE);
manager.addBeanConfig(employeeConf);
Post postPxy = PropertiesProxy.create(Post.class);
BeanConfig postConf = new BeanConfig(Post.class, "post")
.pk(postPxy.getEmployee().getNumber(), "number_employee", DBTypes.LONG)
.pk(postPxy.getEmployee().getCompany().getId(), "idcompany_employee", DBTypes.STRING)
.pk(postPxy.getEmployee().getCompany().getNumber(), "ncompany_employee", DBTypes.LONG)
.pk(postPxy.getCompany().getId(), "idcompany", DBTypes.STRING)
.pk(postPxy.getCompany().getNumber(), "ncompany", DBTypes.LONG)
.field(postPxy.getDescription(), DBTypes.STRING);
manager.addBeanConfig(postConf);
return manager;
}
@Test
public void test() {
final BeanManager manager = configure();
final Connection conn = getConnection();
try {
AnsiSQLBeanSession.DEBUG = false;
AnsiSQLBeanSession.DEBUG_NATIVE = false;
BeanSession session = new H2BeanSession(manager, conn);
session.createTables();
Company comp = new Company();
comp.setId("4356136");
comp.setName("W3C");
comp.setNumber(1);
session.insert(comp);
Company basicComp = session.createBasicInstance(comp);
Assert.assertFalse(comp == basicComp);
Assert.assertNotNull(basicComp.getId());
Assert.assertNotNull(basicComp.getNumber());
Assert.assertNull(basicComp.getName());
if (AnsiSQLBeanSession.DEBUG) {
System.out.println("Company: " + comp);
System.out.println("Company (only pks): " + basicComp);
}
Employee emp = new Employee();
emp.setCompany(comp);
emp.setName("Érico");
emp.setNumber(391);
emp.setSalary(9999);
session.insert(emp);
Employee basicEmp = session.createBasicInstance(emp);
Assert.assertNull(basicEmp.getName());
Assert.assertNotNull(basicEmp.getCompany());
Assert.assertEquals(0d, basicEmp.getSalary());
Assert.assertEquals(emp.getNumber(), basicEmp.getNumber());
Assert.assertEquals(emp.getCompany().getId(), basicEmp.getCompany().getId());
Assert.assertEquals(emp.getCompany().getNumber(), basicEmp.getCompany().getNumber());
Post post = new Post();
post.setCompany(comp);
post.setEmployee(emp);
post.setDescription("Programmer");
session.insert(post);
QueryBuilder builder = session.buildQuery();
Alias<Employee> e = builder.aliasTo(Employee.class, "emp");
Alias<Company> c = builder.aliasTo(Company.class, "com");
Alias<Post> p = builder.aliasTo(Post.class, "p");
Alias<Employee> e2 = builder.aliasTo(Employee.class, "emp2");
e2.setReturns(e2.pxy().getNumber());
Sentence sum = new Sentence(
new ParamFunction(new Count(new ParamField(e, e.pxy().getNumber()))))
.returnType(DBTypes.LONG).fromProperty(p.pxy().getCompany().getEmployeeCount());
Query query = builder.select(p, c, e).add(sum)
.from(p)
.join(c)
.on(c.pxy().getId())
.eq(p.pxy().getCompany().getId())
.and(c.pxy().getNumber())
.eq(p.pxy().getCompany().getNumber())
.eqProperty(p.pxy().getCompany())
.join(e)
.on(e.pxy().getNumber())
.eq(p.pxy().getEmployee().getNumber())
.and(e.pxy().getCompany().getId())
.eq(p.pxy().getCompany().getId())
.eqProperty(p.pxy().getEmployee())
.and(e.pxy().getCompany().getNumber())
.eq(p.pxy().getCompany().getNumber())
.where()
.clauseIf(true, e.pxy().getName())
.condition(new Like(new ParamValue("%o"))).and()
.clauseIf(false, new Lower(new ParamField(c, c.pxy().getName()))).condition(new Equals(new ParamValue(null))).and()
.clauseIf(false, e.pxy().getNumber()).condition(
new In(new ParamSubQuery(builder.subQuery().select(e2).from(e2)
.where().clause(e.pxy().getNumber()).condition(
new GreaterThan(new ParamValue(391)))))).and()
.clause(new Sentence(builder.subQuery().select(e2).from(e2).limit(1))).condition(new GreaterThan(1))
.groupBy()
.having().clause(sum).condition(new GreaterThanEquals(1))
.orderBy().asc(p, p.pxy().getDescription())
.limit(10);
List<Post> list = query.executeQuery();
for (Post reg : list) {
Assert.assertNotNull(reg.getCompany());
Assert.assertNotNull(reg.getCompany().getName());
Assert.assertNotNull(reg.getEmployee().getName());
}
}catch (Exception e) {
throw new BeanException(e);
}finally {
SQLUtils.close(conn);
}
}
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/test/java/org/mentabean/jdbc/AnotherProxyTest.java
New file
0,0 → 1,250
package org.mentabean.jdbc;
 
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
import static org.mentabean.jdbc.AnsiSQLBeanSession.DEBUG;
 
import java.math.BigDecimal;
import java.sql.Connection;
import java.util.LinkedList;
import java.util.List;
 
import org.junit.Test;
import org.mentabean.BeanConfig;
import org.mentabean.BeanManager;
import org.mentabean.BeanSession;
import org.mentabean.DBTypes;
import org.mentabean.util.PropertiesProxy;
 
public class AnotherProxyTest extends AbstractBeanSessionTest {
 
public static class Person {
private String name;
 
public String getName() {
return name;
}
 
public void setName(String name) {
this.name = name;
}
}
public static class Customer extends Person {
private int code;
private Boolean active;
private BigDecimal height;
private int age;
private Type type;
private TypeTwo typeTwo;
public Customer() {
}
public Customer(int code, String name, Boolean active) {
this.code = code;
setName(name);
this.active = active;
}
public Customer(int code) {
this.code = code;
}
public Customer(String name, Boolean active, BigDecimal height) {
setName(name);
this.active = active;
this.height = height;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public Boolean getActive() {
return active;
}
public void setActive(Boolean active) {
this.active = active;
}
public BigDecimal getHeight() {
return height;
}
public void setHeight(BigDecimal height) {
this.height = height;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Type getType() {
return type;
}
public void setType(Type type) {
this.type = type;
}
public TypeTwo getTypeTwo() {
return typeTwo;
}
public void setTypeTwo(TypeTwo typeTwo) {
this.typeTwo = typeTwo;
}
}
public enum Type {
A, B, C;
}
public enum TypeTwo {
A {}, B {}, C {};
}
private BeanManager getBeanManagerCustomer() {
 
BeanManager beanManager = new BeanManager();
 
Customer customerProxy = PropertiesProxy.create(Customer.class);
BeanConfig customerConfig = new BeanConfig(Customer.class, "customers")
.pk(customerProxy.getCode(), "idcustomers", DBTypes.AUTOINCREMENT)
.field(customerProxy.getName(), "name_db", DBTypes.STRING.size(-1))
.field(customerProxy.getActive(), "active_db", DBTypes.BOOLEAN)
.field(customerProxy.getHeight(), "height_db", DBTypes.BIGDECIMAL)
.field(customerProxy.getAge(), "age_db", DBTypes.INTEGER)
.field(customerProxy.getType(), DBTypes.ENUMVALUE.from(Type.class).nullable(true))
.field(customerProxy.getTypeTwo(), DBTypes.ENUMVALUE.from(TypeTwo.class).nullable(true));
//add configurations in beanManager
beanManager.addBeanConfig(customerConfig);
return beanManager;
}
@Test
public void test() {
DEBUG = false;
final Connection conn = getConnection();
try {
BeanSession session = new H2BeanSession(getBeanManagerCustomer(), conn);
session.createTables();
//let's play...
Customer c1 = new Customer("Erico", true, new BigDecimal("3.5"));
c1.setAge(22);
c1.setType(Type.A);
c1.setTypeTwo(TypeTwo.B);
Customer c2 = new Customer("Jessica", true, new BigDecimal("692.894"));
Customer c3 = new Customer("Inactive customer", false, null);
session.insert(c1);
session.insert(c2);
session.insert(c3);
Customer pxy = PropertiesProxy.create(Customer.class);
Customer cDB = new Customer(c3.getCode());
session.loadMinus(cDB, pxy.getActive());
session.loadList(new Customer(), pxy.getName(), pxy.getActive());
c1 = new Customer(c1.getCode());
session.load(c1);
assertEquals(22, c1.getAge());
assertEquals(Type.A, c1.getType());
assertEquals(TypeTwo.B, c1.getTypeTwo());
Customer upd = new Customer(c1.getCode());
upd.setName("Erico KL");
session.update(upd, pxy.getHeight(), "age");
session.load(upd);
assertNull(upd.getHeight());
assertEquals(0, upd.getAge());
assertNotNull(upd.getActive());
c1 = new Customer(1, "Test", true);
c2 = new Customer(2, "Test", true);
List<String> nullProps = new LinkedList<String>();
Customer merged = session.compareDifferences(c1, c2, nullProps);
assertNull(merged);
assertEquals(0, nullProps.size());
c1 = new Customer(1, "John", null);
c1.setAge(20);
c2 = new Customer(1, "Test", true);
c2.setAge(20);
merged = session.compareDifferences(c1, c2, nullProps);
assertEquals(1, merged.getCode());
assertEquals("John", merged.getName());
assertNull(merged.getActive());
assertEquals(0, merged.getAge());
assertEquals(1, nullProps.size());
assertEquals("active", nullProps.get(0));
c1 = new Customer(1, "John", null);
c1.setAge(0);
session.insert(c1);
c2 = new Customer(1, "John", true);
c2.setAge(20);
nullProps.clear();
merged = session.compareDifferences(c1, c2, nullProps);
assertEquals(c1.getCode(), merged.getCode());
assertNull(merged.getName());
assertNull(merged.getActive());
assertEquals(0, merged.getAge());
assertEquals(2, nullProps.size());
assertEquals("active", nullProps.get(0));
assertEquals("age", nullProps.get(1));
assertEquals(1, session.updateDiff(c1, c2));
Customer db = session.loadUnique(new Customer(c1.getCode()));
assertEquals(null, db.getActive());
assertEquals(0, db.getAge());
assertEquals(c1.getCode(), db.getCode());
assertEquals(null, merged.getHeight());
assertEquals("John", db.getName());
c1 = new Customer(1, "John", true);
c1.setAge(20);
c2 = new Customer(1, "John", true);
c2.setAge(0);
nullProps.clear();
merged = session.compareDifferences(c1, c2, nullProps);
assertEquals(1, merged.getCode());
assertNull(merged.getName());
assertNull(merged.getActive());
assertEquals(20, merged.getAge());
assertEquals(0, nullProps.size());
assertEquals(1, session.updateDiff(c1, c2));
c1 = new Customer(1, "John", true);
c1.setAge(20);
c2 = new Customer(1, "John", true);
c2.setAge(20);
nullProps.clear();
merged = session.compareDifferences(c1, c2, nullProps);
assertNull(merged);
assertEquals(0, nullProps.size());
} catch (Exception e) {
throw new RuntimeException(e);
}finally {
close(conn);
}
}
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/test/java/org/mentabean/jdbc/TriggerTest.java
New file
0,0 → 1,250
package org.mentabean.jdbc;
 
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
import static org.mentabean.jdbc.AnsiSQLBeanSession.DEBUG;
 
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
 
import junit.framework.Assert;
 
import org.junit.Test;
import org.mentabean.BeanConfig;
import org.mentabean.BeanManager;
import org.mentabean.BeanSession;
import org.mentabean.DBTypes;
import org.mentabean.event.TriggerAdapter;
import org.mentabean.event.TriggerEvent;
import org.mentabean.util.PropertiesProxy;
 
public class TriggerTest extends AbstractBeanSessionTest {
public static class Person {
private String name;
 
public String getName() {
return name;
}
 
public void setName(String name) {
this.name = name;
}
}
public static class Customer extends Person {
private Long code;
private Boolean active;
private BigDecimal height;
private int age;
private byte[] picture;
public Customer() {
}
public Customer(Long code, String name, Boolean active) {
this.code = code;
setName(name);
this.active = active;
}
public Customer(Long code) {
this.code = code;
}
public Customer(String name, Boolean active, BigDecimal height) {
setName(name);
this.active = active;
this.height = height;
}
public Long getCode() {
return code;
}
public void setCode(Long code) {
this.code = code;
}
public Boolean getActive() {
return active;
}
public void setActive(Boolean active) {
this.active = active;
}
public BigDecimal getHeight() {
return height;
}
public void setHeight(BigDecimal height) {
this.height = height;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public byte[] getPicture() {
return picture;
}
public void setPicture(byte[] picture) {
this.picture = picture;
}
@Override
public String toString() {
return "Customer [code=" + code + ", active=" + active
+ ", height=" + height + ", age=" + age + "]";
}
}
private BeanManager getBeanManagerCustomer() {
 
BeanManager beanManager = new BeanManager();
 
Customer customerProxy = PropertiesProxy.create(Customer.class);
BeanConfig customerConfig = new BeanConfig(Customer.class, "customers")
.pk(customerProxy.getCode(), "idcustomers", DBTypes.AUTOINCREMENT)
.field(customerProxy.getName(), "name_db", DBTypes.STRING)
.field(customerProxy.getActive(), "active_db", DBTypes.BOOLEAN)
.field(customerProxy.getHeight(), "height_db", DBTypes.BIGDECIMAL)
.field(customerProxy.getPicture(), "picture_db", DBTypes.BYTE_ARRAY)
.field(customerProxy.getAge(), "age_db", DBTypes.INTEGER);
customerConfig.trigger(new TriggerAdapter() {
@Override
public void beforeInsert(TriggerEvent evt) {
Customer c = evt.getBean();
showMsg("===> BeanConfig trigger => Before insert for: "+c);
assertNull(c.getCode());
}
@Override
public void afterInsert(TriggerEvent evt) {
Customer c = evt.getBean();
showMsg("===> BeanConfig trigger => After insert for: "+c);
assertNotNull(c.getCode());
}
});
//add configurations in beanManager
beanManager.addBeanConfig(customerConfig);
return beanManager;
}
@Test
public void test() {
DEBUG = false;
final Connection conn = getConnection();
PreparedStatement stmt = null;
try {
BeanSession session = new H2BeanSession(getBeanManagerCustomer(), conn);
session.createTables();
session.addTrigger(new TriggerAdapter() {
@Override
public void beforeInsert(TriggerEvent evt) {
showMsg("Before insert for: "+evt.getBean());
Customer c = evt.getBean();
assertNull(c.getCode());
}
@Override
public void afterInsert(TriggerEvent evt) {
showMsg("After insert for: "+evt.getBean());
Customer c = evt.getBean();
assertNotNull(c.getCode());
}
@Override
public void beforeUpdate(TriggerEvent evt) {
showMsg("Before update for: "+evt.getBean());
}
@Override
public void afterUpdate(TriggerEvent evt) {
showMsg("After update for: "+evt.getBean());
}
@Override
public void beforeDelete(TriggerEvent evt) {
showMsg("Before delete for: "+evt.getBean());
assertNotNull(evt.getSession().loadUnique(evt.getBean()));
}
@Override
public void afterDelete(TriggerEvent evt) {
showMsg("After delete for: "+evt.getBean());
assertNull(evt.getSession().loadUnique(evt.getBean()));
}
});
//let's play...
Customer c1 = new Customer("Erico", true, new BigDecimal("3.5"));
c1.setAge(22);
c1.setPicture(new byte[1024]);
Customer c2 = new Customer("Jessica", true, new BigDecimal("692.894"));
Customer c3 = new Customer("Inactive customer", false, null);
session.insert(c1);
session.insert(c2);
session.insert(c3);
session.load(c1);
Customer basic = session.createBasicInstance(c1);
Assert.assertNotNull(basic.getCode());
Assert.assertNull(basic.getName());
Assert.assertNull(basic.getActive());
Assert.assertNull(basic.getHeight());
Assert.assertNull(basic.getPicture());
Assert.assertEquals(0, basic.getAge());
session.load(c2);
assertNotNull(c1.getPicture());
assertNull(c2.getPicture());
Customer pxy = PropertiesProxy.create(Customer.class);
Customer cDB = new Customer(c3.getCode());
session.loadMinus(cDB, pxy.getActive());
session.loadList(new Customer(), pxy.getName(), pxy.getActive());
session.load(c1);
assertEquals(22, c1.getAge());
Customer upd = new Customer(c1.getCode());
upd.setName("Erico KL");
session.update(upd, pxy.getHeight(), "age");
session.load(upd);
assertNull(upd.getHeight());
assertEquals(0, upd.getAge());
assertNotNull(upd.getActive());
session.delete(upd);
} catch (Exception e) {
throw new RuntimeException(e);
}finally {
close(stmt);
close(conn);
}
}
private void showMsg(String msg) {
if (DEBUG) {
showMsg(msg);
}
}
 
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/test/java/org/mentabean/jdbc/AnsiSQLBeanSessionTest.java
New file
0,0 → 1,2015
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.jdbc;
 
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
 
import junit.framework.Assert;
 
import org.junit.BeforeClass;
import org.junit.Test;
import org.mentabean.AutoBeanConfig;
import org.mentabean.BeanConfig;
import org.mentabean.BeanException;
import org.mentabean.BeanManager;
import org.mentabean.BeanSession;
import org.mentabean.DBTypes;
import org.mentabean.sql.TableAlias;
import org.mentabean.type.EnumIdType;
import org.mentabean.util.PropertiesProxy;
import org.mentabean.util.SQLBuilder;
import org.mentabean.util.SQLUtils;
 
public class AnsiSQLBeanSessionTest extends AbstractBeanSessionTest {
 
private static final SimpleDateFormat BD_FORMATTER = new SimpleDateFormat("yyyy-MM-dd");
 
@BeforeClass
public static void setup() {
AnsiSQLBeanSession.DEBUG = false; // turn on to see SQL generated
}
 
private static class User {
 
public static enum Status {
BASIC, PREMIUM, GOLD
}
 
private long id;
private String username;
private Date birthdate;
private Status status;
private boolean deleted;
private Date insertTime;
 
public User() {
}
 
public User(long id) {
this.id = id;
}
 
public User(String username, String birthdate) {
this.username = username;
this.birthdate = fromString(birthdate);
this.status = Status.BASIC;
}
 
private static Date fromString(String date) {
try {
return BD_FORMATTER.parse(date);
} catch (Exception e) {
throw new IllegalArgumentException("Cannot parse date: " + date);
}
}
 
public void setBirthdate(String date) {
setBirthdate(fromString(date));
}
 
public long getId() {
return id;
}
 
public void setId(long id) {
this.id = id;
}
 
public String getUsername() {
return username;
}
 
public void setUsername(String username) {
this.username = username;
}
 
public Date getBirthdate() {
return birthdate;
}
 
public void setBirthdate(Date birthdate) {
this.birthdate = birthdate;
}
 
public boolean isDeleted() {
return deleted;
}
 
public void setDeleted(boolean deleted) {
this.deleted = deleted;
}
 
public Date getInsertTime() {
return insertTime;
}
 
public void setInsertTime(Date insertTime) {
this.insertTime = insertTime;
}
 
public void setStatus(Status status) {
this.status = status;
}
 
public Status getStatus() {
return status;
}
}
 
private void createTables(Connection conn) throws SQLException {
 
execUpdate(conn, "create table Users(id integer primary key auto_increment, username varchar(25), bd datetime, status varchar(20), deleted tinyint, insert_time timestamp)");
execUpdate(conn, "create table Posts(id integer primary key auto_increment, user_id integer, title varchar(200), body text, insert_time timestamp)");
}
 
private BeanConfig getUserBeanConfig() {
 
// programmatic configuration for the bean... (no annotation or XML)
 
BeanConfig config = new BeanConfig(User.class, "Users");
User userProps = PropertiesProxy.create(User.class);
config.pk(userProps.getId(), DBTypes.AUTOINCREMENT)
.field(userProps.getUsername(), DBTypes.STRING)
.field(userProps.getBirthdate(), "bd", DBTypes.DATE) // note that the database column name is different
.field(userProps.getStatus(), DBTypes.ENUMVALUE.from(User.Status.class))
.field(userProps.isDeleted(), DBTypes.BOOLEANINT)
.field(userProps.getInsertTime(), "insert_time", DBTypes.NOW_ON_INSERT_TIMESTAMP);
 
return config;
}
 
@Test
public void testCRUD() throws SQLException { // CRUD = ISUD = Insert, Select, Update, Delete
 
BeanManager beanManager = new BeanManager();
BeanConfig userConfig = getUserBeanConfig();
beanManager.addBeanConfig(userConfig);
 
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rset = null;
 
try {
 
conn = getConnection();
BeanSession session = new H2BeanSession(beanManager, conn);
 
createTables(conn);
 
// INSERT:
 
User u = new User("saoj", "1980-03-01");
u.setStatus(User.Status.GOLD);
 
session.insert(u);
 
Assert.assertEquals(1, u.getId());
Assert.assertEquals("saoj", u.getUsername());
Assert.assertEquals("1980-03-01", BD_FORMATTER.format(u.getBirthdate()));
Assert.assertEquals(false, u.isDeleted());
Assert.assertEquals(User.Status.GOLD, u.getStatus());
 
// SELECT:
 
u = new User(1);
 
boolean loaded = session.load(u);
 
Assert.assertEquals(true, loaded);
 
Assert.assertEquals(1, u.getId());
Assert.assertEquals("saoj", u.getUsername());
Assert.assertEquals("1980-03-01", BD_FORMATTER.format(u.getBirthdate()));
Assert.assertEquals(false, u.isDeleted());
Assert.assertEquals(User.Status.GOLD, u.getStatus());
Assert.assertTrue((new Date()).getTime() >= u.getInsertTime().getTime());
 
// UPDATE:
 
u.setUsername("soliveira");
 
int modified = session.update(u);
 
Assert.assertEquals(1, modified);
 
Assert.assertEquals(1, u.getId());
Assert.assertEquals("soliveira", u.getUsername());
Assert.assertEquals("1980-03-01", BD_FORMATTER.format(u.getBirthdate()));
Assert.assertEquals(false, u.isDeleted());
Assert.assertEquals(User.Status.GOLD, u.getStatus());
Assert.assertTrue((new Date()).getTime() >= u.getInsertTime().getTime());
 
// make sure the new username was saved in the database
 
u = new User(1);
 
loaded = session.load(u);
 
Assert.assertEquals(true, loaded);
 
Assert.assertEquals(1, u.getId());
Assert.assertEquals("soliveira", u.getUsername());
Assert.assertEquals("1980-03-01", BD_FORMATTER.format(u.getBirthdate()));
Assert.assertEquals(false, u.isDeleted());
Assert.assertEquals(User.Status.GOLD, u.getStatus());
Assert.assertTrue((new Date()).getTime() >= u.getInsertTime().getTime());
 
// DELETE:
 
boolean deleted = session.delete(u);
 
Assert.assertEquals(true, deleted);
 
// make sure the bean is deleted from the database...
 
u = new User(1);
 
loaded = session.load(u);
 
Assert.assertEquals(false, loaded);
 
} finally {
 
close(stmt, rset);
close(conn);
}
}
 
@Test
public void testDynUpdate() throws SQLException {
 
BeanManager beanManager = new BeanManager();
BeanConfig userConfig = getUserBeanConfig();
beanManager.addBeanConfig(userConfig);
 
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rset = null;
 
try {
 
conn = getConnection();
BeanSession session = new H2BeanSession(beanManager, conn);
 
createTables(conn);
 
// First insert, so we can test the update after...
User u = new User("saoj", "1980-03-01");
session.insert(u);
 
Assert.assertEquals(1, u.getId());
Assert.assertEquals("saoj", u.getUsername());
Assert.assertEquals("1980-03-01", BD_FORMATTER.format(u.getBirthdate()));
Assert.assertEquals(false, u.isDeleted());
 
// UNATTACHED UPDATE:
 
u = new User(1); // note that bean was NOT loaded, in other words,
// it was NOT attached to session
u.setUsername("soliveira");
 
int modified = session.update(u); // only properties that are
// considered SET will be
// updated
Assert.assertEquals(1, modified);
 
// make sure it was written to the database
u = new User(1);
boolean loaded = session.load(u);
Assert.assertEquals(true, loaded);
 
Assert.assertEquals("soliveira", u.getUsername());
 
// ATTACHED UPDATE:
 
u = new User(1);
loaded = session.load(u);
Assert.assertEquals(true, loaded);
 
u.setUsername(u.getUsername()); // setting, but nothing is
// changing...
 
modified = session.update(u); // nothing should happen here...
Assert.assertEquals(0, modified);
 
// UNATTACHED UPDATED ALL:
 
u = new User(1); // note that bean was NOT loaded, in other words,
// it was NOT attached to session
u.setUsername("julia");
 
modified = session.updateAll(u);
 
Assert.assertEquals(1, modified);
 
// everything was written to the database, even the fields that were
// NOT set
// as a result, some fields were nullified
 
u = new User(1);
loaded = session.load(u);
Assert.assertEquals(true, loaded);
Assert.assertEquals("julia", u.getUsername());
Assert.assertNull(u.getBirthdate());
Assert.assertNull(u.getInsertTime());
 
// ATTACHED UPDATE ALL:
 
u = new User(1);
loaded = session.load(u);
Assert.assertEquals(true, loaded);
 
u.setBirthdate("1980-02-02");
 
modified = session.updateAll(u);
 
Assert.assertEquals(1, modified);
 
// everything was written to the database, even the fields that were
// NOT set
 
u = new User(1);
loaded = session.load(u);
Assert.assertEquals(true, loaded);
Assert.assertEquals("julia", u.getUsername());
Assert.assertEquals("1980-02-02", BD_FORMATTER.format(u.getBirthdate()));
Assert.assertNull(u.getInsertTime());
 
} finally {
 
close(stmt, rset);
close(conn);
}
}
 
@Test
public void testMultipleInserts() throws SQLException {
 
BeanManager beanManager = new BeanManager();
BeanConfig userConfig = getUserBeanConfig();
beanManager.addBeanConfig(userConfig);
 
Connection conn = null;
 
try {
 
conn = getConnection();
BeanSession session = new H2BeanSession(beanManager, conn);
 
createTables(conn);
 
for (int i = 0; i < 10; i++) {
User u = new User();
u.setUsername("saoj" + (i + 1));
u.setBirthdate("1990-01-1" + i);
 
session.insert(u);
 
Assert.assertEquals(i + 1, u.getId());
}
} finally {
close(conn);
}
}
 
@Test
public void testLoadList() throws SQLException {
 
BeanManager beanManager = new BeanManager();
BeanConfig userConfig = getUserBeanConfig();
beanManager.addBeanConfig(userConfig);
 
Connection conn = null;
 
try {
 
conn = getConnection();
BeanSession session = new H2BeanSession(beanManager, conn);
 
createTables(conn);
 
for (int i = 0; i < 10; i++) {
User u = new User();
u.setUsername("saoj" + (i + 1));
u.setBirthdate("1990-01-1" + i);
u.setStatus(User.Status.BASIC);
 
session.insert(u);
 
Assert.assertEquals(i + 1, u.getId());
}
 
// now set one user to GOLD
 
User u = new User(5);
boolean loaded = session.load(u);
Assert.assertEquals(true, loaded);
u.setStatus(User.Status.GOLD);
int modified = session.update(u);
Assert.assertEquals(1, modified);
 
// first count to see if we are excluding the golad...
 
u = new User();
u.setStatus(User.Status.BASIC);
 
int total = session.countList(u);
 
Assert.assertEquals(9, total);
 
// now load a list of all BASIC users
 
u = new User();
u.setStatus(User.Status.BASIC);
 
List<User> users = session.loadList(u);
 
Assert.assertEquals(9, users.size());
 
// check that the GOLD user was not loaded...
 
for (User user : users) {
Assert.assertTrue(user.getId() != 5);
}
 
} finally {
close(conn);
}
}
 
private static class Post {
 
private int id;
private User user;
private String title;
private String body;
private Date insertTime;
 
public Post() {
}
 
public Post(int id) {
this.id = id;
}
 
public Post(User user, String title, String text) {
this.user = user;
this.title = title;
this.body = text;
}
 
public int getId() {
return id;
}
 
public void setId(int id) {
this.id = id;
}
 
public User getUser() {
return user;
}
 
public void setUser(User user) {
this.user = user;
}
 
public String getTitle() {
return title;
}
 
public void setTitle(String title) {
this.title = title;
}
 
public String getBody() {
return body;
}
 
public void setBody(String body) {
this.body = body;
}
 
public Date getInsertTime() {
return insertTime;
}
 
public void setInsertTime(Date insertTime) {
this.insertTime = insertTime;
}
}
 
private void getPostBeanConfig(BeanManager beanManager) {
 
// Fluent API
 
beanManager
.bean(Post.class, "Posts")
.pk("id", DBTypes.AUTOINCREMENT)
.field("user.id", "user_id", DBTypes.LONG)
.field("title", DBTypes.STRING).field("body", DBTypes.STRING)
.field("insertTime", "insert_time", DBTypes.NOW_ON_INSERT_TIMESTAMP);
}
 
@Test
public void testOneToOneRelationshipCRUD() throws SQLException {
 
BeanManager beanManager = new BeanManager();
BeanConfig userConfig = getUserBeanConfig();
getPostBeanConfig(beanManager);
beanManager.addBeanConfig(userConfig);
 
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rset = null;
 
try {
 
conn = getConnection();
BeanSession session = new H2BeanSession(beanManager, conn);
 
createTables(conn);
 
User u = new User("saoj", "1980-01-02");
session.insert(u);
 
Assert.assertEquals(1, u.getId());
 
// Now insert a post for this user...
Post p = new Post(new User(1), "Test", "This is a test!");
session.insert(p);
 
Assert.assertEquals(1, p.getId());
 
// Load from the database...
p = new Post(1);
boolean loaded = session.load(p);
Assert.assertEquals("Test", p.getTitle());
Assert.assertEquals(1, p.getUser().getId());
Assert.assertNotNull(p.getUser()); // loads user with id only
Assert.assertEquals(1, p.getUser().getId());
Assert.assertNull(p.getUser().getUsername());
 
// Load user for this post... (let's do our manual lazy loading)
u = new User(p.getUser().getId());
loaded = session.load(u);
Assert.assertEquals(true, loaded);
p.setUser(u); // manual lazy loading (forget about automatic lazy loading, you want control!)
 
// Use JOIN to load all dependencies with a single query... (you know how to make a join, right?)
 
p = new Post(1);
 
StringBuilder query = new StringBuilder(256);
query.append("select ");
query.append(session.buildSelect(Post.class, "p"));
query.append(", ");
query.append(session.buildSelect(User.class, "u"));
query.append(" from Posts p join Users u on p.user_id = u.id");
query.append(" where p.id = ?");
 
stmt = SQLUtils.prepare(conn, query.toString(), p.getId());
rset = stmt.executeQuery();
 
if (rset.next()) {
 
session.populateBean(rset, p, "p");
 
u = new User();
 
session.populateBean(rset, u, "u");
 
p.setUser(u); // manual lazy loading (we prefer to have control!)
}
 
Assert.assertEquals(1, p.getId());
Assert.assertEquals("Test", p.getTitle());
Assert.assertEquals(1, u.getId());
Assert.assertEquals("saoj", p.getUser().getUsername());
Assert.assertTrue((new Date()).getTime() >= p.getInsertTime().getTime());
 
rset.close();
stmt.close();
 
// Deleting => No cascade deletes, if you want that implement in the database level...
 
u = new User(1);
boolean deleted = session.delete(u);
Assert.assertEquals(true, deleted);
 
// Post of course is still there...
p = new Post(1);
loaded = session.load(p);
Assert.assertEquals(true, loaded);
Assert.assertEquals(1, p.getUser().getId()); // of course this user is gone!
 
u = new User(1);
loaded = session.load(u);
Assert.assertEquals(false, loaded); // use was deleted above...
 
} finally {
close(stmt, rset);
close(conn);
}
}
 
@Test
public void testOneToOneRelationshipCRUDWithTableAlias() throws SQLException {
 
BeanManager beanManager = new BeanManager();
BeanConfig userConfig = getUserBeanConfig();
getPostBeanConfig(beanManager);
beanManager.addBeanConfig(userConfig);
 
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rset = null;
 
try {
 
conn = getConnection();
BeanSession session = new H2BeanSession(beanManager, conn);
 
createTables(conn);
 
User u = new User("saoj", "1980-01-02");
session.insert(u);
 
Assert.assertEquals(1, u.getId());
 
// Now insert a post for this user...
Post p = new Post(new User(1), "Test", "This is a test!");
session.insert(p);
 
Assert.assertEquals(1, p.getId());
 
// Load from the database...
p = new Post(1);
boolean loaded = session.load(p);
Assert.assertEquals("Test", p.getTitle());
Assert.assertEquals(1, p.getUser().getId());
Assert.assertNotNull(p.getUser());
Assert.assertEquals(1, p.getUser().getId());
Assert.assertNull(p.getUser().getUsername());
 
// Load user for this post... (let's do our manual lazy loading)
u = new User(p.getUser().getId());
loaded = session.load(u);
Assert.assertEquals(true, loaded);
p.setUser(u); // manual lazy loading (forget about automatic lazy loading, you want control!)
 
// Use JOIN to load all dependencies with a single query... (you know how to make a join, right?)
 
p = new Post(1);
TableAlias<Post> postAlias = session.createTableAlias(Post.class, "p");
TableAlias<User> userAlias = session.createTableAlias(User.class, "u");
 
StringBuilder query = new StringBuilder(256);
query.append("select ");
query.append(postAlias.columns());
query.append(", ");
query.append(userAlias.columns());
query.append(" from ").append(postAlias.tableName());
query.append(" join ").append(userAlias.tableName());
query.append(" on ");
query.append(postAlias.column(postAlias.pxy().getUser().getId())).append(" = ").append(userAlias.column(userAlias.pxy().getId()));
query.append(" where ");
query.append(postAlias.column(postAlias.pxy().getId()));
query.append(" = ?");
stmt = SQLUtils.prepare(conn, query.toString(), p.getId());
rset = stmt.executeQuery();
 
if (rset.next()) {
 
session.populateBean(rset, p, "p");
 
u = new User();
 
session.populateBean(rset, u, "u");
 
p.setUser(u); // manual lazy loading (we prefer to have control!)
}
 
Assert.assertEquals(1, p.getId());
Assert.assertEquals("Test", p.getTitle());
Assert.assertEquals(1, u.getId());
Assert.assertEquals("saoj", p.getUser().getUsername());
Assert.assertTrue((new Date()).getTime() >= p.getInsertTime().getTime());
 
rset.close();
stmt.close();
 
// Deleting => No cascade deletes, if you want that implement in the database level...
 
u = new User(1);
boolean deleted = session.delete(u);
Assert.assertEquals(true, deleted);
 
// Post of course is still there...
p = new Post(1);
loaded = session.load(p);
Assert.assertEquals(true, loaded);
Assert.assertEquals(1, p.getUser().getId()); // of course this user is gone!
 
u = new User(1);
loaded = session.load(u);
Assert.assertEquals(false, loaded); // use was deleted above...
 
} finally {
close(stmt, rset);
close(conn);
}
}
 
@Test
public void testSQLBuilder() throws SQLException {
 
BeanManager beanManager = new BeanManager();
BeanConfig userConfig = getUserBeanConfig();
getPostBeanConfig(beanManager);
beanManager.addBeanConfig(userConfig);
 
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rset = null;
 
try {
 
conn = getConnection();
BeanSession session = new H2BeanSession(beanManager, conn);
 
createTables(conn);
 
User u = new User("saoj", "1980-01-02");
session.insert(u);
 
Assert.assertEquals(1, u.getId());
 
// Now insert a post for this user...
Post p = new Post(new User(1), "Test", "This is a test!");
session.insert(p);
 
Assert.assertEquals(1, p.getId());
 
// Load from the database...
p = new Post(1);
boolean loaded = session.load(p);
Assert.assertEquals("Test", p.getTitle());
Assert.assertEquals(1, p.getUser().getId());
Assert.assertNotNull(p.getUser());
Assert.assertEquals(1, p.getUser().getId());
Assert.assertNull(p.getUser().getUsername());
 
// Load user for this post... (let's do our manual lazy loading)
u = new User(p.getUser().getId());
loaded = session.load(u);
Assert.assertEquals(true, loaded);
p.setUser(u); // manual lazy loading (forget about automatic lazy loading, you want control!)
 
// Use JOIN to load all dependencies with a single query... (you know how to make a join, right?)
 
p = new Post(1);
TableAlias<Post> postAlias = session.createTableAlias(Post.class, "p");
TableAlias<User> userAlias = session.createTableAlias(User.class, "u");
Post post = postAlias.pxy();
User user = userAlias.pxy();
 
SQLBuilder query = new SQLBuilder(256, postAlias, userAlias);
query.append("select ");
query.append(postAlias.columns());
query.append(", ");
query.append(userAlias.columns());
query.append(" from ").append(postAlias.tableName());
query.append(" join ").append(userAlias.tableName());
query.append(" on ");
// query.append(postAlias.column(postAlias.pxy().getUser().getId())).append(" = ").append(userAlias.column(userAlias.pxy().getId()));
query.column(post.getUser().getId()).append(" = ").column(user.getId());
query.append(" where ");
// query.append(postAlias.column(postAlias.pxy().getId()));
query.column(post.getId());
query.append(" = ?");
stmt = SQLUtils.prepare(conn, query.toString(), p.getId());
rset = stmt.executeQuery();
 
if (rset.next()) {
 
session.populateBean(rset, p, "p");
 
u = new User();
 
session.populateBean(rset, u, "u");
 
p.setUser(u); // manual lazy loading (we prefer to have control!)
}
 
Assert.assertEquals(1, p.getId());
Assert.assertEquals("Test", p.getTitle());
Assert.assertEquals(1, u.getId());
Assert.assertEquals("saoj", p.getUser().getUsername());
Assert.assertTrue((new Date()).getTime() >= p.getInsertTime().getTime());
 
rset.close();
stmt.close();
 
// Deleting => No cascade deletes, if you want that implement in the database level...
 
u = new User(1);
boolean deleted = session.delete(u);
Assert.assertEquals(true, deleted);
 
// Post of course is still there...
p = new Post(1);
loaded = session.load(p);
Assert.assertEquals(true, loaded);
Assert.assertEquals(1, p.getUser().getId()); // of course this user is gone!
 
u = new User(1);
loaded = session.load(u);
Assert.assertEquals(false, loaded); // use was deleted above...
 
} finally {
close(stmt, rset);
close(conn);
}
}
@Test
public void testSQLBuilder2() throws SQLException {
 
BeanManager beanManager = new BeanManager();
BeanConfig userConfig = getUserBeanConfig();
getPostBeanConfig(beanManager);
beanManager.addBeanConfig(userConfig);
 
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rset = null;
 
try {
 
conn = getConnection();
BeanSession session = new H2BeanSession(beanManager, conn);
 
createTables(conn);
 
User u = new User("saoj", "1980-01-02");
session.insert(u);
 
Assert.assertEquals(1, u.getId());
 
// Now insert a post for this user...
Post p = new Post(new User(1), "Test", "This is a test!");
session.insert(p);
 
Assert.assertEquals(1, p.getId());
 
// Load from the database...
p = new Post(1);
boolean loaded = session.load(p);
Assert.assertEquals("Test", p.getTitle());
Assert.assertEquals(1, p.getUser().getId());
Assert.assertNotNull(p.getUser());
Assert.assertEquals(1, p.getUser().getId());
Assert.assertNull(p.getUser().getUsername());
 
// Load user for this post... (let's do our manual lazy loading)
u = new User(p.getUser().getId());
loaded = session.load(u);
Assert.assertEquals(true, loaded);
p.setUser(u); // manual lazy loading (forget about automatic lazy loading, you want control!)
 
// Use JOIN to load all dependencies with a single query... (you know how to make a join, right?)
 
p = new Post(1);
TableAlias<Post> postAlias = session.createTableAlias(Post.class, "p");
TableAlias<User> userAlias = session.createTableAlias(User.class, "u");
Post post = postAlias.pxy();
User user = userAlias.pxy();
 
SQLBuilder query = new SQLBuilder(256, postAlias, userAlias);
query.append("select ");
query.append(postAlias.columnsMinus(post.getTitle()));
query.append(", ");
query.append(userAlias.columns());
query.append(" from ").append(postAlias.tableName());
query.append(" join ").append(userAlias.tableName());
query.append(" on ");
// query.append(postAlias.column(postAlias.pxy().getUser().getId())).append(" = ").append(userAlias.column(userAlias.pxy().getId()));
query.column(post.getUser().getId()).append(" = ").column(user.getId());
query.append(" where ");
// query.append(postAlias.column(postAlias.pxy().getId()));
query.column(post.getId());
query.append(" = ?");
stmt = SQLUtils.prepare(conn, query.toString(), p.getId());
rset = stmt.executeQuery();
 
if (rset.next()) {
 
//XXX aqui daria erro pois a session não vai conseguir popular p_title
//É por isso que o Alias do QueryBuilder tem o seu próprio populateBean,
//pois ele já sabe quais propriedades foram informadas..
//session.populateBean(rset, p, "p");
//XXX "minus" repetitivo...
session.populateBeanMinus(rset, p, "p", post.getTitle());
 
//possível solução.. fazer um populateBean no TableAlias que já pegasse
//o prefix e também as properties que devem retornar
//algo como:
//postAlias.populateBean(rset, p);
u = new User();
 
session.populateBean(rset, u, "u");
 
p.setUser(u); // manual lazy loading (we prefer to have control!)
}
 
Assert.assertEquals(1, p.getId());
Assert.assertNull(p.getTitle());
Assert.assertEquals(1, u.getId());
Assert.assertEquals("saoj", p.getUser().getUsername());
Assert.assertTrue((new Date()).getTime() >= p.getInsertTime().getTime());
 
rset.close();
stmt.close();
 
// Deleting => No cascade deletes, if you want that implement in the database level...
 
u = new User(1);
boolean deleted = session.delete(u);
Assert.assertEquals(true, deleted);
 
// Post of course is still there...
p = new Post(1);
loaded = session.load(p);
Assert.assertEquals(true, loaded);
Assert.assertEquals(1, p.getUser().getId()); // of course this user is gone!
 
u = new User(1);
loaded = session.load(u);
Assert.assertEquals(false, loaded); // use was deleted above...
 
} finally {
close(stmt, rset);
close(conn);
}
}
@Test
public void testSQLBuilder3() throws SQLException {
BeanManager beanManager = new BeanManager();
BeanConfig userConfig = getUserBeanConfig();
getPostBeanConfig(beanManager);
beanManager.addBeanConfig(userConfig);
 
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rset = null;
 
try {
 
conn = getConnection();
BeanSession session = new H2BeanSession(beanManager, conn);
 
createTables(conn);
 
User u = new User("erico", "1991-01-31");
session.insert(u);
 
TableAlias<User> userAlias1 = session.createTableAlias(User.class, "u");
TableAlias<User> userAlias2 = session.createTableAlias(User.class, "u2");
User user1 = userAlias1.pxy();
User user2 = userAlias2.pxy();
 
SQLBuilder query = new SQLBuilder(userAlias1, userAlias2);
query.append("select ");
query.append(userAlias1.columns());
query.append(" from ").append(userAlias1.tableName());
query.append(" where ").column(user1.getId());
query.append(" in (select ").column(user2.getId());
query.append(" from ").append(userAlias2.tableName());
query.append(")");
Assert.assertTrue(query.toString().contains("(select u2.id"));
stmt = SQLUtils.prepare(conn, query.toString());
rset = stmt.executeQuery();
 
if (rset.next()) {
 
u = new User();
 
session.populateBean(rset, u, "u");
}
 
Assert.assertEquals(1, u.getId());
Assert.assertEquals("erico", u.getUsername());
 
} finally {
close(stmt);
close(conn);
}
}
@Test
public void testLoadUnique() throws SQLException {
 
BeanManager beanManager = new BeanManager();
BeanConfig userConfig = getUserBeanConfig();
beanManager.addBeanConfig(userConfig);
 
Connection conn = null;
 
try {
 
conn = getConnection();
BeanSession session = new H2BeanSession(beanManager, conn);
 
createTables(conn);
 
User u1 = new User("saoj", "1983-01-02");
session.insert(u1);
 
User u = new User();
u.setUsername("saoj");
 
u = session.loadUnique(u);
 
Assert.assertEquals(1, u.getId());
Assert.assertEquals("saoj", u.getUsername());
 
// now add another one and try again...
 
User u2 = new User("saoj", "1967-01-03");
session.insert(u2);
 
u = new User();
u.setUsername("saoj");
 
boolean ok = false;
 
try {
 
u = session.loadUnique(u);
 
ok = true; // cannot come here...
 
} catch (BeanException e) {
 
ok = false;
}
 
Assert.assertEquals(false, ok);
//loadUnique specifying properties
u = new User();
u.setBirthdate("1967-01-03");
User proxy = PropertiesProxy.create(User.class);
u = session.loadUnique(u, proxy.getUsername()); //only username
Assert.assertNull(u.getBirthdate());
Assert.assertNull(u.getInsertTime());
Assert.assertNull(u.getStatus());
Assert.assertEquals(2, u.getId()); //always load the pk
Assert.assertNotNull(u.getUsername());
//loadUnique specifying 'minus' properties
u = new User();
u.setBirthdate("1967-01-03");
u = session.loadUniqueMinus(u, proxy.getUsername(), proxy.getId()); //not load username nor pk (mentabean must ignore this)
Assert.assertNotNull(u.getBirthdate());
Assert.assertNotNull(u.getInsertTime());
Assert.assertNotNull(u.getStatus());
Assert.assertEquals(2, u.getId()); //always load the pk... I mean, always
Assert.assertNull(u.getUsername());
 
} finally {
close(conn);
}
}
 
@Test
public void testSettingProperties() throws SQLException {
 
BeanManager beanManager = new BeanManager();
BeanConfig userConfig = getUserBeanConfig();
beanManager.addBeanConfig(userConfig);
 
Connection conn = null;
 
try {
 
conn = getConnection();
BeanSession session = new H2BeanSession(beanManager, conn);
 
createTables(conn);
 
User saoj = new User("saoj", "1980-01-01");
session.insert(saoj);
 
User julia = new User("julia", "1980-03-03");
session.insert(julia);
 
// delete "saoj" by making deleted equals to false
saoj.setDeleted(true);
int modified = session.update(saoj);
Assert.assertEquals(1, modified);
 
// load all non-deleted users...
User u = new User();
u.setStatus(User.Status.BASIC);
u.setDeleted(false);
List<User> nonDeletedUsers = session.loadList(u);
Assert.assertFalse(nonDeletedUsers.size() == 1); // THIS DOES NOT WORK because isDeleted() returns a boolean primitive
Assert.assertEquals(2, nonDeletedUsers.size()); // it will return everything because the deleted = false condition was never detected
 
// to fix, let's change the property to return a Boolean
beanManager.addBeanConfig(getUser2BeanConfig());
 
// now try again
User2 u2 = new User2();
u2.setDeleted(false);
List<User2> nonDeletedUsers2 = session.loadList(u2);
Assert.assertEquals(1, nonDeletedUsers2.size()); // now only ONE is returned, the non-deleted one...
 
} finally {
close(conn);
}
}
 
private static class User2 {
 
public static enum Status {
BASIC, PREMIUM, GOLD
}
 
private int id;
private String username;
private Date birthdate;
private Status status = Status.BASIC;
private boolean deleted;
private Date insertTime;
 
public User2() {
}
 
public User2(int id) {
this.id = id;
}
 
public User2(String username, String birthdate) {
this.username = username;
this.birthdate = fromString(birthdate);
}
 
private static Date fromString(String date) {
try {
return BD_FORMATTER.parse(date);
} catch (Exception e) {
throw new IllegalArgumentException("Cannot parse date: " + date);
}
}
 
public void setBirthdate(String date) {
setBirthdate(fromString(date));
}
 
public int getId() {
return id;
}
 
public void setId(int id) {
this.id = id;
}
 
public String getUsername() {
return username;
}
 
public void setUsername(String username) {
this.username = username;
}
 
public Date getBirthdate() {
return birthdate;
}
 
public void setBirthdate(Date birthdate) {
this.birthdate = birthdate;
}
 
public Boolean isDeleted() {
return deleted;
}
 
public void setDeleted(boolean deleted) {
this.deleted = deleted;
}
 
public Date getInsertTime() {
return insertTime;
}
 
public void setInsertTime(Date insertTime) {
this.insertTime = insertTime;
}
 
public void setStatus(Status status) {
this.status = status;
}
 
public Status getStatus() {
return status;
}
}
 
private BeanConfig getUser2BeanConfig() {
 
// programmatic configuration for the bean... (no annotation or XML)
 
BeanConfig config = new BeanConfig(User2.class, "Users");
config.pk("id", DBTypes.AUTOINCREMENT);
config.field("username", DBTypes.STRING);
config.field("birthdate", "bd", DBTypes.DATE); // note that the database column name is different
config.field("status", DBTypes.ENUMVALUE.from(User2.Status.class));
config.field("deleted", DBTypes.BOOLEANINT);
config.field("insertTime", "insert_time", DBTypes.NOW_ON_INSERT_TIMESTAMP);
 
return config;
}
 
@Test
public void testEnumIdType() throws SQLException {
 
BeanManager beanManager = new BeanManager();
BeanConfig userConfig = getUser3BeanConfig();
beanManager.addBeanConfig(userConfig);
 
Connection conn = null;
 
try {
 
conn = getConnection();
BeanSession session = new H2BeanSession(beanManager, conn);
 
execUpdate(conn, "create table Users(id integer primary key auto_increment, username varchar(25), bd datetime, status integer, deleted tinyint, insert_time timestamp)");
 
User3 u = new User3("saoj", "1980-03-03");
u.setStatus(User3.Status.GOLD);
session.insert(u);
 
// now load and see if we get the same status...
u = new User3(1);
boolean loaded = session.load(u);
Assert.assertEquals(true, loaded);
Assert.assertEquals(User3.Status.GOLD, u.getStatus());
 
} finally {
close(conn);
}
}
 
private static class User3 {
 
public static enum Status {
BASIC(1), PREMIUM(2), GOLD(3);
 
private final int id;
 
private Status(int id) {
this.id = id;
}
 
public int getId() {
return id;
}
 
public static Status fromId(int id) {
for (Status s : Status.values()) {
if (s.getId() == id) {
return s;
}
}
return null;
}
}
 
private int id;
private String username;
private Date birthdate;
private Status status = Status.BASIC;
private boolean deleted;
private Date insertTime;
 
public User3() {
}
 
public User3(int id) {
this.id = id;
}
 
public User3(String username, String birthdate) {
this.username = username;
this.birthdate = fromString(birthdate);
}
 
private static Date fromString(String date) {
try {
return BD_FORMATTER.parse(date);
} catch (Exception e) {
throw new IllegalArgumentException("Cannot parse date: " + date);
}
}
 
public void setBirthdate(String date) {
setBirthdate(fromString(date));
}
 
public int getId() {
return id;
}
 
public void setId(int id) {
this.id = id;
}
 
public String getUsername() {
return username;
}
 
public void setUsername(String username) {
this.username = username;
}
 
public Date getBirthdate() {
return birthdate;
}
 
public void setBirthdate(Date birthdate) {
this.birthdate = birthdate;
}
 
public Boolean isDeleted() {
return deleted;
}
 
public void setDeleted(boolean deleted) {
this.deleted = deleted;
}
 
public Date getInsertTime() {
return insertTime;
}
 
public void setInsertTime(Date insertTime) {
this.insertTime = insertTime;
}
 
public void setStatus(Status status) {
this.status = status;
}
 
public Status getStatus() {
return status;
}
}
 
private BeanConfig getUser3BeanConfig() {
 
// programmatic configuration for the bean... (no annotation or XML)
 
BeanConfig config = new BeanConfig(User3.class, "Users");
config.pk("id", DBTypes.AUTOINCREMENT);
config.field("username", DBTypes.STRING);
config.field("birthdate", "bd", DBTypes.DATE); // note that the database column name is different
config.field("status", new EnumIdType(User3.Status.class));
config.field("deleted", DBTypes.BOOLEANINT);
config.field("insertTime", "insert_time", DBTypes.NOW_ON_INSERT_TIMESTAMP);
 
return config;
}
 
@Test
public void testCreateTable() throws SQLException {
 
BeanManager beanManager = new BeanManager();
BeanConfig userConfig = getUser4BeanConfig();
beanManager.addBeanConfig(userConfig);
 
Connection conn = null;
 
try {
 
conn = getConnection();
BeanSession session = new H2BeanSession(beanManager, conn);
 
Assert.assertFalse(SQLUtils.checkIfTableExists(conn, "Users"));
 
session.createTables();
 
Assert.assertTrue(SQLUtils.checkIfTableExists(conn, "Users"));
 
} finally {
close(conn);
}
}
 
@Test
public void testAutoBeanConfig() throws SQLException {
 
BeanManager beanManager = new BeanManager();
BeanConfig userConfig = new AutoBeanConfig(User4.class, "Users");
beanManager.addBeanConfig(userConfig);
 
userConfig.pk("id", DBTypes.AUTOINCREMENT); // override since PK and autoincrement cannot be discovered by reflection...
 
Connection conn = null;
 
try {
 
conn = getConnection();
BeanSession session = new H2BeanSession(beanManager, conn);
 
// execUpdate(conn, "create table Users(id integer primary key auto_increment, username varchar(25), birthdate datetime, status integer, deleted tinyint, insert_time timestamp, update_time timestamp)");
session.createTables();
 
User4 u = new User4("saoj", "1980-03-03");
u.setStatus(User4.Status.GOLD);
session.insert(u);
 
// now load and see if we get the same status...
u = new User4(1);
boolean loaded = session.load(u);
Assert.assertEquals(true, loaded);
Assert.assertEquals(User4.Status.GOLD, u.getStatus());
 
// update_time must be null
Assert.assertNull(u.getUpdateTime());
 
} finally {
close(conn);
}
}
 
@Test
public void testNowOnUpdate() throws SQLException {
 
BeanManager beanManager = new BeanManager();
BeanConfig userConfig = getUser4BeanConfig();
beanManager.addBeanConfig(userConfig);
 
Connection conn = null;
 
try {
 
conn = getConnection();
BeanSession session = new H2BeanSession(beanManager, conn);
 
execUpdate(conn, "create table Users(id integer primary key auto_increment, username varchar(25), bd datetime, status integer, deleted tinyint, insert_time timestamp, update_time timestamp)");
 
User4 u = new User4("saoj", "1980-03-03");
u.setStatus(User4.Status.GOLD);
session.insert(u);
 
// now load and see if we get the same status...
u = new User4(1);
boolean loaded = session.load(u);
Assert.assertEquals(true, loaded);
Assert.assertEquals(User4.Status.GOLD, u.getStatus());
 
// update_time must be null
Assert.assertNull(u.getUpdateTime());
 
// now update..
u.setUsername("saoj1");
session.update(u);
 
// update_time is still null, you need to load !!!
Assert.assertNull(u.getUpdateTime());
 
session.load(u);
Assert.assertNotNull(u.getUpdateTime());
 
} finally {
close(conn);
}
}
 
private static class User4 {
 
public static enum Status {
BASIC(1), PREMIUM(2), GOLD(3);
 
private final int id;
 
private Status(int id) {
this.id = id;
}
 
public int getId() {
return id;
}
 
public static Status fromId(int id) {
for (Status s : Status.values()) {
if (s.getId() == id) {
return s;
}
}
return null;
}
}
 
private int id;
private String username;
private Date birthdate;
private Status status = Status.BASIC;
private boolean deleted;
private Date insertTime;
private Date updateTime;
 
public Date getUpdateTime() {
return updateTime;
}
 
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
 
public User4() {
}
 
public User4(int id) {
this.id = id;
}
 
public User4(String username, String birthdate) {
this.username = username;
this.birthdate = fromString(birthdate);
}
 
private static Date fromString(String date) {
try {
return BD_FORMATTER.parse(date);
} catch (Exception e) {
throw new IllegalArgumentException("Cannot parse date: " + date);
}
}
 
public void setBirthdate(String date) {
setBirthdate(fromString(date));
}
 
public int getId() {
return id;
}
 
public void setId(int id) {
this.id = id;
}
 
public String getUsername() {
return username;
}
 
public void setUsername(String username) {
this.username = username;
}
 
public Date getBirthdate() {
return birthdate;
}
 
public void setBirthdate(Date birthdate) {
this.birthdate = birthdate;
}
 
public Boolean isDeleted() {
return deleted;
}
 
public void setDeleted(boolean deleted) {
this.deleted = deleted;
}
 
public Date getInsertTime() {
return insertTime;
}
 
public void setInsertTime(Date insertTime) {
this.insertTime = insertTime;
}
 
public void setStatus(Status status) {
this.status = status;
}
 
public Status getStatus() {
return status;
}
}
 
private BeanConfig getUser4BeanConfig() {
 
// programmatic configuration for the bean... (no annotation or XML)
 
BeanConfig config = new BeanConfig(User4.class, "Users");
config.pk("id", DBTypes.AUTOINCREMENT);
config.field("username", DBTypes.STRING.size(50).nullable(false));
config.field("birthdate", "bd", DBTypes.DATE); // note that the database column name is different
config.field("status", new EnumIdType(User4.Status.class));
config.field("deleted", DBTypes.BOOLEANINT);
config.field("insertTime", "insert_time", DBTypes.NOW_ON_INSERT_TIMESTAMP);
config.field("updateTime", "update_time", DBTypes.NOW_ON_UPDATE_TIMESTAMP);
 
return config;
}
/*
* Testing sublevels
*/
public static class Foo {
private long id;
private Bar bar;
private String test;
private Bean bean;
public Foo() {}
public Foo(long id, String test, Bean bean) {
super();
this.id = id;
this.test = test;
this.bean = bean;
}
 
public Foo(long id) {
this.id = id;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public Bar getBar() {
return bar;
}
public void setBar(Bar bar) {
this.bar = bar;
}
public String getTest() {
return test;
}
public void setTest(String test) {
this.test = test;
}
public Bean getBean() {
return bean;
}
public void setBean(Bean bean) {
this.bean = bean;
}
}
public static class Bean {
private long id;
 
public Bean(long id) {
this.id = id;
}
 
public Bean() {}
 
public long getId() {
return id;
}
 
public void setId(long id) {
this.id = id;
}
@Override
public String toString() {
return "Bean: "+id;
}
}
public static class Bar {
private String name;
private Item item;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Item getItem() {
return item;
}
public void setItem(Item item) {
this.item = item;
}
}
public static class Item {
private SubItem subItem;
 
public SubItem getSubItem() {
return subItem;
}
 
public void setSubItem(SubItem subItem) {
this.subItem = subItem;
}
}
public static class SubItem {
private String name;
 
public String getName() {
return name;
}
 
public void setName(String name) {
this.name = name;
}
}
private BeanConfig getSublevelsBeanConfig() {
Foo foo = PropertiesProxy.create(Foo.class);
BeanConfig config = new BeanConfig(Foo.class, "foo")
.pk(foo.getId(), "idfoo", DBTypes.LONG)
.field(foo.getTest(), DBTypes.STRING)
.field(foo.getBean().getId(), "idbean", DBTypes.LONG)
.field(foo.getBar().getItem().getSubItem().getName(), "namebar", DBTypes.STRING);
return config;
}
private Foo createEmptyFoo() {
Foo foo = new Foo();
foo.setBar(new Bar());
foo.getBar().setItem(new Item());
foo.getBar().getItem().setSubItem(new SubItem());
return foo;
}
@Test
public void testSublevels() {
Connection conn = null;
BeanManager beanManager = new BeanManager();
beanManager.addBeanConfig(getSublevelsBeanConfig());
try {
 
conn = getConnection();
BeanSession session = new H2BeanSession(beanManager, conn);
session.createTables();
 
Foo foo = createEmptyFoo();
foo.getBar().getItem().getSubItem().setName("Test one");
foo.setId(1);
foo.setTest("Test one");
session.insert(foo);
foo.getBar().getItem().getSubItem().setName("Test two");
foo.setId(2);
foo.setTest("Test two");
session.insert(foo);
foo.setId(0);
foo.setTest(null);
int count = session.countList(foo);
Assert.assertEquals(1, count);
//here, if we don't force the creation of instances, a NPE will thrown
//getDeepestBean(bean, chain, true); --> findMethodToGet
count = session.countList(new Foo());
Assert.assertEquals(2, count);
foo = createEmptyFoo();
foo.setId(1);
foo.setTest("Test three");
session.update(foo);
Foo fooBD = new Foo();
fooBD.setId(1);
session.load(fooBD);
Assert.assertEquals("Test one", fooBD.getBar().getItem().getSubItem().getName());
Assert.assertEquals("Test three", fooBD.getTest());
foo = new Foo();
foo.setId(1);
foo.setTest("Test four");
session.update(foo);
fooBD = new Foo();
fooBD.setId(1);
session.load(fooBD);
Assert.assertEquals("Test one", fooBD.getBar().getItem().getSubItem().getName());
Assert.assertEquals("Test four", fooBD.getTest());
Foo proto = new Foo();
List<Foo> listBD = session.loadList(proto);
Assert.assertEquals(2, listBD.size());
Assert.assertNull(listBD.get(0).getBean());
Assert.assertNull(listBD.get(1).getBean());
Foo proxy = PropertiesProxy.create(Foo.class);
foo = new Foo(1);
foo.setTest("Test five");
foo.setBean(new Bean());
foo.getBean().setId(3);
session.update(foo, proxy.getBean().getId());
session.load(fooBD = new Foo(1));
Assert.assertEquals("Test five", fooBD.getTest());
Assert.assertEquals(3, fooBD.getBean().getId());
foo = new Foo(1);
//forcing bean to null
session.update(foo, proxy.getBean().getId());
session.load(fooBD = new Foo(1));
Assert.assertNull(fooBD.getBean());
Assert.assertNotNull(fooBD.getBar().getItem().getSubItem().getName());
foo = new Foo(1);
session.update(foo, proxy.getBean().getId(), proxy.getBar().getItem().getSubItem().getName());
session.load(fooBD = new Foo(1));
Assert.assertNull(fooBD.getBean());
Assert.assertNull(fooBD.getBar());
foo = createEmptyFoo();
foo.setId(1);
foo.getBar().getItem().getSubItem().setName("Not null");
session.update(foo, proxy.getBar().getItem().getSubItem().getName());
session.load(fooBD = new Foo(1));
Assert.assertNull(fooBD.getBean());
Assert.assertEquals("Not null", fooBD.getBar().getItem().getSubItem().getName());
foo = createEmptyFoo();
foo.setId(1);
session.update(foo, proxy.getBar().getItem().getSubItem().getName());
session.load(fooBD = new Foo(1));
Assert.assertNull(fooBD.getBar());
/*
* testing using attached update
*/
foo = createEmptyFoo();
foo.setId(5);
foo.setTest("Attached test");
foo.setBean(new Bean());
foo.getBean().setId(5);
foo.getBar().getItem().getSubItem().setName("Anything");
session.insert(foo);
fooBD = new Foo(foo.getId());
session.load(fooBD);
fooBD.setTest("Attached test - updated");
session.update(fooBD);
session.load(fooBD);
Assert.assertEquals("Attached test - updated", fooBD.getTest());
Assert.assertNotNull(fooBD.getBean());
Assert.assertNotNull(fooBD.getBar());
} catch (Exception e) {
throw new BeanException(e);
} finally {
close(conn);
}
}
private BeanManager getNullFKsManager() {
BeanManager manager = new BeanManager();
 
Foo fooPxy = PropertiesProxy.create(Foo.class);
BeanConfig fooConfig = new BeanConfig(Foo.class, "foo")
.pk(fooPxy.getId(), "idfoo", DBTypes.LONG)
.field(fooPxy.getBean().getId(), "idbean", DBTypes.LONG)
.field(fooPxy.getTest(), DBTypes.STRING);
manager.addBeanConfig(fooConfig);
 
Bean barPxy = PropertiesProxy.create(Bean.class);
BeanConfig beanConfig = new BeanConfig(Bean.class, "bean")
.pk(barPxy.getId(), DBTypes.LONG);
manager.addBeanConfig(beanConfig);
 
return manager;
}
@Test
public void testNullFKs() {
Connection conn = null;
BeanManager beanManager = getNullFKsManager();
try {
 
conn = getConnection();
BeanSession session = new H2BeanSession(beanManager, conn);
session.createTables();
SQLUtils.prepare(conn, "alter table foo add foreign key(idbean) references bean");
Bean bean = new Bean(1);
session.insert(bean);
Foo foo = new Foo(1, "Foo UM", bean);
session.insert(foo);
foo = new Foo(2, "Foo DOIS", null);
session.insert(foo);
Foo fooBD = new Foo(2);
session.load(fooBD);
Assert.assertNull(fooBD.getBean());
fooBD.setTest("Foo DOIS - updated");
session.update(fooBD);
session.load(fooBD = new Foo(2));
Assert.assertEquals("Foo DOIS - updated", fooBD.getTest());
Assert.assertNull(fooBD.getBean());
fooBD = new Foo(1);
session.load(fooBD);
Assert.assertNotNull(fooBD.getBean());
Assert.assertEquals(1, fooBD.getBean().getId());
fooBD.setTest(null);
session.update(fooBD);
session.load(fooBD = new Foo(1));
Assert.assertNull(fooBD.getTest());
fooBD.setBean(null);
fooBD.setTest("Foo UM");
session.update(fooBD);
session.load(fooBD = new Foo(1));
Assert.assertEquals("Foo UM", fooBD.getTest());
Assert.assertNull(fooBD.getBean());
fooBD.setTest("Foo UM - alterado");
session.update(fooBD);
session.load(fooBD = new Foo(1));
Assert.assertEquals("Foo UM - alterado", fooBD.getTest());
Assert.assertNull(fooBD.getBean());
} catch (Exception e) {
throw new BeanException(e);
} finally {
close(conn);
}
}
 
}
/tags/menta-bean-2.2.2/src/test/java/org/mentabean/jdbc/RecursivePropertiesTest.java
New file
0,0 → 1,1026
package org.mentabean.jdbc;
 
import static org.mentabean.jdbc.AnsiSQLBeanSession.DEBUG;
import static org.mentabean.util.SQLUtils.lim;
import static org.mentabean.util.SQLUtils.orderByAsc;
 
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
 
import junit.framework.Assert;
 
import org.junit.BeforeClass;
import org.junit.Test;
import org.mentabean.BeanConfig;
import org.mentabean.BeanManager;
import org.mentabean.BeanSession;
import org.mentabean.DBTypes;
import org.mentabean.jdbc.QueryBuilder.Alias;
import org.mentabean.jdbc.QueryBuilder.Query;
import org.mentabean.sql.conditions.GreaterThan;
import org.mentabean.sql.conditions.Like;
import org.mentabean.sql.functions.Coalesce;
import org.mentabean.sql.functions.Lower;
import org.mentabean.sql.param.ParamField;
import org.mentabean.sql.param.ParamFunction;
import org.mentabean.sql.param.ParamValue;
import org.mentabean.util.PropertiesProxy;
import org.mentabean.util.SQLUtils;
 
public class RecursivePropertiesTest extends AbstractBeanSessionTest {
public static class Post {
private int id;
private String title;
private User user;
public Post() {
}
public Post(int id) {
this.id = id;
}
public Post(String title, User user) {
this.title = title;
this.user = user;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
public static class User {
private int id;
private String username;
private Address address;
public User() {
}
public User(int id) {
this.id = id;
}
public User(String username, Address addr) {
this.username = username;
this.address = addr;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
public static class Address {
private int id;
private City city;
public Address() {
}
public Address(int id) {
this.id = id;
}
public Address(City city) {
this.city = city;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public City getCity() {
return city;
}
public void setCity(City city) {
this.city = city;
}
}
public static class City {
private int id;
private String name;
public City() {
}
public City(int id) {
this.id = id;
}
public City(int id, String name) {
this.id = id;
this.name = name;
}
public City(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@BeforeClass
public static void setup() {
DEBUG = false; // turn on to see SQL generated
}
private BeanManager getBeanManager1() {
 
// programmatic configuration for the bean... (no annotation or XML)
BeanManager beanManager = new BeanManager();
 
BeanConfig postConfig = new BeanConfig(Post.class, "Posts");
postConfig.pk("id", DBTypes.AUTOINCREMENT);
postConfig.field("title", DBTypes.STRING);
postConfig.field("user.id", "user_id", DBTypes.INTEGER); // note that the database column name is different
beanManager.addBeanConfig(postConfig);
BeanConfig userConfig = new BeanConfig(User.class, "Users");
userConfig.pk("id", DBTypes.AUTOINCREMENT);
userConfig.field("username", DBTypes.STRING);
userConfig.field("address.id", "address_id", DBTypes.INTEGER);
beanManager.addBeanConfig(userConfig);
BeanConfig addressConfig = new BeanConfig(Address.class, "Addresses");
addressConfig.pk("id", DBTypes.AUTOINCREMENT);
addressConfig.field("city.id", "city_id", DBTypes.INTEGER);
beanManager.addBeanConfig(addressConfig);
BeanConfig cityConfig = new BeanConfig(City.class, "Cities");
cityConfig.pk("id", DBTypes.INTEGER);
cityConfig.field("name", DBTypes.STRING);
beanManager.addBeanConfig(cityConfig);
return beanManager;
}
@Test
public void testTwoLevels() throws SQLException {
BeanManager beanManager = getBeanManager1();
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rset = null;
 
try {
 
conn = getConnection();
// createTables1(conn);
BeanSession session = new H2BeanSession(beanManager, conn);
session.createTables();
// first insert...
City rj = new City(1, "Rio de Janeiro");
City chi = new City(2, "Chicago");
session.insert(rj);
session.insert(chi);
Address addr1 = new Address(rj);
Address addr2 = new Address(chi);
session.insert(addr1);
session.insert(addr2);
User user1 = new User("saoj", addr1);
User user2 = new User("julia", addr2);
session.insert(user1);
session.insert(user2);
Post post1 = new Post("Title1", user1);
session.insert(post1);
// now load and test;
City c1 = new City(1);
session.load(c1);
Assert.assertEquals(c1.getId(), rj.getId());
Assert.assertEquals(c1.getName(), rj.getName());
 
Address a1 = new Address(1);
session.load(a1);
Assert.assertEquals(a1.getId(), addr1.getId());
Assert.assertEquals(a1.getCity().getId(), addr1.getCity().getId());
User u1 = new User(1);
session.load(u1);
Assert.assertEquals(u1.getId(), user1.getId());
Assert.assertEquals(u1.getUsername(), user1.getUsername());
Assert.assertEquals(u1.getAddress().getId(), user1.getAddress().getId());
// now above the second level will be null due to lazy loading:
Assert.assertEquals(u1.getAddress().getCity(), null);
// let's test this again:
Post p1 = new Post(1);
session.load(p1);
Assert.assertEquals(p1.getId(), post1.getId());
Assert.assertEquals(p1.getUser().getId(), post1.getUser().getId());
// but the only thing the user object has is the ID... everything else is null (lazy loading)
Assert.assertEquals(p1.getUser().getUsername(), null);
// when you need the user of the post, you can manually load it:
session.load(p1.getUser()); // manual lazy loading!
Assert.assertEquals(p1.getUser().getUsername(), post1.getUser().getUsername());
// now update!
// change the user of post1
post1.setUser(user2);
session.update(post1);
Post updatedPost = new Post(1);
session.load(updatedPost);
Assert.assertEquals(post1.getId(), updatedPost.getId());
Assert.assertEquals(post1.getTitle(), updatedPost.getTitle());
Assert.assertEquals(post1.getUser().getId(), updatedPost.getUser().getId());
// load list:
Post post2 = new Post("Title2", user1);
session.insert(post2);
Post post3 = new Post("Title3", user2);
session.insert(post3);
// we should have two posts for user2 now: (remember the first one was updated to user2)
Post p = new Post();
p.setUser(user2);
List<Post> posts = session.loadList(p);
Assert.assertEquals(posts.size(), 2);
int beansDeleted = session.deleteAll(p);
Assert.assertEquals(2, beansDeleted);
p.setUser(user1);
posts = session.loadList(p);
Assert.assertEquals(posts.size(), 1);
beansDeleted = session.deleteAll(p);
Assert.assertEquals(1, beansDeleted);
} finally {
close(stmt, rset);
close(conn);
}
}
private BeanManager getBeanManager2() {
 
// programmatic configuration for the bean... (no annotation or XML)
BeanManager beanManager = new BeanManager();
Post postProps = PropertiesProxy.create(Post.class);
 
BeanConfig postConfig = new BeanConfig(Post.class, "Posts");
postConfig.pk(postProps.getId(), DBTypes.AUTOINCREMENT);
postConfig.field(postProps.getTitle(), DBTypes.STRING);
postConfig.field(postProps.getUser().getId(), "user_id", DBTypes.INTEGER); // note that the database column name is different
postConfig.field(postProps.getUser().getAddress().getId(), "address_id", DBTypes.INTEGER);
beanManager.addBeanConfig(postConfig);
User userProps = PropertiesProxy.create(User.class);
BeanConfig userConfig = new BeanConfig(User.class, "Users");
userConfig.pk(userProps.getId(), DBTypes.AUTOINCREMENT);
userConfig.field("username", DBTypes.STRING);
userConfig.field("address.id", "address_id", DBTypes.INTEGER);
beanManager.addBeanConfig(userConfig);
Address addressProps = PropertiesProxy.create(Address.class);
BeanConfig addressConfig = new BeanConfig(Address.class, "Addresses");
addressConfig.pk("id", DBTypes.AUTOINCREMENT);
addressConfig.field(addressProps.getCity().getId(), "city_id", DBTypes.INTEGER);
beanManager.addBeanConfig(addressConfig);
BeanConfig cityConfig = new BeanConfig(City.class, "Cities");
cityConfig.pk("id", DBTypes.INTEGER);
cityConfig.field("name", DBTypes.STRING);
beanManager.addBeanConfig(cityConfig);
return beanManager;
}
@Test
public void testThreeLevels() throws SQLException {
BeanManager beanManager = getBeanManager2();
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rset = null;
 
try {
 
conn = getConnection();
// createTables2(conn);
BeanSession session = new H2BeanSession(beanManager, conn);
session.createTables();
 
// first insert...
City rj = new City(1, "Rio de Janeiro");
City chi = new City(2, "Chicago");
session.insert(rj);
session.insert(chi);
Address addr1 = new Address(rj);
Address addr2 = new Address(chi);
session.insert(addr1);
session.insert(addr2);
User user1 = new User("saoj", addr1);
User user2 = new User("julia", addr2);
session.insert(user1);
session.insert(user2);
Post post1 = new Post("Title1", user1);
session.insert(post1);
// now load and test;
Post p1 = new Post(1);
session.load(p1);
// check if we have the address id
Assert.assertEquals(p1.getUser().getAddress().getId(), post1.getUser().getAddress().getId());
// and everything from user and from address must be NULL except the ids (remember the Posts also have user_id, so the id of the user will NOT be null)
Assert.assertEquals(p1.getUser().getId(), post1.getUser().getId());
Assert.assertEquals(p1.getUser().getUsername(), null);
Assert.assertEquals(p1.getUser().getAddress().getCity(), null);
// change the address of the post (i.e. of its user)
p1.getUser().setAddress(addr2);
session.update(p1);
Post updatedPost = new Post(1);
session.load(updatedPost);
Assert.assertEquals(updatedPost.getUser().getAddress().getId(), addr2.getId());
// NOTE: This will create an inconsistency in the database because we did NOT update the user, only the address_id in the Post table...
// the correct way of doing it:
session.load(p1.getUser());
Assert.assertEquals(p1.getUser().getAddress().getId(), addr1.getId()); // still address 1 because we never updated user...
// now update:
p1.getUser().setAddress(addr2);
session.update(p1.getUser());
// now just call update on the post and its address_id will be updated correctly:
session.update(p1);
Post p = new Post(1);
session.load(p);
Assert.assertEquals(p.getUser().getAddress().getId(), addr2.getId());
// and now the user is also correct:
User u = new User(1);
session.load(u);
Assert.assertEquals(u.getAddress().getId(), addr2.getId());
Assert.assertEquals(1, session.deleteAll(new Post()));
Assert.assertEquals(2, session.deleteAll(new User()));
Assert.assertEquals(2, session.deleteAll(new Address()));
Assert.assertEquals(2, session.deleteAll(new City()));
} finally {
close(stmt, rset);
close(conn);
}
}
@Test
public void testAnotherOperations() throws SQLException {
 
final Connection conn = getConnection();
try {
BeanSession beanSession = new H2BeanSession(getBeanManager1(), conn);
beanSession.createTables();
 
//let's play
City c1 = new City(1, "Santa Rosa");
Address a1 = new Address(c1);
User u1 = new User("erico", a1);
User u2 = new User("jessica", a1);
 
beanSession.insert(c1);
beanSession.insert(a1);
beanSession.insert(u1);
beanSession.insert(u2);
 
//simple check
City c1DB = new City(c1.getId());
beanSession.load(c1DB);
Assert.assertEquals(c1.getName(), c1DB.getName());
 
User u1DB = new User(u1.getId());
beanSession.load(u1DB);
Assert.assertEquals(u1.getId(), u1DB.getId());
Assert.assertEquals(u1.getAddress().getId(), u1DB.getAddress().getId());
 
beanSession.insert(u2);
 
//retrieving all users in base WITHOUT address
List<User> list = beanSession.loadListMinus(new User(), orderByAsc("username"), "address.id");
for (User userDB : list) {
Assert.assertEquals(null, userDB.getAddress());
}
User userProps = PropertiesProxy.create(User.class);
list = beanSession.loadListMinus(new User(), orderByAsc("username"), userProps.getAddress().getId());
for (User userDB : list) {
Assert.assertEquals(null, userDB.getAddress());
}
 
//another way to get the list above
list = beanSession.loadList(new User(), orderByAsc("username"), "id", "username");
for (User userDB : list) {
Assert.assertNull(userDB.getAddress());
Assert.assertNotNull(userDB.getId());
Assert.assertNotNull(userDB.getUsername());
}
// test proxy for list of properties
list = beanSession.loadList(new User(), orderByAsc("username"), userProps.getId(), userProps.getUsername());
for (User userDB : list) {
Assert.assertNull(userDB.getAddress());
Assert.assertNotNull(userDB.getId());
Assert.assertNotNull(userDB.getUsername());
}
list = beanSession.loadList(new User(), orderByAsc("username"), userProps.getId() );
for (User userDB : list) {
Assert.assertNull(userDB.getAddress());
Assert.assertNotNull(userDB.getId());
Assert.assertNull(userDB.getUsername());
}
list = beanSession.loadList(new User(), orderByAsc(userProps.getUsername()), userProps.getId());
for (User userDB : list) {
Assert.assertNull(userDB.getAddress());
Assert.assertNotNull(userDB.getId());
Assert.assertNull(userDB.getUsername());
}
list = beanSession.loadList(new User(), orderByAsc(userProps.getUsername()), lim(1), userProps.getId());
Assert.assertEquals(1, list.size());
Assert.assertEquals(2, beanSession.deleteAll(new User("jessica", null)));
list = beanSession.loadList(new User());
Assert.assertEquals(1, list.size());
Assert.assertNotNull(list.get(0).getAddress());
Assert.assertNotNull(list.get(0).getId());
Assert.assertEquals("erico", list.get(0).getUsername());
}finally {
close(conn);
}
}
/*
* Another situation
*/
public static class Customer {
private int code;
private String name;
private Boolean active;
public Customer() {
}
public Customer(int code, String name, Boolean active) {
this.code = code;
this.name = name;
this.active = active;
}
public Customer(int code) {
this.code = code;
}
public Customer(String name, Boolean active) {
this.name = name;
this.active = active;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Boolean getActive() {
return active;
}
public void setActive(Boolean active) {
this.active = active;
}
}
public static class Sale {
private long id;
private Customer customer;
private List<Item> items = new ArrayList<Item>();
public Sale() {}
public Sale(Customer customer) {
this.customer = customer;
}
public Sale(long id) {
this.id = id;
}
public Sale(Customer customer, List<Item> items) {
this.customer = customer;
this.items = items;
}
public Sale(long id, Customer customer, List<Item> items) {
this.id = id;
this.customer = customer;
this.items = items;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
public BigDecimal getTotalPrice() {
BigDecimal totalPrice = BigDecimal.ZERO;
for (Item item : items)
totalPrice = totalPrice.add(item.getTotalPrice());
return totalPrice;
}
public List<Item> getItems() {
return items;
}
public void setItems(List<Item> items) {
this.items = items;
}
public void addItem(Item item) {
item.setSale(this);
this.items.add(item);
}
 
@Override
public boolean equals(Object obj) {
if (obj instanceof Sale)
return ((Sale)obj).id == id;
return false;
}
@Override
public int hashCode() {
return (int) id;
}
}
public static class Item {
private Sale sale;
private Product product;
private BigDecimal amount;
private Double actualPrice;
public Item() {}
public Item(Sale sale, Product product, BigDecimal amount,
Double actualPrice) {
this.actualPrice = actualPrice;
this.sale = sale;
this.product = product;
this.amount = amount;
}
public Item(Sale sale, Product product, BigDecimal amount) {
this.sale = sale;
this.product = product;
this.amount = amount;
this.actualPrice = product.getPrice();
}
public Item(Product product, BigDecimal amount) {
this.product = product;
this.amount = amount;
this.actualPrice = product.getPrice();
}
public Item(Sale sale, Product product) {
this.product = product;
this.sale = sale;
this.actualPrice = product.getPrice();
}
public Item(Sale sale) {
this.sale = sale;
}
public Sale getSale() {
return sale;
}
public void setSale(Sale sale) {
this.sale = sale;
}
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
public BigDecimal getAmount() {
return amount;
}
public void setAmount(BigDecimal amount) {
this.amount = amount;
}
public Double getActualPrice() {
return actualPrice;
}
public void setActualPrice(Double actualPrice) {
this.actualPrice = actualPrice;
}
public BigDecimal getTotalPrice() {
if (actualPrice <=0)
throw new IllegalArgumentException("Invalid price");
if (amount.signum() <= 0)
throw new IllegalArgumentException("Invalid amount");
return BigDecimal.valueOf(actualPrice).multiply(amount);
}
}
public static class Product {
private int id;
private String description;
private double price;
public Product() {}
public Product(String description, double price) {
this.description = description;
this.price = price;
}
public Product(int id, String description, double price) {
this.id = id;
this.description = description;
this.price = price;
}
public Product(int id) {
this.id = id;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Product)
return ((Product)obj).id == id;
return false;
}
@Override
public int hashCode() {
return (int) id;
}
}
//fluent mode
private BeanManager getBeanManagerCustomer() {
 
// programmatic configuration for the bean... (no annotation or XML)
BeanManager beanManager = new BeanManager();
 
// BeanConfig customerConfig = new BeanConfig(Customer.class, "customers")
// .pk("code", "idcustomers", DBTypes.AUTOINCREMENT)
// .field("name", DBTypes.STRING);
//
// BeanConfig saleConfig = new BeanConfig(Sale.class, "sales")
// .pk("id", "idsales", DBTypes.AUTOINCREMENT)
// .field("customer.code", "idcustomers", DBTypes.INTEGER);
//
// BeanConfig itemConfig = new BeanConfig(Item.class, "items")
//
// // the "sale.id" is a reference for field "id" in object "sale"
// .pk("sale.id", "idsales", DBTypes.LONG)
//
// // same as above, the "product.id" is a reference for field "id" in object "product"
// // note that it's a composite primary key with no sequence or autoincrement field
// .pk("product.id", "idproducts", DBTypes.INTEGER)
//
// .field("amount", "amount_db", DBTypes.DOUBLE)
// .field("actualPrice", "actual_price_db", DBTypes.DOUBLE);
//
// BeanConfig productConfig = new BeanConfig(Product.class, "products")
// .pk("id", "idproducts", DBTypes.AUTOINCREMENT)
// .field("description", DBTypes.STRING)
// .field("price", DBTypes.DOUBLE);
Customer customerProxy = PropertiesProxy.create(Customer.class);
BeanConfig customerConfig = new BeanConfig(Customer.class, "customers")
.pk(customerProxy.getCode(), "idcustomers", DBTypes.AUTOINCREMENT)
.field(customerProxy.getName(), DBTypes.STRING.size(-1))
.field(customerProxy.getActive(), DBTypes.BOOLEAN);
Sale saleProxy = PropertiesProxy.create(Sale.class);
BeanConfig saleConfig = new BeanConfig(Sale.class, "sales")
.pk(saleProxy.getId(), "idsales", DBTypes.AUTOINCREMENT)
.field(saleProxy.getCustomer().getCode(), "idcustomers", DBTypes.INTEGER);
Item itemProxy = PropertiesProxy.create(Item.class);
BeanConfig itemConfig = new BeanConfig(Item.class, "items")
// the "sale.id" is a reference for field "id" in object "sale"
.pk(itemProxy.getSale().getId(), "idsales", DBTypes.LONG)
// same as above, the "product.id" is a reference for field "id" in object "product"
// note that it's a composite primary key with no sequence or autoincrement field
.pk(itemProxy.getProduct().getId(), "idproducts", DBTypes.INTEGER)
.field(itemProxy.getAmount(), "amount_db", DBTypes.BIGDECIMAL)
.field(itemProxy.getActualPrice(), "actual_price_db", DBTypes.DOUBLE);
Product productProxy = PropertiesProxy.create(Product.class);
BeanConfig productConfig = new BeanConfig(Product.class, "products")
.pk(productProxy.getId(), "idproducts", DBTypes.AUTOINCREMENT)
.field(productProxy.getDescription(), DBTypes.STRING.size(-1))
.field(productProxy.getPrice(), DBTypes.DOUBLE);
 
//add configurations in beanManager
beanManager.addBeanConfig(customerConfig);
beanManager.addBeanConfig(saleConfig);
beanManager.addBeanConfig(itemConfig);
beanManager.addBeanConfig(productConfig);
return beanManager;
}
@Test
public void testCustomer() {
 
final Connection conn = getConnection();
PreparedStatement stmt = null;
try {
AnsiSQLBeanSession session = new H2BeanSession(getBeanManagerCustomer(), conn);
session.createTables();
 
//let's play...
Customer c1 = new Customer("Erico", true);
Customer c2 = new Customer("Jessica", true);
Customer c3 = new Customer("Inactive customer", false);
session.insert(c1);
session.insert(c2);
session.insert(c3);
Customer c3DB = new Customer(c3.getCode());
session.load(c3DB);
Assert.assertEquals(c3.getActive(), c3DB.getActive());
 
Product p1 = new Product("Bean", 5.50);
Product p2 = new Product("Rice", 4.32);
Product p3 = new Product("Bread", 0.15);
session.insert(p1);
session.insert(p2);
session.insert(p3);
 
Sale s1 = new Sale(c1);
 
// note that addItem method will set the respective sale in the given item
s1.addItem(new Item(p1, BigDecimal.valueOf(1.0)));
s1.addItem(new Item(p2, BigDecimal.valueOf(3)));
s1.addItem(new Item(p3, BigDecimal.valueOf(0.175)));
 
// we don't want magic here, so we have to insert the sale and the items separately
session.insert(s1);
for (Item item : s1.getItems())
session.insert(item);
 
//retrieving the stored sale
Sale s1DB = new Sale(s1.getId());
session.load(s1DB);
// note that the s1DB sale has a costumer ONLY with code
Assert.assertEquals(s1.getCustomer().getCode(), s1DB.getCustomer().getCode());
// loading the customer
session.load(s1DB.getCustomer());
// now we have a sale with the full customer
Assert.assertEquals(s1.getCustomer().getName(), s1DB.getCustomer().getName());
 
// again, we have to load sale and items if we want to retrieve both of them
Item itemProto = new Item(s1DB);
Item itemProxy = PropertiesProxy.create(Item.class);
s1DB.setItems(session.loadList(itemProto, orderByAsc(itemProxy.getProduct().getId()))); //ordering by idproducts
 
// let's check
Assert.assertEquals(s1.getId(), s1DB.getId());
for (int i=0; i<s1.getItems().size(); i++) {
// we're comparing the items in index order, so the s1 and s1DB's items order need to be equals
Assert.assertEquals(s1.getItems().get(i).getActualPrice(), s1DB.getItems().get(i).getActualPrice());
Assert.assertEquals(s1.getItems().get(i).getAmount().doubleValue(), s1DB.getItems().get(i).getAmount().doubleValue());
}
// updating the sale's customer
s1DB.setCustomer(c2);
session.update(s1DB);
Sale updatedSale = new Sale(s1DB.getId());
session.load(updatedSale);
Assert.assertEquals(c2.getCode(), updatedSale.getCustomer().getCode());
// let's do a more specific query
// loading sales and customers with one query
// first we'll insert a sale WITHOUT a customer
Sale s2 = new Sale();
session.insert(s2);
Sale s2DB = new Sale(s2.getId());
session.load(s2DB);
//we don't have a customer
Assert.assertNull(s2DB.getCustomer());
List<Sale> sales = new ArrayList<Sale>();
// Manual query using QueryBuilder
QueryBuilder builder = session.buildQuery();
// set the Alias just once
Alias<Sale> s = builder.aliasTo(Sale.class, "s");
Alias<Customer> c = builder.aliasTo(Customer.class, "c");
// returns (will be removed from buildSelect and populateBean)
c.setReturnMinus(c.pxy().getActive());
Query query = builder.select(s, c)
.from(s)
.leftJoin(c).pkOf(c).in(s)
.where().clause(s.pxy().getId()).condition(new GreaterThan(new ParamValue(0))).and()
.clause(new Coalesce()
.addParam(new ParamField(s, s.pxy().getId()))
.addParam(new ParamValue(0)))
.condition(new GreaterThan(new ParamValue(0))).and()
.clause(new Coalesce()
.addParam(new ParamFunction(new Lower(new ParamField(c, c.pxy().getName()))))
.addParam(new ParamValue("i")))
.condition(new Like(new ParamValue("%i%")))
.orderBy().asc(s, s.pxy().getId())
.desc(s, s.pxy().getCustomer().getCode())
.limit(2).offset(0);
stmt = query.prepare();
ResultSet rs = stmt.executeQuery();
Sale saleObj = null;
while (rs.next()) {
saleObj = new Sale();
s.populateBean(rs, saleObj);
if (saleObj.getCustomer() != null) { // left join might not return any customer...
c.populateBean(rs, saleObj.getCustomer());
}
sales.add(saleObj);
}
Assert.assertNotNull(sales.get(0).getCustomer());
Assert.assertNull(sales.get(1).getCustomer());
// update or insert
int result = -1;
// must be updated
saleObj.setCustomer(c1);
result = session.save(saleObj);
Assert.assertEquals(BeanSession.UPDATE, result);
//must be inserted
saleObj.setId(0);
result = session.save(saleObj);
Assert.assertEquals(BeanSession.INSERT, result);
} catch (Exception e) {
throw new RuntimeException(e);
}finally {
SQLUtils.close(stmt, conn);
}
}
}
/tags/menta-bean-2.2.2/src/test/java/org/mentabean/jdbc/UpdateDiffTest.java
New file
0,0 → 1,419
package org.mentabean.jdbc;
 
import static org.junit.Assert.*;
 
import java.sql.Connection;
import java.util.LinkedList;
import java.util.List;
 
import junit.framework.Assert;
 
import org.junit.Test;
import org.mentabean.BeanConfig;
import org.mentabean.BeanManager;
import org.mentabean.BeanSession;
import org.mentabean.DBTypes;
import org.mentabean.util.PropertiesProxy;
import org.mentabean.util.SQLUtils;
 
public class UpdateDiffTest extends AbstractBeanSessionTest {
 
static class User implements Cloneable {
 
private int id;
private String name;
private Integer age;
private boolean active;
private Group group;
 
public User() {}
 
public User(int id) {
this.id = id;
}
 
public User(String name, Integer age, boolean active, Group group) {
super();
this.name = name;
this.age = age;
this.group = group;
}
 
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Group getGroup() {
return group;
}
public void setGroup(Group group) {
this.group = group;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
 
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
 
static class Group implements Cloneable {
 
private int id;
private String name;
 
public Group(String name) {
this.name = name;
}
 
public Group(int id) {
this.id = id;;
}
public Group(int id, String name) {
this.id = id;;
this.name = name;
}
 
public Group() {}
 
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Group) {
return id == ((Group) obj).id;
}
return false;
}
@Override
public int hashCode() {
return id;
}
 
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
static class TypeTest {
private long id;
private int intPrimitive;
private double doublePrimitive;
private Double doubleWrapper;
private Integer intWrapper;
private String string;
private Group group;
public long getId() {
return id;
}
public TypeTest setId(long id) {
this.id = id;
return this;
}
public int getIntPrimitive() {
return intPrimitive;
}
public TypeTest setIntPrimitive(int intPrimitive) {
this.intPrimitive = intPrimitive;
return this;
}
public double getDoublePrimitive() {
return doublePrimitive;
}
public TypeTest setDoublePrimitive(double doublePrimitive) {
this.doublePrimitive = doublePrimitive;
return this;
}
public Double getDoubleWrapper() {
return doubleWrapper;
}
public TypeTest setDoubleWrapper(Double doubleWrapper) {
this.doubleWrapper = doubleWrapper;
return this;
}
public Integer getIntWrapper() {
return intWrapper;
}
public TypeTest setIntWrapper(Integer intWrapper) {
this.intWrapper = intWrapper;
return this;
}
public String getString() {
return string;
}
public TypeTest setString(String string) {
this.string = string;
return this;
}
public Group getGroup() {
return group;
}
public TypeTest setGroup(Group group) {
this.group = group;
return this;
}
}
 
private BeanManager configureManager1() {
 
BeanManager manager = new BeanManager();
 
User userProxy = PropertiesProxy.create(User.class);
BeanConfig userCfg = new BeanConfig(User.class, "users")
.pk(userProxy.getId(), DBTypes.AUTOINCREMENT)
.field(userProxy.getGroup().getId(), "idgroups", DBTypes.INTEGER)
.field(userProxy.getName(), DBTypes.STRING.size(0))
.field(userProxy.getAge(), DBTypes.INTEGER)
.field(userProxy.isActive(), DBTypes.BOOLEAN);
manager.addBeanConfig(userCfg);
 
Group groupProxy = PropertiesProxy.create(Group.class);
BeanConfig groupCfg = new BeanConfig(Group.class, "groups")
.pk(groupProxy.getId(), DBTypes.AUTOINCREMENT)
.field(groupProxy.getName(), DBTypes.STRING.size(0));
manager.addBeanConfig(groupCfg);
 
return manager;
}
private BeanManager configureManager2() {
BeanManager manager = new BeanManager();
TypeTest t = PropertiesProxy.create(TypeTest.class);
BeanConfig conf = new BeanConfig(TypeTest.class, "test")
.pk(t.getId(), DBTypes.AUTOINCREMENT)
.field(t.getIntPrimitive(), DBTypes.INTEGER)
.field(t.getIntWrapper(), DBTypes.INTEGER)
.field(t.getDoublePrimitive(), DBTypes.DOUBLE)
.field(t.getDoubleWrapper(), DBTypes.DOUBLE)
.field(t.getGroup().getId(), "idgroups", DBTypes.INTEGER)
.field(t.getString(), DBTypes.STRING);
manager.addBeanConfig(conf);
return manager;
}
 
@Test
public void test() throws Exception {
 
Connection conn = getConnection();
try {
BeanSession session = new H2BeanSession(configureManager1(), conn);
session.createTables();
 
Group g1 = new Group("Common");
Group g2 = new Group("Super");
Group g3 = new Group("Admin");
session.insert(g1);
session.insert(g2);
session.insert(g3);
 
User u1 = new User("John", 40, true, g1);
User u2 = new User("Ralph", 30, false, g2);
User u3 = new User("Matt", 20, true, g3);
session.insert(u1);
session.insert(u2);
session.insert(u3);
 
User ralph = new User(2);
session.load(ralph);
assertEquals("Ralph", ralph.getName());
 
User clone = (User) ralph.clone();
assertNotNull(clone.getGroup());
assertEquals(2, clone.getGroup().getId());
 
int updated = session.updateDiff(clone, ralph);
assertEquals(0, updated);
 
clone.setGroup(null);
updated = session.updateDiff(clone, ralph);
assertEquals(1, updated);
clone = session.createBasicInstance(clone);
session.load(clone);
assertNull(clone.getGroup());
assertEquals("Ralph", clone.getName());
assertFalse(clone.isActive());
 
User old = (User) clone.clone();
clone.setGroup(g3);
updated = session.updateDiff(clone, old);
assertEquals(1, updated);
clone = session.createBasicInstance(clone);
session.load(clone);
assertNotNull(clone.getGroup());
assertEquals("Ralph", clone.getName());
 
old = (User) clone.clone();
clone.setGroup(new Group());
clone.setAge(0);
clone.setActive(true);
updated = session.updateDiff(clone, old);
assertEquals(1, updated);
clone = session.createBasicInstance(clone);
session.load(clone);
assertNull(clone.getGroup());
assertEquals(new Integer(0), clone.getAge());
assertTrue(clone.isActive());
 
old = (User) clone.clone();
clone.setAge(null);
updated = session.updateDiff(clone, old);
assertEquals(1, updated);
clone = session.loadUnique(clone);
assertNull(clone.getAge());
 
old = (User) clone.clone();
clone.setAge(10);
clone.setActive(false);
updated = session.updateDiff(clone, old);
assertEquals(1, updated);
clone = session.createBasicInstance(clone);
session.load(clone);
assertEquals(new Integer(10), clone.getAge());
assertFalse(clone.isActive());
 
} finally {
SQLUtils.close(conn);
}
}
@Test
public void testDifferences() throws Exception {
 
Connection conn = getConnection();
 
try {
 
BeanSession session = new H2BeanSession(configureManager2(), conn);
session.createTables();
 
Group g1 = new Group(1, "Group one");
Group g2 = new Group(2, "Group two");
TypeTest newObj = new TypeTest()
.setDoublePrimitive(0.6)
.setDoubleWrapper(0.6)
.setIntPrimitive(1)
.setIntWrapper(1)
.setGroup(g1)
.setString("Test one");
TypeTest oldObj = new TypeTest()
.setDoublePrimitive(0.7)
.setDoubleWrapper(0.6)
.setIntPrimitive(1)
.setIntWrapper(1)
.setGroup(g1)
.setString("Test one");
List<String> diffs = new LinkedList<String>();
TypeTest diff = session.compareDifferences(newObj, oldObj, diffs);
Assert.assertNotNull(diff);
Assert.assertEquals(diff.getDoublePrimitive(), newObj.getDoublePrimitive());
Assert.assertEquals(0, diffs.size());
diffs.clear();
oldObj.setDoublePrimitive(0.6);
diff = session.compareDifferences(newObj, oldObj, diffs);
Assert.assertNull(diff);
Assert.assertEquals(0, diffs.size());
 
diffs.clear();
newObj.setGroup(g2);
diff = session.compareDifferences(newObj, oldObj, diffs);
Assert.assertNotNull(diff);
Assert.assertEquals(0, diffs.size());
Assert.assertEquals(g2, diff.getGroup());
diffs.clear();
newObj.setGroup(null);
diff = session.compareDifferences(newObj, oldObj, diffs);
Assert.assertEquals(1, diffs.size());
Assert.assertEquals("group.id", diffs.get(0));
diffs.clear();
newObj.setGroup(g2);
newObj.setDoublePrimitive(0);
newObj.setString(null);
diff = session.compareDifferences(newObj, oldObj, diffs);
Assert.assertEquals(g2, diff.getGroup());
Assert.assertEquals(2, diffs.size());
Assert.assertEquals("doublePrimitive", diffs.get(0));
Assert.assertEquals("string", diffs.get(1));
diffs.clear();
newObj.setGroup(oldObj.getGroup());
newObj.setDoublePrimitive(0.000000001d);
oldObj.setDoublePrimitive(0.000000001d);
newObj.setString(oldObj.getString());
diff = session.compareDifferences(newObj, oldObj, diffs);
Assert.assertEquals(0, diffs.size());
Assert.assertNull(diff);
diffs.clear();
oldObj.setDoublePrimitive(0);
diff = session.compareDifferences(newObj, oldObj, diffs);
Assert.assertNotNull(diff);
Assert.assertEquals(newObj.getDoublePrimitive(), diff.getDoublePrimitive());
diffs.clear();
newObj.setDoublePrimitive(0);
oldObj.setDoublePrimitive(0);
diff = session.compareDifferences(newObj, oldObj, diffs);
Assert.assertNull(diff);
diffs.clear();
newObj.setIntPrimitive(0);
diff = session.compareDifferences(newObj, oldObj, diffs);
Assert.assertNotNull(diff);
Assert.assertEquals(0, diff.getIntPrimitive());
Assert.assertEquals(1, diffs.size());
Assert.assertEquals("intPrimitive", diffs.get(0));
 
} finally {
 
SQLUtils.close(conn);
}
}
 
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/test/java/org/mentabean/jdbc/QueryBuilderTest.java
New file
0,0 → 1,1622
package org.mentabean.jdbc;
 
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
 
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
 
import junit.framework.Assert;
 
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mentabean.BeanConfig;
import org.mentabean.BeanException;
import org.mentabean.BeanManager;
import org.mentabean.BeanSession;
import org.mentabean.DBTypes;
import org.mentabean.jdbc.QueryBuilder.Alias;
import org.mentabean.jdbc.QueryBuilder.Query;
import org.mentabean.sql.Sentence;
import org.mentabean.sql.conditions.Between;
import org.mentabean.sql.conditions.Equals;
import org.mentabean.sql.conditions.GreaterThan;
import org.mentabean.sql.conditions.In;
import org.mentabean.sql.conditions.LessThan;
import org.mentabean.sql.conditions.Like;
import org.mentabean.sql.conditions.NotEquals;
import org.mentabean.sql.conditions.NotIn;
import org.mentabean.sql.functions.Avg;
import org.mentabean.sql.functions.Count;
import org.mentabean.sql.functions.Length;
import org.mentabean.sql.functions.Lower;
import org.mentabean.sql.functions.Substring;
import org.mentabean.sql.functions.Upper;
import org.mentabean.sql.operations.Add;
import org.mentabean.sql.param.DefaultParamHandler;
import org.mentabean.sql.param.Param;
import org.mentabean.sql.param.ParamField;
import org.mentabean.sql.param.ParamFunction;
import org.mentabean.sql.param.ParamHandler;
import org.mentabean.sql.param.ParamSubQuery;
import org.mentabean.sql.param.ParamValue;
import org.mentabean.util.PropertiesProxy;
import org.mentabean.util.SQLUtils;
 
public class QueryBuilderTest extends AbstractBeanSessionTest {
 
public static class Country {
private String name;
 
public Country(String name) {
this.name = name;
}
public Country() {
}
public String getName() {
return name;
}
 
public void setName(String name) {
this.name = name;
}
}
public static class City {
private int code;
private String name;
private Country country;
public City(int code, String name, Country country) {
this.code = code;
this.name = name;
this.country = country;
}
public City() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
 
public int getCode() {
return code;
}
 
public void setCode(int code) {
this.code = code;
}
 
public Country getCountry() {
return country;
}
 
public void setCountry(Country country) {
this.country = country;
}
}
public static class Company {
private String id;
private String name;
private City city;
private int employeesCount;
public Company(String name) {
this.name = name;
}
public Company() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public City getCity() {
return city;
}
 
public void setCity(City city) {
this.city = city;
}
 
public int getEmployeesCount() {
return employeesCount;
}
 
public void setEmployeesCount(int employeesCount) {
this.employeesCount = employeesCount;
}
 
@Override
public String toString() {
return "Company [id=" + id + ", name=" + name + ", city=" + city
+ "]";
}
 
}
public static class Employee {
private long number;
private String name;
private double salary;
public Employee(long number, String name, double salary) {
this.number = number;
this.name = name;
this.salary = salary;
}
 
public Employee() {
}
public long getNumber() {
return number;
}
public void setNumber(long number) {
this.number = number;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
 
@Override
public String toString() {
return "\n"+number + " - " + name + " - " + salary;
}
}
public static class Post {
private Employee employee;
private Company company;
private String description;
public Post(Employee employee, Company company, String description) {
this.employee = employee;
this.company = company;
this.description = description;
}
public Post() {
}
public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
public Company getCompany() {
return company;
}
public void setCompany(Company company) {
this.company = company;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
 
@Override
public String toString() {
return "Post [employee=" + employee + ", company=" + company
+ ", description=" + description + "]";
}
}
private BeanManager configure() {
BeanManager manager = new BeanManager();
Company comPxy = PropertiesProxy.create(Company.class);
BeanConfig comConf = new BeanConfig(Company.class, "company")
.pk(comPxy.getId(), "idcompany", DBTypes.STRING)
.field(comPxy.getCity().getCode(), "c_code", DBTypes.INTEGER)
.field(comPxy.getName(), DBTypes.STRING);
manager.addBeanConfig(comConf);
Employee empPxy = PropertiesProxy.create(Employee.class);
BeanConfig employeeConf = new BeanConfig(Employee.class, "employee")
.pk(empPxy.getNumber(), "idemployee", DBTypes.LONG)
.field(empPxy.getName(), DBTypes.STRING)
.field(empPxy.getSalary(), DBTypes.DOUBLE);
manager.addBeanConfig(employeeConf);
Post postPxy = PropertiesProxy.create(Post.class);
BeanConfig postConf = new BeanConfig(Post.class, "post")
.pk(postPxy.getEmployee().getNumber(), "idemployee", DBTypes.LONG)
.pk(postPxy.getCompany().getId(), "idcompany", DBTypes.STRING)
.field(postPxy.getDescription(), DBTypes.STRING);
manager.addBeanConfig(postConf);
City cityPxy = PropertiesProxy.create(City.class);
BeanConfig cityConf = new BeanConfig(City.class, "cities")
.pk(cityPxy.getCode(), "city_code", DBTypes.INTEGER)
.field(cityPxy.getCountry().getName(), "country_name", DBTypes.STRING)
.field(cityPxy.getName(), "city_name", DBTypes.STRING);
manager.addBeanConfig(cityConf);
Country countryPxy = PropertiesProxy.create(Country.class);
BeanConfig countryConf = new BeanConfig(Country.class, "countries")
.pk(countryPxy.getName(), "country_ident", DBTypes.STRING);
manager.addBeanConfig(countryConf);
return manager;
}
@Test
public void test() {
PreparedStatement ppst = null;
try {
Company comp = new Company();
comp.setId("4356136");
comp.setName("W3C");
session.insert(comp);
Company basicComp = session.createBasicInstance(comp);
assertFalse(comp == basicComp);
assertNotNull(basicComp.getId());
assertNull(basicComp.getName());
if (AnsiSQLBeanSession.DEBUG) {
System.out.println("Company: " + comp);
System.out.println("Company (only pks): " + basicComp);
}
Employee emp = new Employee();
emp.setName("Érico");
emp.setNumber(391);
emp.setSalary(9999);
session.insert(emp);
Employee basicEmp = session.createBasicInstance(emp);
assertNull(basicEmp.getName());
assertEquals(0d, basicEmp.getSalary(), 0);
assertEquals(emp.getNumber(), basicEmp.getNumber());
Post post = new Post();
post.setCompany(comp);
post.setEmployee(emp);
post.setDescription("Programmer");
session.insert(post);
QueryBuilder builder = session.buildQuery();
Alias<Employee> e = builder.aliasTo(Employee.class, "emp");
Alias<Company> c = builder.aliasTo(Company.class, "com");
Alias<Post> p = builder.aliasTo(Post.class, "p");
Alias<Employee> e2 = builder.aliasTo(Employee.class, "emp2");
e2.setReturns(e2.pxy().getNumber());
Query query = builder.select(p, c, e)
.from(p)
.join(c).pkOf(c).in(p)
.join(e).pkOf(e).in(p)
.where()
.clause(new Substring(new ParamField(e, e.pxy().getName()))
/*
* it's joke (only for showing that's possible to do that)
*/
.beginIndex(new ParamFunction(new Length(
new ParamFunction(new Lower(
new ParamFunction(new Upper(
new ParamValue("c"))))))))
.endIndex(new ParamFunction(new Length(
new ParamFunction(new Lower(
new ParamField(e, e.pxy().getName())))))))
.condition(new Like(new ParamValue("%o"))).and()
.clause(e.pxy().getNumber()).condition(
new In(new ParamSubQuery(builder.subQuery()
.select(e2)
.from(e2)
.where()
.clause(new Substring(new ParamValue("teste")).endIndex(
new ParamFunction(new Length(new ParamValue("CA")))))
.condition(new Equals(new ParamValue("te")))
))).and()
.clause(new Lower(new ParamField(c, c.pxy().getName()))).condition(
new Equals(new ParamFunction(new Lower(new ParamValue("W3c")))))
.orderBy().asc(p, p.pxy().getDescription())
.limit(10);
ppst = query.prepare();
if (AnsiSQLBeanSession.DEBUG_NATIVE) {
System.out.println("CUSTOM: "+ppst);
}
ResultSet rs = ppst.executeQuery();
List<Post> list = new ArrayList<Post>();
while (rs.next()) {
Post pObj = new Post();
p.populateBean(rs, pObj);
c.populateBean(rs, pObj.getCompany());
e.populateBean(rs, pObj.getEmployee());
list.add(pObj);
}
assertEquals(1, list.size());
assertNotNull(list.get(0));
assertNotNull(list.get(0).getCompany());
assertNotNull(list.get(0).getEmployee());
}catch (Exception e) {
throw new BeanException(e);
}finally {
SQLUtils.close(ppst);
}
}
private BeanSession session;
@Before
public void setUp() {
AnsiSQLBeanSession.DEBUG = false;
AnsiSQLBeanSession.DEBUG_NATIVE = false;
session = new H2BeanSession(configure(), getConnection());
session.createTables();
prepareData();
}
@After
public void tearDown() {
SQLUtils.close(session.getConnection());
}
public void prepareData() {
 
Company comp;
Employee emp;
Post post;
 
Country usa = new Country("United States");
session.insert(usa);
 
City ny = new City(123, "New York", usa);
session.insert(ny);
City sf = new City(1020, "San Francisco", usa);
session.insert(sf);
 
/*
* Companies
*/
comp = new Company();
comp.setId("1");
comp.setName("Google");
comp.setCity(ny);
session.insert(comp);
 
comp = new Company();
comp.setId("2");
comp.setName("IBM");
session.insert(comp);
 
comp = new Company();
comp.setId("3");
comp.setName("Oracle");
comp.setCity(sf);
session.insert(comp);
 
 
/*
* Google employees
*/
comp = session.loadList(new Company("Google")).get(0);
 
emp = new Employee(19, "Maile Ohye", 19750);
session.insert(emp);
post = new Post(emp, comp, "Developer Programs Tech Lead");
session.insert(post);
 
emp = new Employee(12, "Ilya Grigorik", 10000);
session.insert(emp);
post = new Post(emp, comp, "Developer Advocate");
session.insert(post);
 
emp = new Employee(15, "Michael Manoochehri", 18100);
session.insert(emp);
post = new Post(emp, comp, "Developer Programs Engineer");
session.insert(post);
 
emp = new Employee(18, "Brian Cairns", 12500);
session.insert(emp);
post = new Post(emp, comp, "Software Engineer");
session.insert(post);
 
 
/*
* Oracle employees
*/
comp = session.loadList(new Company("Oracle")).get(0);
 
emp = new Employee(2, "Lawrence J. Ellison", 38900);
session.insert(emp);
post = new Post(emp, comp, "Chief Executive Officer");
session.insert(post);
 
emp = new Employee(1, "Mark V. Hurd", 63250);
session.insert(emp);
post = new Post(emp, comp, "President");
session.insert(post);
 
/*
* No company employee
*/
emp = new Employee();
emp.setName("No company");
emp.setNumber(999);
session.insert(emp);
 
}
/**
* Retrieve all employees
*/
@Test
public void query01() throws Exception {
 
QueryBuilder builder = session.buildQuery();
Alias<Employee> e = builder.aliasTo(Employee.class, "emp");
 
Query query = builder
.select(e)
.from(e);
 
List<Employee> list = query.executeQuery();
 
assertEquals(7, list.size());
}
/**
* Retrieve all employees which salary is greater then $15000 sorting by name
*/
@Test
public void query02() throws Exception {
 
QueryBuilder builder = session.buildQuery();
Alias<Employee> e = builder.aliasTo(Employee.class, "emp");
 
Query query = builder
.select(e)
.from(e)
.where()
.clause(e.pxy().getSalary())
.condition(new GreaterThan(15000))
.orderBy().asc(e, e.pxy().getName());
 
List<Employee> list = query.executeQuery();
 
assertEquals(4, list.size());
assertEquals(list.get(0).getName(), "Lawrence J. Ellison"); //first
assertEquals(list.get(3).getName(), "Michael Manoochehri"); //last
}
/**
* Retrieve all Google employees which name starts with "M" sorting by name
*/
@Test
public void query03() throws Exception {
 
QueryBuilder builder = session.buildQuery();
Alias<Employee> e = builder.aliasTo(Employee.class, "emp");
Alias<Company> c = builder.aliasTo(Company.class, "com");
Alias<Post> p = builder.aliasTo(Post.class);
 
Query query = builder
.select(e)
.from(e)
.join(p).pkOf(e).in(p)
.join(c).pkOf(c).in(p)
.where()
.clause(c.pxy().getName())
.condition(new Equals("Google"))
.and()
.clause(e.pxy().getName())
.condition(new Like("M%"))
.orderBy().asc(e, e.pxy().getName());
 
List<Employee> list = query.executeQuery();
 
assertEquals(2, list.size());
assertEquals(list.get(0).getName(), "Maile Ohye"); //first
assertEquals(list.get(1).getName(), "Michael Manoochehri"); //last
}
/**
* Retrieve all Google employees which salary between 10000 and 15000 sorting by salary
*/
@Test
public void query04() throws Exception {
 
QueryBuilder builder = session.buildQuery();
Alias<Employee> e = builder.aliasTo(Employee.class, "emp");
Alias<Company> c = builder.aliasTo(Company.class, "com");
Alias<Post> p = builder.aliasTo(Post.class);
 
Query query = builder
.select(e)
.from(e)
.join(p).pkOf(e).in(p)
.join(c).pkOf(c).in(p)
.where()
.clause(c.pxy().getId())
.condition(new Equals("1"))
.and()
.clause(e.pxy().getSalary())
.condition(new Between(10000, 15000))
.orderBy().asc(e, e.pxy().getSalary());
 
List<Employee> list = query.executeQuery();
 
assertEquals(2, list.size());
assertEquals(list.get(0).getName(), "Ilya Grigorik"); //first
assertEquals(list.get(1).getName(), "Brian Cairns"); //last
}
/**
* Retrieve all posts (with employees and companies) sorting by company name ASC and employee name DESC
*/
@Test
public void query05() throws Exception {
 
QueryBuilder builder = session.buildQuery();
Alias<Employee> e = builder.aliasTo(Employee.class, "emp");
Alias<Company> c = builder.aliasTo(Company.class, "com");
Alias<Post> p = builder.aliasTo(Post.class);
 
Query query = builder
.select(p, e, c)
.from(p)
.join(e).pkOf(e).in(p)
//here we set the bean where 'e' alias (employee) will be populate
.inProperty(p.pxy().getEmployee())
.join(c).pkOf(c).in(p)
//here we set the bean where 'c' alias (company) will be populate
.inProperty(p.pxy().getCompany())
.orderBy()
.asc(c, c.pxy().getName())
.desc(e, e.pxy().getName());
 
List<Post> list = query.executeQuery();
assertNotNull(list.get(0).getCompany().getName());
assertEquals(6, list.size());
assertEquals(list.get(0).getEmployee().getName(), "Michael Manoochehri"); //first
assertEquals(list.get(0).getCompany().getName(), "Google"); //first
assertEquals(list.get(5).getEmployee().getName(), "Lawrence J. Ellison"); //last
assertEquals(list.get(5).getCompany().getName(), "Oracle"); //last
}
/**
* Retrieve all employees that have no company
*/
@Test
public void query06() {
QueryBuilder builder = session.buildQuery();
Alias<Employee> e = builder.aliasTo(Employee.class, "emp");
Alias<Employee> eSub = builder.aliasTo(Employee.class, "emp_sub");
eSub.setReturns(eSub.pxy().getNumber());
Alias<Post> p = builder.aliasTo(Post.class);
Query query = builder
.select(e)
.from(e)
.where()
.clause(e.pxy().getNumber())
//sub query in 'NOT IN' condition
.condition(new NotIn(new ParamSubQuery(
builder.subQuery()
.select(eSub)
.from(eSub)
.join(p).pkOf(eSub).in(p))
));
List<Employee> list = query.executeQuery();
assertEquals(1, list.size());
assertEquals(list.get(0).getName(), "No company");
}
/**
* Retrieve all employees that have no company (same as above, just another way to build the SQL query)
*/
@Test
public void query07() {
QueryBuilder builder = session.buildQuery();
Alias<Employee> e = builder.aliasTo(Employee.class, "emp");
Alias<Post> p = builder.aliasTo(Post.class);
Query query = builder
.select(e)
.from(e)
.leftJoin(p).pkOf(e).in(p)
.where()
.clause(p.pxy().getDescription())
//this will be converted to 'IS NULL' in query. See the Equals condition
.condition(new Equals(null));
List<Employee> list = query.executeQuery();
assertEquals(1, list.size());
assertEquals(list.get(0).getName(), "No company");
}
/**
* Retrieve all employees which name length is greater then 15 sorting by length ASC, name DESC
*/
@Test
public void query08() {
QueryBuilder builder = session.buildQuery();
Alias<Employee> e = builder.aliasTo(Employee.class, "emp");
Query query = builder
.select(e)
.from(e)
.where()
.clause(new Length(new ParamField(e, e.pxy().getName())))
.condition(new GreaterThan(15))
.orderBy()
.asc(new ParamFunction(new Length(new ParamField(e, e.pxy().getName()))))
.desc(e, e.pxy().getName());
List<Employee> list = query.executeQuery();
assertEquals(2, list.size());
assertEquals(list.get(0).getName(), "Michael Manoochehri");
assertEquals(list.get(1).getName(), "Lawrence J. Ellison");
}
/**
* Retrieve all companies with a count of employees sorting by company name ASC
*/
@Test
public void query09() {
QueryBuilder builder = session.buildQuery();
Alias<Company> c = builder.aliasTo(Company.class, "c");
Alias<Employee> e = builder.aliasTo(Employee.class, "e");
Alias<Post> p = builder.aliasTo(Post.class, "p");
Sentence count = new Sentence(new Count(new ParamField(e, e.pxy().getNumber())))
.fromProperty(c.pxy().getEmployeesCount());
Query query = builder
.select(c)
.add(count)
.from(c)
.leftJoin(p).pkOf(c).in(p)
.leftJoin(e).pkOf(e).in(p)
.groupBy(c)
.orderBy()
.asc(c, c.pxy().getName());
List<Company> list = query.executeQuery();
assertEquals(3, list.size());
assertEquals(list.get(0).getName(), "Google");
assertEquals(list.get(0).getEmployeesCount(), 4);
assertEquals(list.get(1).getName(), "IBM");
assertEquals(list.get(1).getEmployeesCount(), 0);
assertEquals(list.get(2).getName(), "Oracle");
assertEquals(list.get(2).getEmployeesCount(), 2);
}
/**
* Retrieve all companies having count of employees greater than 0 (zero) sorting by number of employees ASC
*/
@Test
public void query10() {
QueryBuilder builder = session.buildQuery();
Alias<Company> c = builder.aliasTo(Company.class, "c");
Alias<Employee> e = builder.aliasTo(Employee.class, "e");
Alias<Post> p = builder.aliasTo(Post.class, "p");
Sentence count = new Sentence(new Count(new ParamField(e, e.pxy().getNumber())))
.fromProperty(c.pxy().getEmployeesCount());
Query query = builder
.select(c)
.add(count)
.from(c)
.leftJoin(p).pkOf(c).in(p)
.leftJoin(e).pkOf(e).in(p)
.groupBy(c)
.having()
.clause(count)
.condition(new GreaterThan(0))
.orderBy()
.asc(new ParamFunction(count));
List<Company> list = query.executeQuery();
assertEquals(2, list.size());
assertEquals(list.get(0).getName(), "Oracle");
assertEquals(list.get(0).getEmployeesCount(), 2);
assertEquals(list.get(1).getName(), "Google");
assertEquals(list.get(1).getEmployeesCount(), 4);
}
/**
* Retrieve all companies with a count of employees sorting by company name ASC
*/
@Test
public void query11() {
QueryBuilder builder = session.buildQuery();
Alias<Company> c = builder.aliasTo(Company.class, "com");
Alias<Employee> e = builder.aliasTo(Employee.class, "emp");
Alias<Post> p = builder.aliasTo(Post.class, "p");
Alias<Post> p2 = builder.aliasTo(Post.class, "p2");
Query sub = builder.subQuery()
.select(new Sentence(new Count(new ParamField(p2, p2.pxy().getDescription()))).name("count_sub"))
.from(p2)
.where()
.clause(p2.pxy().getCompany().getId())
.condition(new Equals(new ParamField(c, c.pxy().getId())));
Query query = builder
.select(p, c)
.add(new Sentence(sub)
.fromProperty(p.pxy().getCompany().getEmployeesCount()))
.from(p)
.leftJoin(c).pkOf(c).in(p)
.inProperty(p.pxy().getCompany())
.leftJoin(e).pkOf(e).in(p)
.inProperty(p.pxy().getEmployee())
.orderBy()
.asc(c, c.pxy().getName());
List<Post> list = query.executeQuery();
assertEquals(6, list.size());
assertEquals(list.get(0).getCompany().getName(), "Google");
assertEquals(list.get(0).getCompany().getEmployeesCount(), 4);
assertEquals(list.get(5).getCompany().getName(), "Oracle");
assertEquals(list.get(5).getCompany().getEmployeesCount(), 2);
}
/**
* Retrieve all companies with name upper case
*/
@Test
public void query12() {
QueryBuilder builder = session.buildQuery();
Alias<Company> c = builder.aliasTo(Company.class, "c");
Sentence nameUpper = new Sentence(new Upper(new ParamField(c, c.pxy().getName())))
.fromProperty(c.pxy().getName());
Query query = builder
.select(c)
.add(nameUpper)
.from(c)
.orderBy()
.asc(c, c.pxy().getName());
List<Company> list = query.executeQuery();
assertEquals(3, list.size());
assertEquals(list.get(0).getName(), "GOOGLE");
assertEquals(list.get(1).getName(), "IBM");
assertEquals(list.get(2).getName(), "ORACLE");
}
/**
* Retrieve all companies with name upper case and a count of employees
*/
@Test
public void query13() {
QueryBuilder builder = session.buildQuery();
Alias<Company> c = builder.aliasTo(Company.class, "c");
c.setReturnMinus(c.pxy().getName());
Alias<Employee> e = builder.aliasTo(Employee.class, "e");
Alias<Post> p = builder.aliasTo(Post.class, "p");
Sentence nameUpper = new Sentence(new Upper(new ParamField(c, c.pxy().getName())))
.fromProperty(c.pxy().getName());
Sentence count = new Sentence(new Count(new ParamField(e, e.pxy().getNumber())))
.fromProperty(c.pxy().getEmployeesCount());
Query query = builder
.select(c)
.add(count)
.add(nameUpper)
.from(c)
.leftJoin(p).pkOf(c).in(p)
.leftJoin(e).pkOf(e).in(p)
.groupBy();
List<Company> list = query.executeQuery();
assertEquals(3, list.size());
assertEquals("ORACLE", list.get(0).getName());
assertEquals(2, list.get(0).getEmployeesCount());
assertEquals("GOOGLE", list.get(1).getName());
assertEquals(4, list.get(1).getEmployeesCount());
assertEquals("IBM", list.get(2).getName());
assertEquals(0, list.get(2).getEmployeesCount());
}
/**
* Retrieve all posts
*/
@Test
public void query14() {
QueryBuilder builder = session.buildQuery();
Alias<Post> p = builder.aliasTo(Post.class, "p");
Query query = builder.selectFrom(p);
List<Post> list = query.executeQuery();
assertEquals(6, list.size());
for (Post post : list) {
assertNotNull(post.getCompany());
assertNotNull(post.getEmployee());
assertNotNull(post.getCompany().getId());
assertTrue(post.getEmployee().getNumber() > 0);
assertNull(post.getCompany().getName());
assertNull(post.getEmployee().getName());
}
}
/**
* Retrieve all posts with company and employee using <code>executeQuery()</code> method
*/
@Test
public void queryExecuteQuery() {
QueryBuilder builder = session.buildQuery();
Alias<Company> c = builder.aliasTo(Company.class, "c");
Alias<Employee> e = builder.aliasTo(Employee.class, "e");
Alias<Post> p = builder.aliasTo(Post.class, "p");
Query query = builder
.select(p, e, c)
.from(p)
.leftJoin(c).pkOf(c).in(p)
.inProperty(p.pxy().getCompany())
.leftJoin(e).pkOf(e).in(p)
.inProperty(p.pxy().getEmployee());
List<Post> list = query.executeQuery();
assertEquals(6, list.size());
for (Post post : list) {
assertNotNull(post.getCompany());
assertNotNull(post.getEmployee());
assertNotNull(post.getCompany().getId());
assertTrue(post.getEmployee().getNumber() > 0);
assertNotNull(post.getCompany().getName());
assertNotNull(post.getEmployee().getName());
}
}
/**
* Retrieve all posts using <code>prepare()</code> and <code>populateBean</code> methods.
*/
@Test
public void queryPrepare() {
 
PreparedStatement ppst = null;
 
try {
 
QueryBuilder builder = session.buildQuery();
Alias<Company> c = builder.aliasTo(Company.class, "c");
Alias<Employee> e = builder.aliasTo(Employee.class, "e");
Alias<Post> p = builder.aliasTo(Post.class, "p");
 
Query query = builder
.select(p, e, c)
.from(p)
.leftJoin(c).pkOf(c).in(p)
.leftJoin(e).pkOf(e).in(p);
List<Post> list = new ArrayList<Post>();
ppst = query.prepare();
ResultSet rs = ppst.executeQuery();
Post obj;
while (rs.next()) {
obj = new Post();
p.populateBean(rs, obj);
if (obj.getCompany() != null) {
c.populateBean(rs, obj.getCompany());
}
if (obj.getEmployee() != null) {
e.populateBean(rs, obj.getEmployee());
}
list.add(obj);
}
 
assertEquals(6, list.size());
for (Post post : list) {
assertNotNull(post.getCompany());
assertNotNull(post.getEmployee());
assertNotNull(post.getCompany().getId());
assertTrue(post.getEmployee().getNumber() > 0);
assertNotNull(post.getCompany().getName());
assertNotNull(post.getEmployee().getName());
}
}catch (Exception e) {
throw new BeanException(e);
}finally {
SQLUtils.close(ppst);
}
}
/**
* Retrieve all companies with a count of employees (manual way)
*/
@Test
public void query15() {
 
PreparedStatement ppst = null;
 
try {
QueryBuilder builder = session.buildQuery();
Alias<Company> c = builder.aliasTo(Company.class, "c");
Alias<Employee> e = builder.aliasTo(Employee.class, "e");
Alias<Post> p = builder.aliasTo(Post.class, "p");
 
Sentence count = new Sentence(new Count(
new ParamField(e, e.pxy().getNumber())))
.returnType(DBTypes.INTEGER)
.name("count");
 
Query query = builder
.select(c)
.add(count)
.from(c)
.leftJoin(p).pkOf(c).in(p)
.leftJoin(e).pkOf(e).in(p)
.groupBy();
 
List<Company> list = new ArrayList<Company>();
ppst = query.prepare();
ResultSet rs = ppst.executeQuery();
Company obj;
 
while (rs.next()) {
obj = new Company();
c.populateBean(rs, obj);
 
Integer employeesCount = query.getValueFromResultSet(rs, "count");
obj.setEmployeesCount(employeesCount);
 
list.add(obj);
}
 
assertEquals(3, list.size());
 
assertEquals("Oracle", list.get(0).getName());
assertEquals(2, list.get(0).getEmployeesCount());
assertEquals("IBM", list.get(1).getName());
assertEquals(0, list.get(1).getEmployeesCount());
 
assertEquals("Google", list.get(2).getName());
assertEquals(4, list.get(2).getEmployeesCount());
 
}catch (Exception e) {
throw new BeanException(e);
}finally {
SQLUtils.close(ppst);
}
}
/**
* Returns only the count of posts in database
*/
@Test
public void queryCount() {
QueryBuilder builder = session.buildQuery();
Alias<Post> p = builder.aliasTo(Post.class, "p");
Sentence count = new Sentence(
new Add()
.param(new Count(new ParamField(p, p.pxy().getDescription())))
.param(4))
.name("count")
.returnType(DBTypes.INTEGER);
Query query = builder
.select(count)
.from(p);
Integer postCount = query.executeSentence();
assertEquals(6 + 4, (int)postCount);
}
/**
* Throws an exception because there are no sentences in query
*/
@Test (expected = BeanException.class)
public void queryCountWithNoSentence() {
QueryBuilder builder = session.buildQuery();
Alias<Post> p = builder.aliasTo(Post.class, "p");
Query query = builder
.selectFrom(p);
query.executeSentence();
}
/**
* Retrieve all posts where company or employe name contains 'O' and salary less than 50000,
* order by post description
*/
@Test
public void query16() {
QueryBuilder builder = session.buildQuery();
Alias<Post> p = builder.aliasTo(Post.class, "p");
Alias<Employee> e = builder.aliasTo(Employee.class, "e");
Alias<Company> c = builder.aliasTo(Company.class, "c");
Query query = builder
.select(p, e, c)
.from(p)
.leftJoin(c).pkOf(c).in(p)
.inProperty(p.pxy().getCompany())
.leftJoin(e).pkOf(e).in(p)
.inProperty(p.pxy().getEmployee())
.where()
.openPar()
.clause(c.pxy().getName())
.condition(new Like("%O%"))
.or()
.clause(e.pxy().getName())
.condition(new Like("%O%"))
.closePar()
.and()
.clause(e.pxy().getSalary())
.condition(new LessThan(50000))
.orderBy()
.asc(p, p.pxy().getDescription());
List<Post> list = query.executeQuery();
assertEquals(2, list.size());
assertEquals("Lawrence J. Ellison", list.get(0).getEmployee().getName());
assertEquals("Maile Ohye", list.get(1).getEmployee().getName());
}
/**
* Retrieve posts using parenthesis
*/
@Test
public void queryParenthesis() {
QueryBuilder builder = session.buildQuery();
Alias<Company> c = builder.aliasTo(Company.class, "c");
Alias<Employee> e = builder.aliasTo(Employee.class, "e");
Alias<Post> p = builder.aliasTo(Post.class, "p");
assertEquals(6, builder
.select(p, e, c)
.from(p)
.leftJoin(c).on(c.pxy().getId()).eq(p.pxy().getCompany().getId())
.eqProperty(p.pxy().getCompany())
.leftJoin(e).on(e.pxy().getNumber()).eq(p.pxy().getEmployee().getNumber())
.eqProperty(p.pxy().getEmployee())
.where()
.openPar()
.clauseIf(false, c.pxy().getName())
.condition(new Like("Google"))
.or()
.clauseIf(false, c.pxy().getName())
.condition(new Like("Oracle"))
.closePar()
.executeQuery().size());
assertEquals(6, builder
.select(p, e, c)
.from(p)
.leftJoin(c).on(c.pxy().getId()).eq(p.pxy().getCompany().getId())
.eqProperty(p.pxy().getCompany())
.leftJoin(e).on(e.pxy().getNumber()).eq(p.pxy().getEmployee().getNumber())
.eqProperty(p.pxy().getEmployee())
.where()
.openPar()
.clauseIf(false, c.pxy().getName())
.condition(new Like("Google"))
.or()
.clauseIf(true, c.pxy().getName())
.condition(new Like("%"))
.or()
.clauseIf(false, c.pxy().getName())
.condition(new Like("Oracle"))
.closePar()
.executeQuery().size());
assertEquals(4, builder
.select(p, e, c)
.from(p)
.leftJoin(c).on(c.pxy().getId()).eq(p.pxy().getCompany().getId())
.eqProperty(p.pxy().getCompany())
.leftJoin(e).on(e.pxy().getNumber()).eq(p.pxy().getEmployee().getNumber())
.eqProperty(p.pxy().getEmployee())
.where()
.openPar()
.clauseIf(true, c.pxy().getName())
.condition(new Like("Google"))
.or()
.clauseIf(false, c.pxy().getName())
.condition(new Like("Oracle"))
.closePar()
.and()
.openPar()
.clauseIf(false, c.pxy().getName())
.condition(new Like("Oracle"))
.closePar()
.executeQuery().size());
assertEquals(4, builder
.select(p, e, c)
.from(p)
.leftJoin(c).on(c.pxy().getId()).eq(p.pxy().getCompany().getId())
.eqProperty(p.pxy().getCompany())
.leftJoin(e).on(e.pxy().getNumber()).eq(p.pxy().getEmployee().getNumber())
.eqProperty(p.pxy().getEmployee())
.where()
.openPar()
.clauseIf(true, c.pxy().getName())
.condition(new Like("Google"))
.or()
.clauseIf(false, c.pxy().getName())
.condition(new Like("Oracle"))
.closePar()
.and()
.openPar()
.clauseIf(false, c.pxy().getName())
.condition(new Like("Oracle"))
.and()
.clauseIf(true, c.pxy().getName())
.condition(new Like("Google"))
.closePar()
.executeQuery().size());
assertEquals(4, builder
.select(p, e, c)
.from(p)
.leftJoin(c).on(c.pxy().getId()).eq(p.pxy().getCompany().getId())
.eqProperty(p.pxy().getCompany())
.leftJoin(e).on(e.pxy().getNumber()).eq(p.pxy().getEmployee().getNumber())
.eqProperty(p.pxy().getEmployee())
.where()
.openPar()
.clauseIf(true, c.pxy().getName())
.condition(new Like("Google"))
.or()
.clauseIf(false, c.pxy().getName())
.condition(new Like("Oracle"))
.closePar()
.and()
.openPar()
.clauseIf(false, c.pxy().getName())
.condition(new Like("Oracle"))
.and()
.clauseIf(false, c.pxy().getName())
.condition(new Like("Google"))
.closePar()
.executeQuery().size());
assertEquals(2, builder
.select(p, e, c)
.from(p)
.leftJoin(c).on(c.pxy().getId()).eq(p.pxy().getCompany().getId())
.eqProperty(p.pxy().getCompany())
.leftJoin(e).on(e.pxy().getNumber()).eq(p.pxy().getEmployee().getNumber())
.eqProperty(p.pxy().getEmployee())
.where()
.openPar()
.clauseIf(false, c.pxy().getName())
.condition(new Like("Google"))
.or()
.clauseIf(false, c.pxy().getName())
.condition(new Like("Oracle"))
.closePar()
.or()
.openPar()
.clauseIf(true, c.pxy().getName())
.condition(new Like("Oracle"))
.and()
.clauseIf(false, c.pxy().getName())
.condition(new Like("Google"))
.closePar()
.executeQuery().size());
assertEquals(6, builder
.select(p, e, c)
.from(p)
.leftJoin(c).on(c.pxy().getId()).eq(p.pxy().getCompany().getId())
.eqProperty(p.pxy().getCompany())
.leftJoin(e).on(e.pxy().getNumber()).eq(p.pxy().getEmployee().getNumber())
.eqProperty(p.pxy().getEmployee())
.where()
.openPar()
.clauseIf(false, c.pxy().getName())
.condition(new Like("Google"))
.or()
.clauseIf(false, c.pxy().getName())
.condition(new Like("Oracle"))
.closePar()
.or()
.openPar()
.clauseIf(false, c.pxy().getName())
.condition(new Like("Oracle"))
.and()
.clauseIf(false, c.pxy().getName())
.condition(new Like("Google"))
.closePar()
.executeQuery().size());
assertEquals(0, builder
.select(p, e, c)
.from(p)
.leftJoin(c).on(c.pxy().getId()).eq(p.pxy().getCompany().getId())
.eqProperty(p.pxy().getCompany())
.leftJoin(e).on(e.pxy().getNumber()).eq(p.pxy().getEmployee().getNumber())
.eqProperty(p.pxy().getEmployee())
.where()
.openPar()
.clauseIf(true, c.pxy().getName())
.condition(new Like("Google"))
.or()
.clauseIf(false, c.pxy().getName())
.condition(new Like("Oracle"))
.closePar()
.and()
.clause(c.pxy().getName())
.condition(new Like("Oracle"))
.executeQuery().size());
assertEquals(4, builder
.select(p, e, c)
.from(p)
.leftJoin(c).pkOf(c).in(p)
.inProperty(p.pxy().getCompany())
.leftJoin(e).pkOf(e).in(p)
.inProperty(p.pxy().getEmployee())
.where()
.openPar()
.clauseIf(true, c.pxy().getName())
.condition(new Like("Google"))
.or()
.clauseIf(false, c.pxy().getName())
.condition(new Like("Oracle"))
.closePar()
.executeQuery().size());
assertEquals(2, builder
.select(p, e, c)
.from(p)
.leftJoin(c).pkOf(c).in(p)
.inProperty(p.pxy().getCompany())
.leftJoin(e).pkOf(e).in(p)
.inProperty(p.pxy().getEmployee())
.where()
.openPar()
.clauseIf(false, c.pxy().getName())
.condition(new Like("Google"))
.or()
.clauseIf(true, c.pxy().getName())
.condition(new Like("Oracle"))
.closePar()
.executeQuery().size());
assertEquals(0, builder
.select(p, e, c)
.from(p)
.leftJoin(c).pkOf(c).in(p)
.inProperty(p.pxy().getCompany())
.leftJoin(e).pkOf(e).in(p)
.inProperty(p.pxy().getEmployee())
.where()
.openPar()
.clauseIf(true, c.pxy().getName())
.condition(new Like("Google"))
.and()
.clauseIf(true, c.pxy().getName())
.condition(new Like("Oracle"))
.closePar()
.executeQuery().size());
assertEquals(6, builder
.select(p, e, c)
.from(p)
.leftJoin(c).pkOf(c).in(p)
.inProperty(p.pxy().getCompany())
.leftJoin(e).pkOf(e).in(p)
.inProperty(p.pxy().getEmployee())
.where()
.clauseIf(true, c.pxy().getName())
.condition(new Like("Google"))
.and()
.openPar()
.clauseIf(false, c.pxy().getName())
.condition(new Like("Oracle"))
.closePar()
.or()
.clauseIf(true, c.pxy().getName())
.condition(new Like("Oracle"))
.executeQuery().size());
assertEquals(0, builder
.select(p, e, c)
.from(p)
.leftJoin(c).pkOf(c).in(p)
.inProperty(p.pxy().getCompany())
.leftJoin(e).pkOf(e).in(p)
.inProperty(p.pxy().getEmployee())
.where()
.clauseIf(true, c.pxy().getName())
.condition(new Like("Google"))
.and()
.openPar()
.openPar()
.clauseIf(false, c.pxy().getName())
.condition(new Like("Oracle"))
.closePar()
.or()
.clauseIf(true, c.pxy().getName())
.condition(new Like("Oracle"))
.closePar()
.executeQuery().size());
assertEquals(6, builder
.selectDistinct(p, e, c)
.from(p)
.leftJoin(c).pkOf(c).in(p)
.inProperty(p.pxy().getCompany())
.leftJoin(e).pkOf(e).in(p)
.inProperty(p.pxy().getEmployee())
.where()
.openPar()
.clauseIf(false, c.pxy().getName())
.condition(new Like("Google"))
.or()
.clauseIf(false, c.pxy().getName())
.condition(new Like("Oracle"))
.closePar()
.and()
.clauseIf(false, e.pxy().getName())
.condition(new Like("%"))
.executeQuery().size());
assertEquals(6, builder
.selectDistinct(p, e, c)
.from(p)
.leftJoin(c).pkOf(c).in(p)
.inProperty(p.pxy().getCompany())
.leftJoin(e).pkOf(e).in(p)
.inProperty(p.pxy().getEmployee())
.where()
.openPar()
.clauseIf(true, c.pxy().getName())
.condition(new Like("Google"))
.or()
.clauseIf(true, c.pxy().getName())
.condition(new Like("Oracle"))
.closePar()
.and()
.clauseIf(true, e.pxy().getName())
.condition(new Like("%"))
.executeQuery().size());
assertEquals(4, builder
.select(p, e, c)
.from(p)
.leftJoin(c).pkOf(c).in(p)
.inProperty(p.pxy().getCompany())
.leftJoin(e).pkOf(e).in(p)
.inProperty(p.pxy().getEmployee())
.where()
.openPar()
.openPar()
.clauseIf(true, c.pxy().getName())
.condition(new Like("Google"))
.closePar()
.and()
.openPar()
.clauseIf(false, c.pxy().getName())
.condition(new Like("Oracle"))
.or()
.openPar()
.clauseIf(true, c.pxy().getId())
.condition(new NotEquals(null))
.closePar()
.closePar()
.closePar()
.and()
.clauseIf(false, e.pxy().getName())
.condition(new Like("%"))
.limit(6)
.executeQuery().size());
}
@Test
public void limitNumberTest() {
 
QueryBuilder builder = session.buildQuery();
Alias<Company> c = builder.aliasTo(Company.class, "c");
Alias<Employee> e = builder.aliasTo(Employee.class, "e");
Alias<Post> p = builder.aliasTo(Post.class, "p");
 
assertEquals(6, builder
.selectDistinct(p, e, c)
.from(p)
.leftJoin(c).pkOf(c).in(p)
.inProperty(p.pxy().getCompany())
.leftJoin(e).pkOf(e).in(p)
.inProperty(p.pxy().getEmployee())
.where()
.openPar()
.clauseIf(false, c.pxy().getName())
.condition(new Like("Google"))
.or()
.clauseIf(false, c.pxy().getName())
.condition(new Like("Oracle"))
.closePar()
.limit(0)
.executeQuery().size());
assertEquals(3, builder
.select(p, e, c)
.from(p)
.leftJoin(c).pkOf(c).in(p)
.inProperty(p.pxy().getCompany())
.leftJoin(e).pkOf(e).in(p)
.inProperty(p.pxy().getEmployee())
.where()
.openPar()
.clauseIf(false, c.pxy().getName())
.condition(new Like("Google"))
.or()
.clauseIf(false, c.pxy().getName())
.condition(new Like("Oracle"))
.closePar()
.limit(3)
.executeQuery().size());
}
@Test
public void paramHandlerTest() {
QueryBuilder builder = session.buildQuery();
Alias<Company> c = builder.aliasTo(Company.class, "c");
Alias<Post> p = builder.aliasTo(Post.class, "p");
ParamHandler paramHandler = new DefaultParamHandler();
Param found;
found = paramHandler.findBetter(builder, 3);
Assert.assertTrue(found instanceof ParamValue);
found = paramHandler.findBetter(builder, null);
Assert.assertTrue(found instanceof ParamValue);
found = paramHandler.findBetter(builder, builder.subQuery().selectFrom(c));
Assert.assertTrue(found instanceof ParamSubQuery);
builder.selectFrom(c).where().clause(c.pxy().getName()).condition(new NotEquals(null)).executeQuery();
found = paramHandler.findBetter(builder, c.pxy().getName());
Assert.assertTrue(found instanceof ParamField);
builder = builder.subQuery();
builder.select(c, p)
.from(c)
.join(p).pkOf(c).in(p)
.where().clause(p.pxy().getDescription())
.condition(new NotEquals("aaaaaaaa"))
.and()
.clause(c.pxy().getName())
.condition(new NotEquals("aaaaaaaaa"))
.executeQuery();
found = paramHandler.findBetter(builder, p.pxy().getDescription());
Assert.assertTrue(found instanceof ParamField);
found = paramHandler.findBetter(builder, c.pxy().getId());
Assert.assertTrue(found instanceof ParamField);
found = paramHandler.findBetter(builder, new Avg(null));
Assert.assertTrue(found instanceof ParamFunction);
}
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/test/java/org/mentabean/jdbc/AbstractBeanSessionTest.java
New file
0,0 → 1,111
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.jdbc;
 
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
 
public abstract class AbstractBeanSessionTest {
 
protected static Connection getConnection() {
try {
Class.forName("org.h2.Driver");
return DriverManager.getConnection("jdbc:h2:mem:MentaBean", "sa", "");
} catch (Exception e) {
throw new IllegalStateException("Cannot connect to H2 database!", e);
}
}
 
protected static void execUpdate(Connection conn, String query) throws SQLException {
 
Statement stmt = null;
 
try {
 
stmt = conn.createStatement();
 
stmt.executeUpdate(query);
 
} finally {
 
close(stmt);
}
}
 
static void close(PreparedStatement stmt) {
close(stmt, null);
}
 
static void close(PreparedStatement stmt, ResultSet rset) {
 
if (rset != null) {
try {
rset.close();
} catch (Exception e) {
e.printStackTrace();
}
}
 
if (stmt != null) {
try {
stmt.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
 
static void close(Statement stmt) {
close(stmt, null);
}
 
static void close(Statement stmt, ResultSet rset) {
 
if (rset != null) {
try {
rset.close();
} catch (Exception e) {
e.printStackTrace();
}
}
 
if (stmt != null) {
try {
stmt.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
 
static void close(Connection conn) {
 
if (conn != null) {
try {
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
 
}
/tags/menta-bean-2.2.2/src/test/java/org/mentabean/jdbc/PropertiesProxyTest.java
New file
0,0 → 1,282
package org.mentabean.jdbc;
 
import junit.framework.Assert;
 
import org.junit.Before;
import org.junit.Test;
import org.mentabean.util.DefaultProxy;
import org.mentabean.util.PropertiesProxy;
 
public class PropertiesProxyTest {
public static class User {
private String blah1;
private int blah2;
private Integer blah3;
private Address address;
public String getBlah1() {
return blah1;
}
public void setBlah1(String blah1) {
this.blah1 = blah1;
}
public int getBlah2() {
return blah2;
}
public void setBlah2(int blah2) {
this.blah2 = blah2;
}
public Integer getBlah3() {
return blah3;
}
public void setBlah3(Integer blah3) {
this.blah3 = blah3;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
}
public static class Address {
private int foo1;
private String foo2;
private City city;
public int getFoo1() {
return foo1;
}
public void setFoo1(int foo1) {
this.foo1 = foo1;
}
public String getFoo2() {
return foo2;
}
public void setFoo2(String foo2) {
this.foo2 = foo2;
}
public City getCity() {
return city;
}
public void setCity(City city) {
this.city = city;
}
}
public static class City {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
private static boolean check(String[] array, String s) {
for(String x : array) {
if (s.equals(x)) return true;
}
return false;
}
@Before
public void setUp() {
PropertiesProxy.INSTANCE = new DefaultProxy();
}
@Test
public void testRegular() {
User userProp = PropertiesProxy.create(User.class);
userProp.getBlah1();
Assert.assertEquals("blah1", PropertiesProxy.getPropertyName());
userProp.getBlah3();
Assert.assertEquals("blah3", PropertiesProxy.getPropertyName());
userProp.getBlah1();
userProp.getBlah2();
String[] array = PropertiesProxy.getPropertyNames();
Assert.assertEquals(2, array.length);
Assert.assertTrue(check(array, "blah1"));
Assert.assertTrue(check(array, "blah2"));
}
@Test
public void testNonFinal() {
User userProp = PropertiesProxy.create(User.class);
userProp.getBlah1();
Assert.assertEquals("blah1", PropertiesProxy.getPropertyName());
userProp.getAddress();
Assert.assertEquals("address", PropertiesProxy.getPropertyName());
userProp.getAddress();
userProp.getBlah3();
String[] array = PropertiesProxy.getPropertyNames();
Assert.assertEquals(2, array.length);
Assert.assertTrue(check(array, "address"));
Assert.assertTrue(check(array, "blah3"));
}
@Test
public void testNestedProperties() {
User userProp = PropertiesProxy.create(User.class);
userProp.getBlah1();
userProp.getAddress().getFoo1();
String[] array = PropertiesProxy.getPropertyNames();
Assert.assertEquals(2, array.length);
Assert.assertTrue(check(array, "blah1"));
Assert.assertTrue(check(array, "address.foo1"));
userProp.getAddress().getFoo2();
userProp.getBlah3();
array = PropertiesProxy.getPropertyNames();
Assert.assertEquals(2, array.length);
Assert.assertTrue(check(array, "address.foo2"));
Assert.assertTrue(check(array, "blah3"));
}
@Test
public void testThreeLevels() {
User userProp = PropertiesProxy.create(User.class);
userProp.getBlah2();
userProp.getAddress().getCity().getId();
userProp.getBlah1();
String[] array = PropertiesProxy.getPropertyNames();
Assert.assertEquals(3, array.length);
Assert.assertTrue(check(array, "blah2"));
Assert.assertTrue(check(array, "address.city.id"));
Assert.assertTrue(check(array, "blah1"));
 
userProp.getAddress().getFoo2();
userProp.getBlah3();
userProp.getAddress().getCity().getId();
userProp.getBlah1();
array = PropertiesProxy.getPropertyNames();
Assert.assertEquals(4, array.length);
Assert.assertTrue(check(array, "address.foo2"));
Assert.assertTrue(check(array, "blah3"));
Assert.assertTrue(check(array, "address.city.id"));
Assert.assertTrue(check(array, "blah1"));
}
@Test
public void testVarargs() {
User userProp = PropertiesProxy.create(User.class);
Object[] obj = new Object[] { "blah1", "blah2" };
String[] array = AnsiSQLBeanSession.getProperties(obj);
Assert.assertEquals(2, array.length);
Assert.assertTrue(check(array, "blah1"));
Assert.assertTrue(check(array, "blah2"));
obj = new Object[] { "blah1", userProp.getBlah3(), "blah2" };
array = AnsiSQLBeanSession.getProperties(obj);
Assert.assertEquals(3, array.length);
Assert.assertTrue(check(array, "blah1"));
Assert.assertTrue(check(array, "blah2"));
Assert.assertTrue(check(array, "blah3"));
obj = new Object[] { userProp.getBlah3() };
array = AnsiSQLBeanSession.getProperties(obj);
Assert.assertEquals(1, array.length);
Assert.assertTrue(check(array, "blah3"));
obj = new Object[] { userProp.getBlah2(), userProp.getBlah3() };
array = AnsiSQLBeanSession.getProperties(obj);
Assert.assertEquals(2, array.length);
Assert.assertTrue(check(array, "blah2"));
Assert.assertTrue(check(array, "blah3"));
obj = new Object[] { userProp.getBlah3(), userProp.getAddress() };
array = AnsiSQLBeanSession.getProperties(obj);
Assert.assertEquals(2, array.length);
Assert.assertTrue(check(array, "blah3"));
Assert.assertTrue(check(array, "address"));
obj = new Object[] { userProp.getBlah3(), userProp.getAddress().getCity(), "blah1" };
array = AnsiSQLBeanSession.getProperties(obj);
Assert.assertEquals(3, array.length);
Assert.assertTrue(check(array, "blah3"));
Assert.assertTrue(check(array, "blah1"));
Assert.assertTrue(check(array, "address.city"));
obj = new Object[] { userProp.getBlah3(), userProp.getAddress().getFoo1(), "blah1" };
array = AnsiSQLBeanSession.getProperties(obj);
Assert.assertEquals(3, array.length);
Assert.assertTrue(check(array, "blah3"));
Assert.assertTrue(check(array, "blah1"));
Assert.assertTrue(check(array, "address.foo1"));
obj = new Object[] { userProp.getBlah3(), userProp.getAddress().getCity().getId() };
array = AnsiSQLBeanSession.getProperties(obj);
Assert.assertEquals(2, array.length);
Assert.assertTrue(check(array, "blah3"));
Assert.assertTrue(check(array, "address.city.id"));
obj = new Object[] { "blah3", userProp.getAddress().getCity().getId(), userProp.getAddress().getFoo2() };
array = AnsiSQLBeanSession.getProperties(obj);
Assert.assertEquals(3, array.length);
Assert.assertTrue(check(array, "blah3"));
Assert.assertTrue(check(array, "address.city.id"));
Assert.assertTrue(check(array, "address.foo2"));
obj = new Object[] { "blah3", userProp.getAddress().getFoo2(), userProp.getAddress().getCity().getId() };
array = AnsiSQLBeanSession.getProperties(obj);
Assert.assertEquals(3, array.length);
Assert.assertTrue(check(array, "blah3"));
Assert.assertTrue(check(array, "address.city.id"));
Assert.assertTrue(check(array, "address.foo2"));
}
@Test
public void testProxyInstances() {
Address address = PropertiesProxy.create(Address.class);
City city = PropertiesProxy.create(City.class);
address.getFoo1();
city.getId();
address.getFoo2();
city.getName();
//first we have to get the proxy instances, cause getPropertyNames will clear them
Object instances[] = PropertiesProxy.getBeanInstances();
//now we can work with property names...
String properties[] = PropertiesProxy.getPropertyNames();
Assert.assertEquals(properties.length, instances.length);
Assert.assertEquals("foo1", properties[0]);
Assert.assertEquals(address, instances[0]);
Assert.assertEquals("id", properties[1]);
Assert.assertEquals(city, instances[1]);
Assert.assertEquals("foo2", properties[2]);
Assert.assertEquals(address, instances[2]);
Assert.assertEquals("name", properties[3]);
Assert.assertEquals(city, instances[3]);
}
}
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/HasParams.java
New file
0,0 → 1,11
package org.mentabean.sql;
 
import org.mentabean.sql.param.Param;
 
public interface HasParams {
 
public Param[] getParams();
public String build();
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/param/Param.java
New file
0,0 → 1,18
package org.mentabean.sql.param;
 
public interface Param {
 
/**
* Represents the parameters in query. In other words, this method returns a String
* with the expression exactly as will be shown in SQL before its execution.
* @return String
*/
public String paramInQuery();
/**
* The parameter's values
* @return Object[]
*/
public Object[] values();
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/param/ParamSubQuery.java
New file
0,0 → 1,23
package org.mentabean.sql.param;
 
import org.mentabean.jdbc.QueryBuilder.Query;
 
public class ParamSubQuery implements Param {
 
private Query query;
public ParamSubQuery(Query query) {
this.query = query;
}
@Override
public String paramInQuery() {
return "("+query.getSQL()+")";
}
 
@Override
public Object[] values() {
return query.getParamValues().toArray();
}
 
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/param/DefaultParamHandler.java
New file
0,0 → 1,36
package org.mentabean.sql.param;
 
import org.mentabean.jdbc.QueryBuilder;
import org.mentabean.jdbc.QueryBuilder.Alias;
import org.mentabean.jdbc.QueryBuilder.Query;
import org.mentabean.sql.Function;
import org.mentabean.util.PropertiesProxy;
 
public class DefaultParamHandler implements ParamHandler {
 
@Override
public Param findBetter(QueryBuilder builder, Object property) {
if (property instanceof Param)
return (Param) property;
if (property instanceof Query)
return new ParamSubQuery((Query) property);
if (property instanceof Function)
return new ParamFunction((Function) property);
if (PropertiesProxy.hasBeanInstance()) {
Object proxy = PropertiesProxy.getBeanInstances()[0];
for (Alias<?> a : builder.getCreatedAliases()) {
if (a.pxy() == proxy) {
return new ParamField(a, property);
}
}
}
return new ParamValue(property);
}
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/param/ParamField.java
New file
0,0 → 1,23
package org.mentabean.sql.param;
 
import org.mentabean.jdbc.QueryBuilder.Alias;
 
public class ParamField implements Param {
 
private String column;
public ParamField(Alias<?> alias, Object property) {
column = alias.toColumn(property);
}
@Override
public String paramInQuery() {
return column;
}
 
@Override
public Object[] values() {
return null;
}
 
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/param/ParamFunction.java
New file
0,0 → 1,40
package org.mentabean.sql.param;
 
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
 
import org.mentabean.sql.Function;
 
public class ParamFunction implements Param {
 
private Function function;
public ParamFunction(Function function) {
this.function = function;
}
@Override
public String paramInQuery() {
return function.build();
}
 
@Override
public Object[] values() {
List<Object> values = new ArrayList<Object>();
Param[] params = function.getParams();
if (params != null && params.length > 0) {
for (Param p : params) {
if (p.values() != null && p.values().length > 0) {
values.addAll(Arrays.asList(p.values()));
}
}
}
return values.toArray();
}
 
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/param/ParamNative.java
New file
0,0 → 1,21
package org.mentabean.sql.param;
 
public class ParamNative implements Param {
 
private Object param;
public ParamNative(Object param) {
this.param = param;
}
 
@Override
public String paramInQuery() {
return param.toString();
}
 
@Override
public Object[] values() {
return null;
}
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/param/ParamValue.java
New file
0,0 → 1,21
package org.mentabean.sql.param;
 
public class ParamValue implements Param {
 
private Object value;
public ParamValue(Object value) {
this.value = value;
}
@Override
public String paramInQuery() {
return "?";
}
 
@Override
public Object[] values() {
return new Object[] {value};
}
 
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/param/ParamHandler.java
New file
0,0 → 1,9
package org.mentabean.sql.param;
 
import org.mentabean.jdbc.QueryBuilder;
 
public interface ParamHandler {
 
public Param findBetter(QueryBuilder builder, Object property);
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/TableAlias.java
New file
0,0 → 1,112
package org.mentabean.sql;
 
import org.mentabean.BeanConfig;
import org.mentabean.BeanSession;
import org.mentabean.DBField;
import org.mentabean.util.PropertiesProxy;
 
/**
*
* This class encapsulates a proxy to help construct queries that are fully refactorable.
*
* @author Sergio Oliveira Jr.
*
* @param <E>
*/
public class TableAlias<E> {
private final Class<? extends E> beanClass;
private final String prefix;
private final BeanSession session;
private final BeanConfig config;
private final E proxy;
public TableAlias(BeanSession session, BeanConfig config, Class<? extends E> beanClass) {
this(session, config, beanClass, null);
}
public TableAlias(BeanSession session, BeanConfig config, Class<? extends E> beanClass, String prefix) {
this.beanClass = beanClass;
this.prefix = prefix;
this.session = session;
this.config = config;
this.proxy = PropertiesProxy.create(beanClass);
}
@Override
public String toString() {
return "TableAlias [beanClass=" + beanClass.getSimpleName() + ", prefix=" + prefix + "]";
}
 
/**
* Return the db columns of a select statements.
*
* @return the columns to build a select statement
*/
public String columns(Object... props) {
if (prefix != null) {
return session.buildSelect(beanClass, prefix, props);
} else {
return session.buildSelect(beanClass, props);
}
}
public String columnsMinus(Object... props) {
if (prefix != null) {
return session.buildSelectMinus(beanClass, prefix, props);
} else {
return session.buildSelectMinus(beanClass, props);
}
}
/**
* Return the table name.
*
* @return the table name
*/
public String tableName() {
if (prefix != null) {
return config.getTableName() + " " + prefix;
} else {
return config.getTableName();
}
}
/**
* Return the db column name for this bean property.
*
* @param prop this is a filler parameter because a proxy call will be performed!
* @return the db column name of this property
*/
public String column(Object prop) {
String propName = PropertiesProxy.getPropertyName();
DBField field = config.getField(propName);
if (field == null) throw new IllegalStateException("Cannot find field for property \"" + propName + "\" on beanconfig: " + config);
if (prefix != null) {
return prefix + "." + field.getDbName();
} else {
return field.getDbName();
}
}
public E pxy() {
return proxy;
}
public E proxy() {
return proxy;
}
public String prefix() {
return prefix;
}
public Class<? extends E> beanClass() {
return beanClass;
}
}
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/Parametrizable.java
New file
0,0 → 1,40
package org.mentabean.sql;
 
import java.util.ArrayList;
import java.util.List;
 
import org.mentabean.sql.param.Param;
 
public abstract class Parametrizable implements HasParams {
 
protected List<Param> params = new ArrayList<Param>();
public abstract String name();
@Override
public Param[] getParams() {
return params.toArray(new Param[0]);
}
protected Parametrizable addParam(Param param) {
params.add(param);
return this;
}
@Override
public String build() {
StringBuilder sb = new StringBuilder(name());
sb.append(" (");
for (Param param : getParams()) {
sb.append(param.paramInQuery()).append(',');
}
sb.setCharAt(sb.length()-1, ')');
return sb.toString();
}
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/operations/Multiply.java
New file
0,0 → 1,11
package org.mentabean.sql.operations;
 
 
public class Multiply extends Operation {
 
@Override
public String operationSignal() {
return "*";
}
 
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/operations/Operation.java
New file
0,0 → 1,69
package org.mentabean.sql.operations;
 
import java.util.ArrayList;
import java.util.List;
 
import org.mentabean.BeanException;
import org.mentabean.jdbc.QueryBuilder.Alias;
import org.mentabean.jdbc.QueryBuilder.Query;
import org.mentabean.sql.Condition;
import org.mentabean.sql.Function;
import org.mentabean.sql.param.Param;
import org.mentabean.sql.param.ParamField;
import org.mentabean.sql.param.ParamFunction;
import org.mentabean.sql.param.ParamSubQuery;
import org.mentabean.sql.param.ParamValue;
 
public abstract class Operation implements Function, Condition {
 
private List<Param> params = new ArrayList<Param>();
public abstract String operationSignal();
public Operation param(Param p) {
this.params.add(p);
return this;
}
public Operation param(Function function) {
this.params.add(new ParamFunction(function));
return this;
}
public Operation param(Object value) {
this.params.add(new ParamValue(value));
return this;
}
public Operation param(Query query) {
this.params.add(new ParamSubQuery(query));
return this;
}
public Operation param(Alias<?> alias, Object property) {
this.params.add(new ParamField(alias, property));
return this;
}
@Override
public Param[] getParams() {
return params.toArray(new Param[0]);
}
 
@Override
public String build() {
if (params.size() < 2)
throw new BeanException("An operation needs 2 (two) or more parameters");
StringBuilder sb = new StringBuilder();
sb.append("(").append(params.get(0).paramInQuery());
for (int i=1; i < params.size(); i++) {
sb.append(operationSignal()).append(params.get(i).paramInQuery());
}
return sb.append(")").toString();
}
 
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/operations/Divide.java
New file
0,0 → 1,11
package org.mentabean.sql.operations;
 
 
public class Divide extends Operation {
 
@Override
public String operationSignal() {
return "/";
}
 
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/operations/Subtract.java
New file
0,0 → 1,11
package org.mentabean.sql.operations;
 
 
public class Subtract extends Operation {
 
@Override
public String operationSignal() {
return "-";
}
 
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/operations/Add.java
New file
0,0 → 1,11
package org.mentabean.sql.operations;
 
 
public class Add extends Operation {
 
@Override
public String operationSignal() {
return "+";
}
 
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/Sentence.java
New file
0,0 → 1,84
package org.mentabean.sql;
 
import java.sql.ResultSet;
import java.sql.SQLException;
 
import org.mentabean.DBType;
import org.mentabean.jdbc.AnsiSQLBeanSession;
import org.mentabean.jdbc.QueryBuilder.Query;
import org.mentabean.sql.param.Param;
import org.mentabean.sql.param.ParamFunction;
import org.mentabean.sql.param.ParamSubQuery;
import org.mentabean.type.GenericType;
 
public class Sentence implements Function, Condition {
 
private Param param;
private String name, property;
private DBType<?> returnType = new GenericType();
public Sentence(Param param) {
this.param = param;
}
public Sentence(Query query) {
this.param = new ParamSubQuery(query);
}
public Sentence(Function function) {
this.param = new ParamFunction(function);
}
/**
* Specify the property of <code>FROM</code> alias that will be populated with this sentence
* @param property
* @return this
*/
public Sentence fromProperty(Object property) {
this.property = AnsiSQLBeanSession.getProperties(new Object[] {property})[0];
if (name == null) {
name = this.property.replace('.', '_');
}
return this;
}
public Sentence name(String name) {
this.name = name;
return this;
}
public Sentence returnType(DBType<?> type) {
this.returnType = type;
return this;
}
@SuppressWarnings("unchecked")
public <T> T getValue(ResultSet rset) throws SQLException {
return (T) returnType.getFromResultSet(rset, name);
}
public DBType<?> getReturnType() {
return returnType;
}
public String getProperty() {
return property;
}
public String getName() {
return name;
}
@Override
public Param[] getParams() {
return new Param[] {param};
}
 
@Override
public String build() {
return "("+param.paramInQuery()+")";
}
 
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/Function.java
New file
0,0 → 1,5
package org.mentabean.sql;
 
public interface Function extends HasParams {
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/Condition.java
New file
0,0 → 1,5
package org.mentabean.sql;
 
public interface Condition extends HasParams {
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/functions/Substring.java
New file
0,0 → 1,43
package org.mentabean.sql.functions;
 
import org.mentabean.sql.Function;
import org.mentabean.sql.Parametrizable;
import org.mentabean.sql.param.Param;
import org.mentabean.sql.param.ParamFunction;
import org.mentabean.sql.param.ParamValue;
 
public class Substring extends Parametrizable implements Function {
 
private Param str, beginIndex, endIndex;
public Substring(Param str) {
this.str = str;
}
public Substring endIndex(Param param) {
endIndex = param;
return this;
}
public Substring beginIndex(Param param) {
beginIndex = param;
return this;
}
@Override
public Param[] getParams() {
if (beginIndex == null)
beginIndex = new ParamValue(0);
if (endIndex == null)
endIndex = new ParamFunction(new Length(str));
return new Param[] {str, beginIndex, endIndex};
}
@Override
public String name() {
return "SUBSTRING";
}
 
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/functions/Length.java
New file
0,0 → 1,18
package org.mentabean.sql.functions;
 
import org.mentabean.sql.Function;
import org.mentabean.sql.Parametrizable;
import org.mentabean.sql.param.Param;
 
public class Length extends Parametrizable implements Function {
 
public Length(Param param) {
addParam(param);
}
@Override
public String name() {
return "LENGTH";
}
 
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/functions/Min.java
New file
0,0 → 1,18
package org.mentabean.sql.functions;
 
import org.mentabean.sql.Function;
import org.mentabean.sql.Parametrizable;
import org.mentabean.sql.param.Param;
 
public class Min extends Parametrizable implements Function {
 
public Min(Param param) {
addParam(param);
}
@Override
public String name() {
return "MIN";
}
 
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/functions/Sum.java
New file
0,0 → 1,18
package org.mentabean.sql.functions;
 
import org.mentabean.sql.Function;
import org.mentabean.sql.Parametrizable;
import org.mentabean.sql.param.Param;
 
public class Sum extends Parametrizable implements Function {
 
public Sum(Param param) {
addParam(param);
}
@Override
public String name() {
return "SUM";
}
 
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/functions/Max.java
New file
0,0 → 1,18
package org.mentabean.sql.functions;
 
import org.mentabean.sql.Function;
import org.mentabean.sql.Parametrizable;
import org.mentabean.sql.param.Param;
 
public class Max extends Parametrizable implements Function {
 
public Max(Param param) {
addParam(param);
}
@Override
public String name() {
return "MAX";
}
 
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/functions/Count.java
New file
0,0 → 1,18
package org.mentabean.sql.functions;
 
import org.mentabean.sql.Function;
import org.mentabean.sql.Parametrizable;
import org.mentabean.sql.param.Param;
 
public class Count extends Parametrizable implements Function {
 
public Count(Param param) {
addParam(param);
}
@Override
public String name() {
return "COUNT";
}
 
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/functions/Lower.java
New file
0,0 → 1,25
package org.mentabean.sql.functions;
 
import org.mentabean.sql.Function;
import org.mentabean.sql.Parametrizable;
import org.mentabean.sql.param.Param;
 
public class Lower extends Parametrizable implements Function {
 
private Param param;
public Lower(Param param) {
this.param = param;
}
@Override
public Param[] getParams() {
return new Param[] {param};
}
@Override
public String name() {
return "LOWER";
}
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/functions/Nullif.java
New file
0,0 → 1,32
package org.mentabean.sql.functions;
 
import org.mentabean.sql.Function;
import org.mentabean.sql.Parametrizable;
import org.mentabean.sql.param.Param;
import org.mentabean.sql.param.ParamValue;
 
public class Nullif extends Parametrizable implements Function {
 
private Param p1, p2;
public Nullif(Param p1, Param p2) {
this.p1 = p1;
this.p2 = p2;
}
public Nullif(Object p1, Object p2) {
this.p1 = new ParamValue(p1);
this.p2 = new ParamValue(p2);
}
@Override
public Param[] getParams() {
return new Param[] {p1, p2};
}
@Override
public String name() {
return "NULLIF";
}
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/functions/Upper.java
New file
0,0 → 1,18
package org.mentabean.sql.functions;
 
import org.mentabean.sql.Function;
import org.mentabean.sql.Parametrizable;
import org.mentabean.sql.param.Param;
 
public class Upper extends Parametrizable implements Function {
 
public Upper(Param param) {
addParam(param);
}
@Override
public String name() {
return "UPPER";
}
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/functions/Avg.java
New file
0,0 → 1,18
package org.mentabean.sql.functions;
 
import org.mentabean.sql.Function;
import org.mentabean.sql.Parametrizable;
import org.mentabean.sql.param.Param;
 
public class Avg extends Parametrizable implements Function {
 
public Avg(Param param) {
addParam(param);
}
@Override
public String name() {
return "AVG";
}
 
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/functions/Coalesce.java
New file
0,0 → 1,20
package org.mentabean.sql.functions;
 
import org.mentabean.sql.Function;
import org.mentabean.sql.Parametrizable;
import org.mentabean.sql.param.Param;
 
public class Coalesce extends Parametrizable implements Function {
 
@Override
public String name() {
return "COALESCE";
}
@Override
public Coalesce addParam(Param param) {
super.addParam(param);
return this;
}
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/conditions/GreaterThanEquals.java
New file
0,0 → 1,20
package org.mentabean.sql.conditions;
 
import org.mentabean.sql.param.Param;
 
public class GreaterThanEquals extends SimpleComparison {
 
public GreaterThanEquals(Param param) {
super(param);
}
public GreaterThanEquals(Object param) {
super(param);
}
 
@Override
public String comparisonSignal() {
return ">=";
}
 
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/conditions/LessThan.java
New file
0,0 → 1,20
package org.mentabean.sql.conditions;
 
import org.mentabean.sql.param.Param;
 
public class LessThan extends SimpleComparison {
 
public LessThan(Param param) {
super(param);
}
public LessThan(Object param) {
super(param);
}
 
@Override
public String comparisonSignal() {
return "<";
}
 
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/conditions/GreaterThan.java
New file
0,0 → 1,20
package org.mentabean.sql.conditions;
 
import org.mentabean.sql.param.Param;
 
public class GreaterThan extends SimpleComparison {
 
public GreaterThan(Param param) {
super(param);
}
public GreaterThan(Object param) {
super(param);
}
 
@Override
public String comparisonSignal() {
return ">";
}
 
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/conditions/Like.java
New file
0,0 → 1,21
package org.mentabean.sql.conditions;
 
import org.mentabean.sql.param.Param;
 
public class Like extends SimpleComparison {
 
public Like(Param param) {
super(param);
}
public Like(Object value) {
super(value);
}
 
@Override
public String comparisonSignal() {
return "LIKE";
}
 
 
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/conditions/SimpleComparison.java
New file
0,0 → 1,31
package org.mentabean.sql.conditions;
 
import org.mentabean.sql.Condition;
import org.mentabean.sql.param.Param;
import org.mentabean.sql.param.ParamValue;
 
public abstract class SimpleComparison implements Condition {
 
private Param param;
public abstract String comparisonSignal();
public SimpleComparison(Param param) {
this.param = param;
}
public SimpleComparison(Object value) {
this.param = new ParamValue(value);
}
@Override
public Param[] getParams() {
return new Param[] {param};
}
 
@Override
public String build() {
return comparisonSignal()+" "+param.paramInQuery();
}
 
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/conditions/NotLike.java
New file
0,0 → 1,21
package org.mentabean.sql.conditions;
 
import org.mentabean.sql.param.Param;
 
public class NotLike extends SimpleComparison {
 
public NotLike(Param param) {
super(param);
}
public NotLike(Object value) {
super(value);
}
 
@Override
public String comparisonSignal() {
return "NOT LIKE";
}
 
 
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/conditions/In.java
New file
0,0 → 1,23
package org.mentabean.sql.conditions;
 
import org.mentabean.sql.Condition;
import org.mentabean.sql.Parametrizable;
import org.mentabean.sql.param.Param;
 
public class In extends Parametrizable implements Condition {
@Override
public String name() {
return "IN";
}
public In (Param param) {
addParam(param);
}
@Override
public Parametrizable addParam(Param param) {
return super.addParam(param);
}
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/conditions/NotIn.java
New file
0,0 → 1,16
package org.mentabean.sql.conditions;
 
import org.mentabean.sql.param.Param;
 
public class NotIn extends In {
 
public NotIn(Param param) {
super(param);
}
 
@Override
public String name() {
return "NOT IN";
}
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/conditions/Between.java
New file
0,0 → 1,54
package org.mentabean.sql.conditions;
 
import org.mentabean.sql.param.Param;
 
public class Between extends AbstractBetween {
 
private boolean not;
public Between(Param begin, Param end) {
super(begin, end);
}
public Between(Object beginValue, Object endValue) {
super(beginValue, endValue);
}
public Between not() {
not = true;
return this;
}
@Override
public String build() {
if (begin == null && end == null) {
return "";
}
if (begin == null) {
if (not) {
return new GreaterThan(end).build();
}
return new LessThanEquals(end).build();
}
if (end == null) {
if (not) {
return new LessThan(begin).build();
}
return new GreaterThanEquals(begin).build();
}
String str = "BETWEEN "+begin.paramInQuery()+" AND "+end.paramInQuery();
return not ? "NOT "+str : str;
}
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/conditions/Equals.java
New file
0,0 → 1,35
package org.mentabean.sql.conditions;
 
import org.mentabean.sql.Condition;
import org.mentabean.sql.param.Param;
import org.mentabean.sql.param.ParamValue;
 
public class Equals implements Condition {
 
protected Param param;
public Equals(Object value) {
if (value != null) {
this.param = new ParamValue(value);
}
}
public Equals(Param param) {
this.param = param;
}
 
@Override
public Param[] getParams() {
return new Param[] {param};
}
 
@Override
public String build() {
if (param == null)
return "IS NULL";
return "= "+param.paramInQuery();
}
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/conditions/NotBetween.java
New file
0,0 → 1,31
package org.mentabean.sql.conditions;
 
import org.mentabean.sql.param.Param;
 
public class NotBetween extends AbstractBetween {
 
public NotBetween(Param begin, Param end) {
super(begin, end);
}
public NotBetween(Object beginValue, Object endValue) {
super(beginValue, endValue);
}
 
@Override
public String build() {
if (begin == null && end == null)
return "";
if (begin == null) {
return new GreaterThan(end).build();
}
if (end == null) {
return new LessThan(begin).build();
}
return "NOT BETWEEN "+begin.paramInQuery()+" AND "+end.paramInQuery();
}
 
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/conditions/NotEquals.java
New file
0,0 → 1,24
package org.mentabean.sql.conditions;
 
import org.mentabean.sql.param.Param;
 
public class NotEquals extends Equals {
 
public NotEquals(Param param) {
super(param);
}
public NotEquals(Object param) {
super(param);
}
 
@Override
public String build() {
if (param == null)
return "IS NOT NULL";
return "<> "+param.paramInQuery();
}
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/conditions/LessThanEquals.java
New file
0,0 → 1,20
package org.mentabean.sql.conditions;
 
import org.mentabean.sql.param.Param;
 
public class LessThanEquals extends SimpleComparison {
 
public LessThanEquals(Param param) {
super(param);
}
public LessThanEquals(Object param) {
super(param);
}
 
@Override
public String comparisonSignal() {
return "<=";
}
 
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/sql/conditions/AbstractBetween.java
New file
0,0 → 1,28
package org.mentabean.sql.conditions;
 
import org.mentabean.sql.Condition;
import org.mentabean.sql.param.Param;
import org.mentabean.sql.param.ParamValue;
 
public abstract class AbstractBetween implements Condition {
protected Param begin, end;
public AbstractBetween(Param begin, Param end) {
this.begin = begin;
this.end = end;
}
public AbstractBetween(Object beginValue, Object endValue) {
if (beginValue != null)
begin = new ParamValue(beginValue);
if (endValue != null)
end = new ParamValue(endValue);
}
@Override
public Param[] getParams() {
return new Param[] {begin, end};
}
 
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/BeanManager.java
New file
0,0 → 1,105
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean;
 
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
 
import org.mentabean.util.DefaultProxy;
import org.mentabean.util.PropertiesProxy;
 
/**
* The manager that keeps track of the configuration for all beans.
*
* @author sergio.oliveira.jr@gmail.com
*/
public class BeanManager {
 
private final Map<Class<? extends Object>, BeanConfig> beans = new HashMap<Class<? extends Object>, BeanConfig>();
public BeanManager(PropertiesProxy proxy) {
PropertiesProxy.INSTANCE = proxy == null ? new DefaultProxy() : proxy;
}
public BeanManager() {
this(null);
}
 
/**
* Add a bean configuration.
*
* @param bc
* The bean configuration to add.
* @return The BeanConfig added (Fluent API)
*/
public BeanConfig bean(final BeanConfig bc) {
 
if (beans.containsKey(bc.getBeanClass())) {
throw new IllegalStateException("A configuration was already added for this bean ("+bc.getBeanClass()+")");
}
 
beans.put(bc.getBeanClass(), bc);
 
return bc;
}
 
/**
* Add a bean configuration.
*
* @param bc
* The bean configuration to add.
*/
public void addBeanConfig(final BeanConfig bc) {
bean(bc);
}
 
/**
* Creates a bean configuration and add to this manager.
*
* @param beanClass
* The bean class
* @param tableName
* The table name where the bean properties will be stored.
* @return The BeanConfig created (Fluent API)
*/
public BeanConfig bean(final Class<? extends Object> beanClass, final String tableName) {
 
return bean(new BeanConfig(beanClass, tableName));
}
 
/**
* Get the bean configuration for the given bean class.
*
* @param beanClass
* The bean class
* @return The bean configuration for this bean or null if it was not defined
*/
public BeanConfig getBeanConfig(final Class<? extends Object> beanClass) {
 
return beans.get(beanClass);
}
 
public Set<BeanConfig> getBeanConfigs() {
Set<BeanConfig> all = new HashSet<BeanConfig>();
all.addAll(beans.values());
return all;
}
}
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/event/TriggerAdapter.java
New file
0,0 → 1,35
package org.mentabean.event;
 
public abstract class TriggerAdapter implements TriggerListener {
 
@Override
public void beforeInsert(TriggerEvent evt) {
}
 
@Override
public void afterInsert(TriggerEvent evt) {
}
 
@Override
public void beforeUpdate(TriggerEvent evt) {
}
 
@Override
public void afterUpdate(TriggerEvent evt) {
}
 
@Override
public void beforeDelete(TriggerEvent evt) {
}
 
@Override
public void afterDelete(TriggerEvent evt) {
}
 
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/event/TriggerEvent.java
New file
0,0 → 1,24
package org.mentabean.event;
 
import org.mentabean.BeanSession;
 
public class TriggerEvent {
 
private final BeanSession session;
private final Object bean;
public TriggerEvent(final BeanSession session, final Object bean) {
this.session = session;
this.bean = bean;
}
 
public BeanSession getSession() {
return session;
}
 
@SuppressWarnings("unchecked")
public <E> E getBean() {
return (E) bean;
}
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/event/TriggerListener.java
New file
0,0 → 1,17
package org.mentabean.event;
 
public interface TriggerListener {
 
public void beforeInsert(TriggerEvent evt);
public void afterInsert(TriggerEvent evt);
public void beforeUpdate(TriggerEvent evt);
public void afterUpdate(TriggerEvent evt);
public void beforeDelete(TriggerEvent evt);
public void afterDelete(TriggerEvent evt);
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/event/TriggerDispatcher.java
New file
0,0 → 1,98
package org.mentabean.event;
 
import java.util.ArrayList;
import java.util.List;
 
public class TriggerDispatcher {
 
private final List<TriggerListener> triggers = new ArrayList<TriggerListener>();
public void addTrigger(TriggerListener trigger) {
synchronized (triggers) {
if (!triggers.contains(trigger)) {
triggers.add(trigger);
}
}
}
public void removeTrigger(TriggerListener trigger) {
synchronized (triggers) {
triggers.remove(trigger);
}
}
public void dispatch(Type type, TriggerEvent evt) {
type.dispatchAll(triggers, evt);
}
public enum Type {
BEFORE_INSERT {
 
@Override
void fire(TriggerListener l, TriggerEvent evt) {
l.beforeInsert(evt);
}
},
AFTER_INSERT {
 
@Override
void fire(TriggerListener l, TriggerEvent evt) {
l.afterInsert(evt);
}
},
BEFORE_UPDATE {
 
@Override
void fire(TriggerListener l, TriggerEvent evt) {
l.beforeUpdate(evt);
}
},
AFTER_UPDATE {
 
@Override
void fire(TriggerListener l, TriggerEvent evt) {
l.afterUpdate(evt);
}
},
BEFORE_DELETE {
 
@Override
void fire(TriggerListener l, TriggerEvent evt) {
l.beforeDelete(evt);
}
},
AFTER_DELETE {
 
@Override
void fire(TriggerListener l, TriggerEvent evt) {
l.afterDelete(evt);
}
};
public void dispatchAll(List<TriggerListener> list, TriggerEvent evt) {
for (TriggerListener l : list) {
fire(l, evt);
}
}
abstract void fire(TriggerListener l, TriggerEvent evt);
}
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/type/IntegerType.java
New file
0,0 → 1,94
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.type;
 
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
 
import org.mentabean.DBType;
 
public class IntegerType implements DBType<Integer> {
 
private boolean canBeNull = true;
 
@Override
public boolean canBeNull() {
return canBeNull;
}
 
public IntegerType nullable(boolean flag) {
IntegerType d = new IntegerType();
d.canBeNull = flag;
return d;
}
 
@Override
public String getAnsiType() {
return "integer";
}
 
@Override
public String toString() {
 
return this.getClass().getSimpleName();
}
 
@Override
public Integer getFromResultSet(final ResultSet rset, final int index) throws SQLException {
 
Integer x = rset.getInt(index);
if (rset.wasNull()) {
return null;
}
return x;
}
 
@Override
public Integer getFromResultSet(final ResultSet rset, final String field) throws SQLException {
 
Integer x = rset.getInt(field);
if (rset.wasNull()) {
return null;
}
return x;
}
 
@Override
public Class<? extends Object> getTypeClass() {
 
return Integer.class;
}
 
@Override
public void bindToStmt(final PreparedStatement stmt, final int index, final Integer value) throws SQLException {
 
if (value == null) {
 
stmt.setNull(index, java.sql.Types.INTEGER);
 
} else {
 
stmt.setInt(index, value.intValue());
}
}
}
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/type/TimeType.java
New file
0,0 → 1,89
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.type;
 
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
 
import org.mentabean.DBType;
 
public class TimeType implements DBType<java.util.Date> {
 
private boolean canBeNull = true;
 
@Override
public boolean canBeNull() {
return canBeNull;
}
 
public TimeType nullable(boolean flag) {
TimeType d = new TimeType();
d.canBeNull = flag;
return d;
}
 
@Override
public String getAnsiType() {
return "time";
}
 
@Override
public String toString() {
 
return this.getClass().getSimpleName();
}
 
@Override
public java.util.Date getFromResultSet(final ResultSet rset, final int index) throws SQLException {
 
return rset.getTime(index);
}
 
@Override
public java.util.Date getFromResultSet(final ResultSet rset, final String field) throws SQLException {
 
return rset.getTime(field);
}
 
@Override
public Class<? extends Object> getTypeClass() {
 
return java.util.Date.class;
}
 
@Override
public void bindToStmt(final PreparedStatement stmt, final int index, final java.util.Date value) throws SQLException {
 
if (value == null) {
 
stmt.setTime(index, null);
 
} else if (value instanceof java.sql.Time) {
 
final java.sql.Time t = (java.sql.Time) value;
 
stmt.setTime(index, t);
 
} else {
 
stmt.setTime(index, new java.sql.Time(value.getTime()));
 
}
}
}
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/type/NowOnInsertAndUpdateTimestampType.java
New file
0,0 → 1,35
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.type;
 
public class NowOnInsertAndUpdateTimestampType extends TimestampType {
 
@Override
public boolean canBeNull() {
return false;
}
 
@Override
public NowOnInsertAndUpdateTimestampType nullable(boolean flag) {
if (flag) {
throw new UnsupportedOperationException("NowOnInsertAndUpdateTimestampType can never be null!");
}
return this;
}
 
}
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/type/LongType.java
New file
0,0 → 1,94
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.type;
 
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
 
import org.mentabean.DBType;
 
public class LongType implements DBType<Long> {
 
private boolean canBeNull = true;
 
@Override
public boolean canBeNull() {
return canBeNull;
}
 
public LongType nullable(boolean flag) {
LongType d = new LongType();
d.canBeNull = flag;
return d;
}
 
@Override
public String getAnsiType() {
return "integer"; // most database will not support BIGINT
}
 
@Override
public String toString() {
 
return this.getClass().getSimpleName();
}
 
@Override
public Long getFromResultSet(final ResultSet rset, final int index) throws SQLException {
 
Long x = rset.getLong(index);
if (rset.wasNull()) {
return null;
}
return x;
}
 
@Override
public Long getFromResultSet(final ResultSet rset, final String field) throws SQLException {
 
Long x = rset.getLong(field);
if (rset.wasNull()) {
return null;
}
return x;
}
 
@Override
public Class<? extends Object> getTypeClass() {
 
return Long.class;
}
 
@Override
public void bindToStmt(final PreparedStatement stmt, final int index, final Long value) throws SQLException {
 
if (value == null) {
 
stmt.setNull(index, java.sql.Types.BIGINT);
 
} else {
 
stmt.setLong(index, value.longValue());
}
}
}
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/type/EnumValueType.java
New file
0,0 → 1,131
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.type;
 
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
 
import org.mentabean.DBType;
 
public class EnumValueType implements DBType<Enum<?>>, SizedType {
 
private final Class<? extends Enum<?>> enumType;
private final int size;
 
private boolean canBeNull = false;
 
@Override
public boolean canBeNull() {
return canBeNull;
}
 
public EnumValueType nullable(boolean flag) {
EnumValueType d = new EnumValueType(enumType);
d.canBeNull = flag;
return d;
}
 
public EnumValueType(final Class<? extends Enum<?>> enumType) {
 
this.enumType = enumType;
this.size = calcSize();
}
 
@Override
public String getAnsiType() {
return "varchar";
}
 
public EnumValueType size(int size) {
throw new UnsupportedOperationException("Cannot set the size on a " + this);
}
 
@Override
public int getSize() {
return size;
}
 
private int calcSize() {
Enum<?>[] all = enumType.getEnumConstants();
int max = 0;
for (Enum<?> o : all) {
max = Math.max(max, o.name().length());
}
return max;
}
 
@Override
public String toString() {
 
return this.getClass().getSimpleName() + ": " + enumType.getSimpleName();
}
 
@Override
public Enum<?> getFromResultSet(final ResultSet rset, final int index) throws SQLException {
 
final String s = rset.getString(index);
 
if (s == null) {
return null;
}
 
return Enum.valueOf((Class) enumType, s);
 
}
 
@Override
public Enum<?> getFromResultSet(final ResultSet rset, final String field) throws SQLException {
 
final String s = rset.getString(field);
 
if (s == null) {
return null;
}
 
return Enum.valueOf((Class) enumType, s);
 
}
 
@Override
public Class<? extends Object> getTypeClass() {
 
return enumType;
}
 
@Override
public void bindToStmt(final PreparedStatement stmt, final int index, final Enum<?> value) throws SQLException {
 
if (value == null) {
 
stmt.setString(index, null);
 
//Support for overwritten enums (superclass on left)
} else if (enumType.isAssignableFrom(value.getClass())) {
 
final String s = value.name();
 
stmt.setString(index, s);
 
} else {
 
throw new IllegalArgumentException("Value '"+value+"' from '"+value.getClass()+"' is not an enum!");
}
 
}
}
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/type/ByteArrayType.java
New file
0,0 → 1,76
package org.mentabean.type;
 
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
 
import org.mentabean.DBType;
 
/**
* ByteArrayType that uses a get/setBytes from ResultSet/PreparedStatement respectively
*
* @author erico
*
*/
public class ByteArrayType implements DBType<byte[]> {
 
private boolean canBeNull = true;
 
@Override
public boolean canBeNull() {
return canBeNull;
}
 
public ByteArrayType nullable(boolean flag) {
ByteArrayType d = new ByteArrayType();
d.canBeNull = flag;
return d;
}
 
@Override
public String getAnsiType() {
return "blob";
}
 
@Override
public String toString() {
 
return ByteArrayType.class.getSimpleName();
}
 
@Override
public byte[] getFromResultSet(final ResultSet rset, final int index) throws SQLException {
 
byte[] x = rset.getBytes(index);
if (rset.wasNull()) {
return null;
}
return x;
}
 
@Override
public byte[] getFromResultSet(final ResultSet rset, final String field) throws SQLException {
 
byte[] x = rset.getBytes(field);
if (rset.wasNull()) {
return null;
}
return x;
}
 
@Override
public Class<? extends Object> getTypeClass() {
 
return byte[].class;
}
 
@Override
public void bindToStmt(final PreparedStatement stmt, final int index, final byte[] value) throws SQLException {
 
stmt.setBytes(index, value);
}
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/type/TimestampType.java
New file
0,0 → 1,89
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.type;
 
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
 
import org.mentabean.DBType;
 
public class TimestampType implements DBType<java.util.Date> {
 
private boolean canBeNull = true;
 
@Override
public boolean canBeNull() {
return canBeNull;
}
 
public TimestampType nullable(boolean flag) {
TimestampType d = new TimestampType();
d.canBeNull = flag;
return d;
}
 
@Override
public String getAnsiType() {
return "timestamp";
}
 
@Override
public String toString() {
 
return this.getClass().getSimpleName();
}
 
@Override
public java.util.Date getFromResultSet(final ResultSet rset, final int index) throws SQLException {
 
return rset.getTimestamp(index);
}
 
@Override
public java.util.Date getFromResultSet(final ResultSet rset, final String field) throws SQLException {
 
return rset.getTimestamp(field);
}
 
@Override
public Class<? extends Object> getTypeClass() {
 
return java.util.Date.class;
}
 
@Override
public void bindToStmt(final PreparedStatement stmt, final int index, final java.util.Date value) throws SQLException {
 
if (value == null) {
 
stmt.setTimestamp(index, null);
 
} else if (value instanceof java.sql.Timestamp) {
 
final java.sql.Timestamp t = (java.sql.Timestamp) value;
 
stmt.setTimestamp(index, t);
 
} else {
 
stmt.setTimestamp(index, new java.sql.Timestamp(value.getTime()));
 
}
}
}
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/type/FloatType.java
New file
0,0 → 1,95
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.type;
 
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
 
import org.mentabean.DBType;
 
public class FloatType implements DBType<Float> {
 
private boolean canBeNull = true;
 
@Override
public boolean canBeNull() {
return canBeNull;
}
 
public FloatType nullable(boolean flag) {
FloatType d = new FloatType();
d.canBeNull = flag;
return d;
}
 
@Override
public String getAnsiType() {
return "float";
}
 
@Override
public String toString() {
 
return this.getClass().getSimpleName();
}
 
@Override
public Float getFromResultSet(final ResultSet rset, final int index) throws SQLException {
 
Float x = rset.getFloat(index);
if (rset.wasNull()) {
return null;
}
return x;
}
 
@Override
public Float getFromResultSet(final ResultSet rset, final String field) throws SQLException {
 
Float x = rset.getFloat(field);
if (rset.wasNull()) {
return null;
}
return x;
}
 
@Override
public Class<? extends Object> getTypeClass() {
 
return Float.class;
}
 
@Override
public void bindToStmt(final PreparedStatement stmt, final int index, final Float value) throws SQLException {
 
if (value == null || value.isNaN() || value.isInfinite()) {
 
stmt.setNull(index, java.sql.Types.FLOAT);
 
} else {
 
stmt.setFloat(index, value.floatValue());
 
}
}
}
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/type/StringType.java
New file
0,0 → 1,97
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.type;
 
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
 
import org.mentabean.DBType;
 
public class StringType implements DBType<String>, SizedType {
 
private int size = DEFAULT_SIZE;
 
private boolean canBeNull = true;
 
@Override
public boolean canBeNull() {
return canBeNull;
}
 
public StringType nullable(boolean flag) {
StringType d = new StringType();
d.canBeNull = flag;
d.size = this.size;
return d;
}
 
@Override
public String getAnsiType() {
return "varchar"; // if your database do not support that you are in trouble !!!
}
 
@Override
public String toString() {
 
return this.getClass().getSimpleName();
}
 
public StringType size(int size) {
// clone so we can use this with DBTypes (cleaner API)
StringType clone = new StringType();
clone.size = size;
return clone;
}
 
@Override
public int getSize() {
return size;
}
 
@Override
public String getFromResultSet(final ResultSet rset, final int index) throws SQLException {
 
return rset.getString(index);
}
 
@Override
public String getFromResultSet(final ResultSet rset, final String field) throws SQLException {
 
return rset.getString(field);
}
 
@Override
public Class<? extends Object> getTypeClass() {
 
return String.class;
}
 
@Override
public void bindToStmt(final PreparedStatement stmt, final int index, final String value) throws SQLException {
 
if (value == null) {
 
stmt.setString(index, null);
 
} else {
 
stmt.setString(index, value);
}
}
}
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/type/BooleanStringType.java
New file
0,0 → 1,172
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.type;
 
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
 
import org.mentabean.BeanException;
import org.mentabean.DBType;
 
public class BooleanStringType implements DBType<Boolean>, SizedType {
 
private final String sTrue;
private final String sFalse;
private boolean canBeNull = true;
 
public BooleanStringType() {
this("T", "F");
}
 
public BooleanStringType(final String sTrue, final String sFalse) {
this.sTrue = sTrue;
this.sFalse = sFalse;
}
public static BooleanStringType values(String sTrue, String sFalse) {
return new BooleanStringType(sTrue, sFalse);
}
 
@Override
public boolean canBeNull() {
return canBeNull;
}
 
@Override
public String getAnsiType() {
return "varchar";
}
 
public BooleanStringType nullable(boolean flag) {
// clone:
BooleanStringType b = new BooleanStringType(this.sTrue, this.sFalse);
b.canBeNull = flag;
return b;
}
 
public BooleanStringType size(int size) {
throw new UnsupportedOperationException("Cannot set size of a " + this);
}
 
@Override
public int getSize() {
return Math.max(sTrue.length(), sFalse.length());
}
 
@Override
public boolean equals(final Object obj) {
 
if (obj instanceof BooleanStringType) {
 
final BooleanStringType bt = (BooleanStringType) obj;
 
if (bt.sTrue.equals(this.sTrue) && bt.sFalse.equals(this.sFalse)) {
 
return true;
}
}
 
return false;
}
 
@Override
public String toString() {
 
return this.getClass().getSimpleName();
}
 
protected Boolean getBooleanValue(final String s) {
 
if (s.equals(sTrue)) {
return true;
}
 
if (s.equals(sFalse)) {
return false;
}
 
return null;
}
 
private static Boolean getBoolValue(final boolean b) {
 
if (b) {
return Boolean.TRUE;
}
 
return Boolean.FALSE;
}
 
@Override
public Boolean getFromResultSet(final ResultSet rset, final int index) throws SQLException {
 
final String s = rset.getString(index);
if (rset.wasNull() || s == null) {
return null;
}
 
final Boolean b = getBooleanValue(s);
if (b == null) {
throw new BeanException("Don't know how to convert String to boolean:" + s);
}
 
return getBoolValue(b);
}
 
@Override
public Boolean getFromResultSet(final ResultSet rset, final String field) throws SQLException {
 
final String s = rset.getString(field);
if (rset.wasNull() || s == null) {
return null;
}
 
final Boolean b = getBooleanValue(s);
if (b == null) {
throw new BeanException("Don't know how to convert String to boolean: " + s);
}
 
return getBoolValue(b);
}
 
@Override
public Class<? extends Object> getTypeClass() {
 
return Boolean.class;
}
 
@Override
public void bindToStmt(final PreparedStatement stmt, final int index, final Boolean value) throws SQLException {
 
if (value == null) {
 
stmt.setString(index, null);
 
} else {
 
final String s = value ? sTrue : sFalse;
 
stmt.setString(index, s);
}
}
}
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/type/SequenceType.java
New file
0,0 → 1,86
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.type;
 
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
 
import org.mentabean.DBType;
 
public class SequenceType implements DBType<Number> {
 
@Override
public boolean canBeNull() {
return false;
}
 
@Override
public String toString() {
 
return this.getClass().getSimpleName();
}
 
@Override
public String getAnsiType() {
return "integer";
}
 
@Override
public Long getFromResultSet(final ResultSet rset, final int index) throws SQLException {
 
Long x = rset.getLong(index);
if (rset.wasNull()) {
return null;
}
return x;
}
 
@Override
public Long getFromResultSet(final ResultSet rset, final String field) throws SQLException {
 
Long x = rset.getLong(field);
if (rset.wasNull()) {
return null;
}
return x;
}
 
@Override
public Class<? extends Object> getTypeClass() {
 
return Long.class;
}
 
@Override
public void bindToStmt(final PreparedStatement stmt, final int index, final Number value) throws SQLException {
 
if (value == null) {
 
stmt.setNull(index, java.sql.Types.INTEGER);
 
} else {
 
stmt.setLong(index, value.longValue());
}
}
}
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/type/NowOnInsertTimestampType.java
New file
0,0 → 1,36
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.type;
 
public class NowOnInsertTimestampType extends TimestampType {
 
private boolean canBeNull = true;
 
@Override
public boolean canBeNull() {
return canBeNull;
}
 
@Override
public NowOnInsertTimestampType nullable(boolean flag) {
NowOnInsertTimestampType d = new NowOnInsertTimestampType();
d.canBeNull = flag;
return d;
}
 
}
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/type/EnumIdTypeFactory.java
New file
0,0 → 1,21
package org.mentabean.type;
 
public class EnumIdTypeFactory {
private static EnumIdTypeFactory instance = null;
private EnumIdTypeFactory() {
 
}
public static EnumIdTypeFactory getInstance() {
if (instance == null) {
instance = new EnumIdTypeFactory();
}
return instance;
}
public EnumIdType from(final Class<? extends Enum<?>> enumType) {
return new EnumIdType(enumType);
}
}
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/type/DoubleType.java
New file
0,0 → 1,94
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.type;
 
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
 
import org.mentabean.DBType;
 
public class DoubleType implements DBType<Double> {
 
private boolean canBeNull = true;
 
@Override
public boolean canBeNull() {
return canBeNull;
}
 
public DoubleType nullable(boolean flag) {
DoubleType d = new DoubleType();
d.canBeNull = flag;
return d;
}
 
@Override
public String getAnsiType() {
return "double precision";
}
 
@Override
public String toString() {
 
return this.getClass().getSimpleName();
}
 
@Override
public Double getFromResultSet(final ResultSet rset, final int index) throws SQLException {
 
Double x = rset.getDouble(index);
if (rset.wasNull()) {
return null;
}
return x;
}
 
@Override
public Double getFromResultSet(final ResultSet rset, final String field) throws SQLException {
 
Double x = rset.getDouble(field);
if (rset.wasNull()) {
return null;
}
return x;
}
 
@Override
public Class<? extends Object> getTypeClass() {
 
return Double.class;
}
 
@Override
public void bindToStmt(final PreparedStatement stmt, final int index, final Double value) throws SQLException {
 
if (value == null || value.isNaN() || value.isInfinite()) {
 
stmt.setNull(index, java.sql.Types.DOUBLE);
 
} else {
 
stmt.setDouble(index, value.doubleValue());
}
}
}
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/type/GenericType.java
New file
0,0 → 1,76
package org.mentabean.type;
 
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
 
import org.mentabean.DBType;
 
/**
* Generic type that uses a get/setObject from ResultSet/PreparedStatement respectively
* <br><br><i>Note this class must NOT be used to create tables. Databases doesn't have a generic type</i>
* @author erico
*
*/
public class GenericType implements DBType<Object> {
 
private boolean canBeNull = true;
 
@Override
public boolean canBeNull() {
return canBeNull;
}
 
public GenericType nullable(boolean flag) {
GenericType d = new GenericType();
d.canBeNull = flag;
return d;
}
 
@Override
public String getAnsiType() {
return null; // we don't have generic types in database level
}
 
@Override
public String toString() {
 
return this.getClass().getSimpleName();
}
 
@Override
public Object getFromResultSet(final ResultSet rset, final int index) throws SQLException {
 
Object x = rset.getObject(index);
if (rset.wasNull()) {
return null;
}
return x;
}
 
@Override
public Object getFromResultSet(final ResultSet rset, final String field) throws SQLException {
 
Object x = rset.getObject(field);
if (rset.wasNull()) {
return null;
}
return x;
}
 
@Override
public Class<? extends Object> getTypeClass() {
 
return Object.class;
}
 
@Override
public void bindToStmt(final PreparedStatement stmt, final int index, final Object value) throws SQLException {
 
stmt.setObject(index, value);
}
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/type/DateType.java
New file
0,0 → 1,89
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.type;
 
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
 
import org.mentabean.DBType;
 
public class DateType implements DBType<java.util.Date> {
 
private boolean canBeNull = true;
 
@Override
public boolean canBeNull() {
return canBeNull;
}
 
public DateType nullable(boolean flag) {
DateType d = new DateType();
d.canBeNull = flag;
return d;
}
 
@Override
public String getAnsiType() {
return "date";
}
 
@Override
public String toString() {
 
return this.getClass().getSimpleName();
}
 
@Override
public java.util.Date getFromResultSet(final ResultSet rset, final int index) throws SQLException {
 
return rset.getDate(index);
}
 
@Override
public java.util.Date getFromResultSet(final ResultSet rset, final String field) throws SQLException {
 
return rset.getDate(field);
}
 
@Override
public Class<? extends Object> getTypeClass() {
 
return java.util.Date.class;
}
 
@Override
public void bindToStmt(final PreparedStatement stmt, final int index, final java.util.Date value) throws SQLException {
 
if (value == null) {
 
stmt.setDate(index, null);
 
} else if (value instanceof java.sql.Date) {
 
final java.sql.Date d = (java.sql.Date) value;
 
stmt.setDate(index, d);
 
} else {
 
stmt.setDate(index, new java.sql.Date(value.getTime()));
 
}
}
}
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/type/AutoIncrementType.java
New file
0,0 → 1,86
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.type;
 
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
 
import org.mentabean.DBType;
 
public class AutoIncrementType implements DBType<Number> {
 
@Override
public String getAnsiType() {
return "integer";
}
 
@Override
public boolean canBeNull() {
return false;
}
 
@Override
public String toString() {
 
return this.getClass().getSimpleName();
}
 
@Override
public Long getFromResultSet(final ResultSet rset, final int index) throws SQLException {
 
Long x = rset.getLong(index);
if (rset.wasNull()) {
return null;
}
return x;
}
 
@Override
public Long getFromResultSet(final ResultSet rset, final String field) throws SQLException {
 
Long x = rset.getLong(field);
if (rset.wasNull()) {
return null;
}
return x;
}
 
@Override
public Class<? extends Object> getTypeClass() {
 
return Long.class;
}
 
@Override
public void bindToStmt(final PreparedStatement stmt, final int index, final Number value) throws SQLException {
 
if (value == null) {
 
stmt.setNull(index, java.sql.Types.INTEGER);
 
} else {
 
stmt.setLong(index, value.longValue());
}
}
}
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/type/SizedType.java
New file
0,0 → 1,26
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.type;
 
 
public interface SizedType {
 
public static int DEFAULT_SIZE = 200;
public int getSize();
}
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/type/BooleanType.java
New file
0,0 → 1,76
package org.mentabean.type;
 
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
 
import org.mentabean.DBType;
 
public class BooleanType implements DBType<Boolean> {
 
private boolean canBeNull = true;
 
@Override
public boolean canBeNull() {
return canBeNull;
}
 
public BooleanType nullable(boolean flag) {
BooleanType bt = new BooleanType();
bt.canBeNull = flag;
return bt;
}
 
@Override
public Boolean getFromResultSet(ResultSet rset, int index) throws SQLException {
 
Boolean b = rset.getBoolean(index);
 
if (rset.wasNull()) {
return null;
}
 
return b;
}
 
@Override
public void bindToStmt(PreparedStatement stmt, int index, Boolean value)throws SQLException {
if (value == null) {
stmt.setNull(index, Types.BOOLEAN);
}else {
stmt.setBoolean(index, value);
}
}
 
@Override
public Boolean getFromResultSet(ResultSet rset, String field) throws SQLException {
Boolean b = rset.getBoolean(field);
 
if (rset.wasNull()) {
return null;
}
 
return b;
}
 
@Override
public Class<? extends Object> getTypeClass() {
return Boolean.class;
}
 
@Override
public String getAnsiType() {
return "boolean";
}
 
}
Property changes:
Added: svn:mime-type
+ text/plain
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/type/BigDecimalType.java
New file
0,0 → 1,96
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.type;
 
import java.math.BigDecimal;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
 
import org.mentabean.DBType;
 
public class BigDecimalType implements DBType<BigDecimal> {
 
private boolean canBeNull = true;
 
@Override
public boolean canBeNull() {
return canBeNull;
}
 
public BigDecimalType nullable(boolean flag) {
// clone:
BigDecimalType b = new BigDecimalType();
canBeNull = flag;
return b;
}
 
@Override
public String getAnsiType() {
return "double precision";
}
 
@Override
public String toString() {
 
return this.getClass().getSimpleName();
}
 
@Override
public BigDecimal getFromResultSet(final ResultSet rset, final int index) throws SQLException {
 
BigDecimal bd = rset.getBigDecimal(index);
if (rset.wasNull()) {
return null;
}
 
return bd;
}
 
@Override
public BigDecimal getFromResultSet(final ResultSet rset, final String field) throws SQLException {
BigDecimal bd = rset.getBigDecimal(field);
if (rset.wasNull()) {
return null;
}
 
return bd;
}
 
@Override
public Class<? extends Object> getTypeClass() {
 
return BigDecimal.class;
}
 
@Override
public void bindToStmt(final PreparedStatement stmt, final int index, final BigDecimal value) throws SQLException {
 
if (value == null) {
 
stmt.setNull(index, java.sql.Types.DECIMAL);
 
} else {
 
stmt.setBigDecimal(index, value);
}
}
}
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/type/EnumIdType.java
New file
0,0 → 1,186
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.type;
 
import java.lang.reflect.Method;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
 
import org.mentabean.BeanException;
import org.mentabean.DBType;
 
public class EnumIdType implements DBType<Enum<?>> {
 
private final Class<? extends Enum<?>> enumType;
private final Method fromIdMethod;
private final Method getIdMethod;
 
private boolean canBeNull = false;
 
@Override
public boolean canBeNull() {
return canBeNull;
}
 
public EnumIdType nullable(boolean flag) {
EnumIdType d = new EnumIdType(enumType);
d.canBeNull = flag;
return d;
}
 
public EnumIdType(final Class<? extends Enum<?>> enumType) {
this.enumType = enumType;
this.fromIdMethod = getFromIdMethod(enumType);
this.getIdMethod = getGetIdMethod(enumType);
}
 
@Override
public String getAnsiType() {
return "smallint";
}
 
private static Method getFromIdMethod(Class<? extends Enum<?>> enumType) {
 
try {
 
return enumType.getMethod("fromId", int.class);
} catch (Exception e) {
 
throw new BeanException("Cannot find fromId(int) method from enum class: " + enumType, e);
}
}
 
private static Method getGetIdMethod(Class<? extends Enum<?>> enumType) {
 
try {
 
return enumType.getMethod("getId", (Class[]) null);
} catch (Exception e) {
 
throw new BeanException("Cannot find getId() method from enum class: " + enumType, e);
}
}
 
private Enum<?> fromId(int id) {
try {
return (Enum<?>) fromIdMethod.invoke(null, id);
} catch (Exception e) {
throw new BeanException(e);
}
}
 
private int getId(Enum<?> theEnum) {
try {
return (Integer) getIdMethod.invoke(theEnum, (Object[]) null);
} catch (Exception e) {
throw new BeanException(e);
}
}
 
@Override
public String toString() {
 
return this.getClass().getSimpleName() + ": " + enumType.getSimpleName();
}
 
@Override
public Enum<?> getFromResultSet(final ResultSet rset, final int index) throws SQLException {
 
final int id = rset.getInt(index);
 
if (rset.wasNull()) {
return null;
}
 
return fromId(id);
}
 
@Override
public Enum<?> getFromResultSet(final ResultSet rset, final String field) throws SQLException {
 
final int id = rset.getInt(field);
 
if (rset.wasNull()) {
return null;
}
 
return fromId(id);
}
 
@Override
public Class<? extends Object> getTypeClass() {
 
return enumType;
}
 
@Override
public void bindToStmt(final PreparedStatement stmt, final int index, final Enum<?> value) throws SQLException {
 
if (value == null) {
 
stmt.setNull(index, Types.INTEGER);
 
//Support for overwritten enums (superclass on left)
} else if (enumType.isAssignableFrom(value.getClass())) {
 
final int id = getId(value);
 
stmt.setInt(index, id);
 
} else {
 
throw new IllegalArgumentException("Value '"+value+"' from '"+value.getClass()+"' is not an enum!");
}
}
 
public static enum Test {
 
T1(1), T2(2), T3(3);
 
private final int id;
 
private Test(int id) {
this.id = id;
}
 
public int getId() {
return id;
}
 
public static Test fromId(int id) {
for (Test t : Test.values()) {
if (t.getId() == id) {
return t;
}
}
return null;
}
}
 
public static void main(String[] args) throws Exception {
 
EnumIdType eit = new EnumIdType(Test.class);
 
System.out.println(eit.fromId(2));
 
System.out.println(eit.getId(Test.T3));
 
}
}
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/type/NowOnUpdateTimestampType.java
New file
0,0 → 1,36
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.type;
 
public class NowOnUpdateTimestampType extends TimestampType {
 
private boolean canBeNull = true;
 
@Override
public boolean canBeNull() {
return canBeNull;
}
 
@Override
public NowOnUpdateTimestampType nullable(boolean flag) {
NowOnUpdateTimestampType d = new NowOnUpdateTimestampType();
d.canBeNull = flag;
return d;
}
 
}
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/type/EnumValueTypeFactory.java
New file
0,0 → 1,21
package org.mentabean.type;
 
public class EnumValueTypeFactory {
private static EnumValueTypeFactory instance = null;
private EnumValueTypeFactory() {
 
}
public static EnumValueTypeFactory getInstance() {
if (instance == null) {
instance = new EnumValueTypeFactory();
}
return instance;
}
public EnumValueType from(final Class<? extends Enum<?>> enumType) {
return new EnumValueType(enumType);
}
}
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/type/BooleanIntType.java
New file
0,0 → 1,111
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.type;
 
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
 
import org.mentabean.DBType;
 
public class BooleanIntType implements DBType<Boolean> {
 
private boolean canBeNull = true;
 
@Override
public boolean canBeNull() {
return canBeNull;
}
 
public BooleanIntType nullable(boolean flag) {
// clone
BooleanIntType b = new BooleanIntType();
b.canBeNull = flag;
return b;
}
 
@Override
public String getAnsiType() {
return "smallint";
}
 
@Override
public String toString() {
 
return this.getClass().getSimpleName();
}
 
private static Boolean getBoolValue(final int x) throws SQLException {
 
if (x == 1) {
return Boolean.TRUE;
}
 
if (x == 0) {
return Boolean.FALSE;
}
 
throw new SQLException("integer is not 0 or 1: " + x);
}
 
@Override
public Boolean getFromResultSet(final ResultSet rset, final int index) throws SQLException {
 
final int x = rset.getInt(index);
if (rset.wasNull()) {
return null;
}
 
return getBoolValue(x);
}
 
@Override
public Boolean getFromResultSet(final ResultSet rset, final String field) throws SQLException {
 
final int x = rset.getInt(field);
if (rset.wasNull()) {
return null;
}
 
return getBoolValue(x);
}
 
@Override
public Class<? extends Object> getTypeClass() {
 
return Boolean.class;
}
 
@Override
public void bindToStmt(final PreparedStatement stmt, final int index, final Boolean value) throws SQLException {
 
if (value == null) {
 
stmt.setInt(index, 0);
 
} else if (value instanceof Boolean) {
 
final int x = value ? 1 : 0;
 
stmt.setInt(index, x);
}
 
}
}
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/type/AutoTimestampType.java
New file
0,0 → 1,82
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.type;
 
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
 
import org.mentabean.DBType;
 
public class AutoTimestampType implements DBType<Date> {
 
@Override
public String getAnsiType() {
return "timestamp";
}
 
@Override
public boolean canBeNull() {
return false;
}
 
@Override
public String toString() {
 
return this.getClass().getSimpleName();
}
 
@Override
public Date getFromResultSet(final ResultSet rset, final int index) throws SQLException {
 
return rset.getTimestamp(index);
}
 
@Override
public Date getFromResultSet(final ResultSet rset, final String field) throws SQLException {
 
return rset.getTimestamp(field);
}
 
@Override
public Class<? extends Object> getTypeClass() {
 
return Date.class;
}
 
@Override
public void bindToStmt(final PreparedStatement stmt, final int index, final Date value) throws SQLException {
 
if (value == null) {
 
stmt.setTimestamp(index, null);
 
} else if (value instanceof java.sql.Timestamp) {
 
final java.sql.Timestamp t = (java.sql.Timestamp) value;
 
stmt.setTimestamp(index, t);
 
} else {
 
stmt.setTimestamp(index, new java.sql.Timestamp(value.getTime()));
 
}
}
}
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/jdbc/MySQLBeanSession.java
New file
0,0 → 1,138
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.jdbc;
 
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
 
import org.mentabean.BeanConfig;
import org.mentabean.BeanException;
import org.mentabean.BeanManager;
import org.mentabean.DBField;
import org.mentabean.DBType;
import org.mentabean.type.AutoIncrementType;
import org.mentabean.util.Limit;
import org.mentabean.util.OrderBy;
 
/**
* MySQL only supports auto-increment.
*
* Now in mysql is 'now()'
*
* @author soliveira
*
*/
public class MySQLBeanSession extends AnsiSQLBeanSession {
 
public MySQLBeanSession(final BeanManager beanManager, final Connection conn) {
 
super(beanManager, conn);
}
 
@Override
protected String getCurrentTimestampCommand() {
 
return "now()";
}
 
@Override
protected String getDatabaseType(DBType<?> dbType) {
if (dbType instanceof AutoIncrementType) {
return "integer AUTO_INCREMENT";
}
return super.getDatabaseType(dbType);
}
 
/**
* MySQL is not like Oracle. It will SORT everything first and then apply LIMIT.
*/
@Override
protected StringBuilder handleLimit(final StringBuilder sb, final OrderBy orderBy, final Limit limit) {
 
if (limit == null || limit.intValue() <= 0) {
return sb;
}
 
final StringBuilder sbLimit = new StringBuilder(sb.length() + 32);
 
sbLimit.append(sb.toString()).append(" LIMIT ").append(limit);
 
return sbLimit;
}
 
@Override
public void insert(final Object bean) {
 
super.insert(bean);
 
// find autoincrement field...
 
final BeanConfig bc = beanManager.getBeanConfig(bean.getClass());
 
final DBField autoIncrement = bc.getAutoIncrementField();
 
if (autoIncrement == null) {
 
dispatchAfterInsert(bean);
return;
}
 
PreparedStatement stmt = null;
 
ResultSet rset = null;
 
final StringBuilder sb = new StringBuilder("select last_insert_id() from ");
 
sb.append(bc.getTableName());
 
try {
 
stmt = conn.prepareStatement(sb.toString());
 
rset = stmt.executeQuery();
 
if (rset.next()) {
 
final long id = rset.getLong(1);
try {
 
injectValue(bean, autoIncrement.getName(), id, Integer.class);
} catch(Exception e) {
// try long as well:
injectValue(bean, autoIncrement.getName(), id, Long.class);
}
dispatchAfterInsert(bean);
}
 
} catch (Exception e) {
 
throw new BeanException(e);
 
} finally {
 
close(stmt, rset);
}
}
 
}
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/jdbc/OracleBeanSession.java
New file
0,0 → 1,155
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.jdbc;
 
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
 
import org.mentabean.BeanConfig;
import org.mentabean.BeanException;
import org.mentabean.BeanManager;
import org.mentabean.DBField;
import org.mentabean.util.Limit;
import org.mentabean.util.OrderBy;
 
/**
* When using limit, Oracle will NOT sort first before limiting, so a trick must be used.
*
* Now in Oracle is 'sysdate'.
*
* Oracle only supports sequences for primary keys.
*
* @author soliveira
*
*/
public class OracleBeanSession extends AnsiSQLBeanSession {
 
public OracleBeanSession(final BeanManager beanManager, final Connection conn) {
 
super(beanManager, conn);
}
 
@Override
protected String getCurrentTimestampCommand() {
 
return "sysdate";
}
 
/**
* Oracle will not SORT first then apply LIMIT.
*/
@Override
protected StringBuilder handleLimit(final StringBuilder sb, final OrderBy orderBy, final Limit limit) {
 
if (limit == null || limit.intValue() <= 0) {
return sb;
}
 
final StringBuilder sbLimit = new StringBuilder(sb.length() + 32);
 
if (orderBy != null && !orderBy.isEmpty()) {
 
sbLimit.append("SELECT * FROM (").append(sb.toString()).append(") where rowcount <= ").append(limit);
 
} else {
 
sbLimit.append(sb.toString()).append(" AND rownum <= ").append(limit);
}
 
return sbLimit;
}
 
@Override
public void insert(final Object bean) {
 
// find sequence field...
 
final BeanConfig bc = beanManager.getBeanConfig(bean.getClass());
 
if (bc == null) {
throw new BeanException("Cannot find bean config: " + bean.getClass());
}
 
final DBField seqField = bc.getSequenceField();
 
if (seqField == null) {
 
super.insert(bean);
dispatchAfterInsert(bean);
 
return;
}
 
PreparedStatement stmt = null;
 
ResultSet rset = null;
 
final StringBuilder sb = new StringBuilder(128);
sb.append("select ");
String seqName = bc.getSequenceName();
if (seqName != null) {
// sequence name was defined defined
sb.append(seqName);
} else {
// use the convention for sequence name
sb.append("seq_").append(seqField.getDbName()).append("_").append(bc.getTableName());
}
 
sb.append(".nextval from ").append(bc.getTableName());
 
try {
 
stmt = conn.prepareStatement(sb.toString());
 
rset = stmt.executeQuery();
 
if (rset.next()) {
 
final long id = rset.getLong(1);
try {
 
injectValue(bean, seqField.getName(), id, Integer.class);
} catch(Exception e) {
// try long as well:
injectValue(bean, seqField.getName(), id, Long.class);
}
}
 
} catch (Exception e) {
 
throw new BeanException(e);
 
} finally {
 
close(stmt, rset);
}
 
super.insert(bean);
dispatchAfterInsert(bean);
}
 
}
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/jdbc/FirebirdBeanSession.java
New file
0,0 → 1,143
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.jdbc;
 
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.List;
import java.util.Map;
 
import org.mentabean.BeanConfig;
import org.mentabean.BeanException;
import org.mentabean.BeanManager;
import org.mentabean.DBField;
import org.mentabean.util.Limit;
import org.mentabean.util.OrderBy;
 
/**
* Firebird support.
*
* @author soliveira
*/
public class FirebirdBeanSession extends AnsiSQLBeanSession {
 
public FirebirdBeanSession(final BeanManager beanManager, final Connection conn) {
 
super(beanManager, conn);
}
 
@Override
protected String getCurrentTimestampCommand() {
 
return "current_timestamp";
}
 
/**
* MySQL is not like Oracle. It will SORT everything first and then apply LIMIT.
*/
@Override
protected StringBuilder handleLimit(final StringBuilder sb, final OrderBy orderBy, final Limit limit) {
 
if (limit == null || limit.intValue() <= 0) {
return sb;
}
 
String query = sb.toString();
 
if (query.toLowerCase().startsWith("select ")) {
throw new BeanException("Got a limit query that does not start with select: " + query);
}
 
String withoutSelect = query.substring("select".length());
 
final StringBuilder sbLimit = new StringBuilder(withoutSelect.length() + 64);
 
sbLimit.append("SELECT first(").append(limit).append(")").append(withoutSelect);
 
return sbLimit;
}
 
@Override
public void insert(final Object bean) {
 
// find autoincrement field...
 
final BeanConfig bc = beanManager.getBeanConfig(bean.getClass());
 
final DBField autoIncrement = bc.getAutoIncrementField();
 
if (autoIncrement == null) {
 
super.insert(bean);
dispatchAfterInsert(bean);
 
return;
}
 
QueryAndValues qav = prepareInsertQuery(bean);
 
StringBuilder sb = qav.sb;
 
List<Value> values = qav.values;
 
if (conn == null) {
throw new BeanException("Connection is null!");
}
 
PreparedStatement stmt = null;
ResultSet rset = null;
 
try {
 
// add the returning...
 
sb.append(" returning ").append(autoIncrement.getDbName());
 
if (DEBUG) {
System.out.println("INSERT SQL: " + sb.toString());
}
 
stmt = conn.prepareStatement(sb.toString());
 
Map<String, Value> fieldsLoaded = bindToInsertStatement(stmt, values);
 
rset = stmt.executeQuery();
 
if (!rset.next()) {
throw new BeanException("Nothing was inserted! Insert returned no result set!");
}
 
int id = rset.getInt(autoIncrement.getDbName());
 
injectValue(bean, autoIncrement.getName(), id, Integer.class);
 
loaded.put(bean, fieldsLoaded);
dispatchAfterInsert(bean);
 
} catch (Exception e) {
 
throw new BeanException(e);
 
} finally {
close(stmt, rset);
}
}
}
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/jdbc/H2BeanSession.java
New file
0,0 → 1,201
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.jdbc;
 
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
 
import org.mentabean.BeanConfig;
import org.mentabean.BeanException;
import org.mentabean.BeanManager;
import org.mentabean.DBField;
import org.mentabean.DBType;
import org.mentabean.type.AutoIncrementType;
import org.mentabean.util.Limit;
import org.mentabean.util.OrderBy;
 
/**
* H2 supports AUTOINCREMENT and SEQUENCE fields.
*
* Now has the value 'sysdate', like Oracle.
*
* @author Sergio Oliveira Jr.
*/
public class H2BeanSession extends AnsiSQLBeanSession {
 
public H2BeanSession(final BeanManager beanManager, final Connection conn) {
super(beanManager, conn);
}
 
@Override
protected String getCurrentTimestampCommand() {
 
return "sysdate";
}
 
@Override
protected StringBuilder handleLimit(final StringBuilder sb, final OrderBy orderBy, final Limit limit) {
 
if (limit == null || limit.intValue() <= 0) {
return sb;
}
 
final StringBuilder sbLimit = new StringBuilder(sb.length() + 32);
 
sbLimit.append(sb.toString()).append(" LIMIT ").append(limit);
 
return sbLimit;
}
 
@Override
protected String getDatabaseType(DBType<?> dbType) {
if (dbType instanceof AutoIncrementType) {
return "integer AUTO_INCREMENT";
}
return super.getDatabaseType(dbType);
}
 
@Override
public void insert(final Object bean) {
 
// find sequence... (if any)...
 
final BeanConfig bc = beanManager.getBeanConfig(bean.getClass());
 
if (bc == null) {
throw new BeanException("Cannot find bean config: " + bean.getClass());
}
 
final DBField seqField = bc.getSequenceField();
 
if (seqField != null) {
 
PreparedStatement stmt = null;
 
ResultSet rset = null;
 
final StringBuilder sb = new StringBuilder(128);
sb.append("select NEXTVAL(");
String seqName = bc.getSequenceName();
if (seqName != null) {
// sequence name was defined
sb.append(seqName);
} else {
// use convention
sb.append("seq_").append(seqField.getDbName()).append("_").append(bc.getTableName());
}
 
sb.append(") from ").append(bc.getTableName());
 
try {
 
stmt = conn.prepareStatement(sb.toString());
 
rset = stmt.executeQuery();
 
if (rset.next()) {
 
final long id = rset.getLong(1);
try {
 
injectValue(bean, seqField.getName(), id, Integer.class);
} catch(Exception e) {
// try long as well...
injectValue(bean, seqField.getName(), id, Long.class);
}
}
 
} catch (Exception e) {
 
throw new BeanException(e);
 
} finally {
 
close(stmt, rset);
}
}
 
super.insert(bean);
 
// find autoincrement field...
 
final DBField autoIncrement = bc.getAutoIncrementField();
 
if (autoIncrement == null) {
 
dispatchAfterInsert(bean);
return;
}
 
PreparedStatement stmt = null;
 
ResultSet rset = null;
 
final StringBuilder sb = new StringBuilder("select identity() from ");
 
sb.append(bc.getTableName());
 
try {
 
stmt = conn.prepareStatement(sb.toString());
 
rset = stmt.executeQuery();
 
if (rset.next()) {
 
final long id = rset.getLong(1);
try {
 
injectValue(bean, autoIncrement.getName(), id, Integer.class);
} catch(Exception e) {
// try long as well:
injectValue(bean, autoIncrement.getName(), id, Long.class);
}
dispatchAfterInsert(bean);
}
 
} catch (Exception e) {
 
throw new BeanException(e);
 
} finally {
 
close(stmt, rset);
}
}
@Override
protected boolean isVarcharUnlimitedSupported() {
return true;
}
 
}
/tags/menta-bean-2.2.2/src/main/java/org/mentabean/jdbc/AnsiSQLBeanSession.java
New file
0,0 → 1,2641
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* MentaBean => http://www.mentabean.org
* Author: Sergio Oliveira Jr. (sergio.oliveira.jr@gmail.com)
*/
package org.mentabean.jdbc;
 
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
 
import org.mentabean.BeanConfig;
import org.mentabean.BeanException;
import org.mentabean.BeanManager;
import org.mentabean.BeanSession;
import org.mentabean.DBField;
import org.mentabean.DBType;
import org.mentabean.event.TriggerDispatcher;
import org.mentabean.event.TriggerDispatcher.Type;
import org.mentabean.event.TriggerEvent;
import org.mentabean.event.TriggerListener;
import org.mentabean.sql.TableAlias;
import org.mentabean.type.AutoIncrementType;
import org.mentabean.type.AutoTimestampType;
import org.mentabean.type.NowOnInsertAndUpdateTimestampType;
import org.mentabean.type.NowOnInsertTimestampType;
import org.mentabean.type.NowOnUpdateTimestampType;
import org.mentabean.type.SizedType;
import org.mentabean.util.InjectionUtils;
import org.mentabean.util.Limit;
import org.mentabean.util.OrderBy;
import org.mentabean.util.PropertiesProxy;
import org.mentabean.util.SQLUtils;
 
/**
* The bean session implementation based on JDBC and SQL.
*
* @author soliveira
*/
public class AnsiSQLBeanSession implements BeanSession {
 
protected static boolean DEBUG = false;
protected static boolean DEBUG_NATIVE = false;
 
/* The loaded map will be cleared when the session dies */
protected IdentityHashMap<Object, Map<String, Value>> loaded = new IdentityHashMap<Object, Map<String, Value>>();
 
protected Connection conn;
 
protected final BeanManager beanManager;
protected final TriggerDispatcher dispatcher = new TriggerDispatcher();
 
/**
* Creates a JdbcBeanSession with a BeanManager and a Connection.
*
* @param beanManager
* The bean manager
* @param conn
* The database connection
*/
public AnsiSQLBeanSession(final BeanManager beanManager, final Connection conn) {
this.beanManager = beanManager;
this.conn = conn;
}
 
/**
* Turn SQL debugging on and off.
*
* @param b
* true if it should be debugged
*/
public static void debugSql(boolean b) {
DEBUG = b;
}
/**
* Turn SQL native queries debugging on and off.
*
* @param b
* true if it should be debugged
*/
public static void debugNativeSql(boolean b) {
DEBUG_NATIVE = b;
}
 
/**
* Get the connection associated with this JdbcBeanSession.
*
* @return the database connection
*/
@Override
public Connection getConnection() {
 
return conn;
}
 
/**
* Get the command representing 'now' in this database. This base implementation returns null, in other words, no now command will be used.
*
* @return the command for now in this database (now(), sysdate, etc)
*/
protected String getCurrentTimestampCommand() {
 
return null;
}
 
/**
* Get a value from a bean through reflection.
*
* @param bean
* @param fieldName
* @return The value of a bean property
*/
protected Object getValueFromBean(final Object bean, final String fieldName) {
 
return getValueFromBean(bean, fieldName, null);
 
}
public static String[] getProperties(Object[] names) {
if (names != null) {
for(Object o : names) {
if (o instanceof String) {
PropertiesProxy.addPropertyName((String) o);
}
}
}
if (PropertiesProxy.hasProperties()) {
return PropertiesProxy.getPropertyNames();
} else {
return null;
}
}
/**
* Get a value from a bean through reflection.
*
* @param bean
* @param fieldName
* @param m
* @return The value of a bean property
*/
protected Object getValueFromBean(final Object bean, final String fieldName, Method m) {
int index;
if ((index = fieldName.lastIndexOf(".")) > 0) {
String chain = fieldName.substring(0, index);
String lastField = fieldName.substring(index + 1);
Object deepestBean = getDeepestBean(bean, chain, false);
if (deepestBean == null) return null;
return getValueFromBean(deepestBean, lastField, m);
}
if (bean == null) {
return null;
}
 
if (m == null) {
m = InjectionUtils.findMethodToGet(bean.getClass(), fieldName);
}
 
if (m == null) {
throw new BeanException("Cannot find method to get field from bean: " +
"Class: " + bean.getClass() + ", field: " + fieldName);
}
 
Object value = null;
 
try {
 
value = m.invoke(bean, (Object[]) null);
 
return value;
 
} catch (Exception e) {
throw new BeanException(e);
}
}
 
private static void checkPK(final Object value, final DBField dbField) {
 
if (value == null) {
throw new BeanException("pk is missing: " + dbField);
} else if (value instanceof Number) {
 
final Number n = (Number) value;
 
if (n.doubleValue() <= 0) {
throw new BeanException("Number pk is missing: " + dbField);
}
}
}
@Override
public boolean load(Object bean) {
return loadImpl(bean, null, null);
}
@Override
public boolean load(Object bean, Object... properties) {
return loadImpl(bean, getProperties(properties), null);
}
@Override
public boolean loadMinus(Object bean, Object... minus) {
return loadImpl(bean, null, getProperties(minus));
}
protected boolean loadImpl(final Object bean, String[] properties, String[] minus) {
 
final BeanConfig bc = getConfigFor(bean.getClass());
 
if (bc == null) {
throw new BeanException("Cannot find bean config: " + bean.getClass());
}
 
if (bc.getNumberOfFields() == 0) {
throw new BeanException("BeanConfig has zero fields: " + bc);
}
 
final StringBuilder sb = new StringBuilder(32 * bc.getNumberOfFields());
 
sb.append("SELECT ");
 
Iterator<DBField> iter = bc.fields();
 
int count = 0;
 
while (iter.hasNext()) {
 
DBField field = iter.next();
final String fieldName = field.getDbName();
if (!field.isPK()) { // always load the PK...
if (properties != null && !checkArray(fieldName, properties, bc)) {
continue;
}
if (minus != null && checkArray(fieldName, minus, bc)) {
continue;
}
}
 
if (count++ > 0) {
sb.append(',');
}
 
sb.append(fieldName);
 
}
 
sb.append(" FROM ").append(bc.getTableName()).append(" WHERE ");
 
if (!bc.hasPK()) {
throw new BeanException("Cannot load bean without a PK!");
}
 
iter = bc.pks();
 
count = 0;
 
final List<Value> values = new LinkedList<Value>();
 
while (iter.hasNext()) {
 
final DBField dbField = iter.next();
 
final String fieldName = dbField.getName();
 
final String dbFieldName = dbField.getDbName();
 
final Object value = getValueFromBean(bean, fieldName);
 
checkPK(value, dbField);
 
if (count++ > 0) {
sb.append(" AND ");
}
 
sb.append(dbFieldName).append("=?");
 
values.add(new Value(dbField, value));
 
}
 
if (values.isEmpty()) {
throw new BeanException("Bean is empty: " + bean + " / " + bc);
}
 
if (conn == null) {
throw new BeanException("Connection is null!");
}
 
PreparedStatement stmt = null;
 
ResultSet rset = null;
 
try {
if (DEBUG) {
System.out.println("LOAD SQL: " + sb.toString());
}
stmt = conn.prepareStatement(sb.toString());
 
final Iterator<Value> iter2 = values.iterator();
 
int index = 0;
 
while (iter2.hasNext()) {
 
final Value v = iter2.next();
v.field.getType().bindToStmt(stmt, ++index, v.value);
 
}
 
rset = stmt.executeQuery();
if (DEBUG_NATIVE) {
System.out.println("LOAD SQL (NATIVE): " + stmt);
}
 
index = 0;
 
final Map<String, Value> fieldsLoaded = new HashMap<String, Value>();
 
if (rset.next()) {
 
iter = bc.fields();
 
while (iter.hasNext()) {
 
final DBField f = iter.next();
 
final String fieldName = f.getName();
if (!f.isPK()) {
if (properties != null && !checkArray(fieldName, properties, bc)) {
continue;
}
if (minus != null && checkArray(fieldName, minus, bc)) {
continue;
}
}
 
final DBType type = f.getType();
 
final Object value = type.getFromResultSet(rset, ++index);
 
injectValue(bean, fieldName, value, type.getTypeClass());
 
fieldsLoaded.put(fieldName, new Value(f, value));
}
 
} else {
return false;
}
 
if (rset.next()) {
throw new BeanException("Load returned more than one row!");
}
 
loaded.put(bean, fieldsLoaded);
 
return true;
 
} catch (Exception e) {
 
throw new BeanException(e);
 
} finally {
 
close(stmt, rset);
}
}
private Object getDeepestBean(Object target, String name, boolean create) {
int index;
if ((index = name.indexOf('.')) > 0) {
String fieldName = name.substring(0, index);
 
String remainingName = name.substring(index + 1);
Object bean = getPropertyBean(target, fieldName, create);
return getDeepestBean(bean, remainingName, create);
}
return getPropertyBean(target, name, create);
}
/**
* Get a value from target through reflection and tries to create a new instance if create parameter is true
* @param target
* @param name
* @param create
* @return The value from bean
*/
protected Object getPropertyBean(Object target, String name, boolean create) {
Object value = getValueFromBean(target, name);
if (value == null && create) {
// try to instantiate, must have a default constructor!
Class<?> beanClass = InjectionUtils.findPropertyType(target.getClass(), name);
if (beanClass == null) {
throw new BeanException("Cannot find property type: " + target.getClass() + " " + name);
}
try {
value = beanClass.newInstance();
} catch(Exception e) {
value = getAbstractValue(target.getClass(), name);
}
// don't forget to inject in the target so next time it is there...
injectValue(target, name, value, beanClass);
}
return value;
}
private Object getAbstractValue(Class<? extends Object> clazz, String name) {
try {
BeanConfig bc = getConfigFor(clazz);
if (bc != null) {
Class<? extends Object> instanceClass = bc.getAbstractProperty(name);
if (instanceClass != null) {
return instanceClass.newInstance();
}
}
throw new BeanException("Cannot instantiate property name: " + name + " from "+clazz);
} catch (Exception e) {
throw new BeanException("Cannot instantiate abstract value for "+clazz+" (field "+name+")", e);
}
}
 
/**
* Inject a value in a bean through reflection.
*
* @param bean
* @param fieldName
* @param value
* @param valueType
*/
protected void injectValue(final Object bean, final String fieldName, Object value, final Class<? extends Object> valueType) {
// first check if we have a chain of fields...
int index;
if ((index = fieldName.lastIndexOf(".")) > 0) {
if (value == null) {
// there is nothing to do here, as we don't want to create any object since the id is null...
return;
}
String chain = fieldName.substring(0, index);
String lastField = fieldName.substring(index + 1);
Object deepestBean = getDeepestBean(bean, chain, true);
injectValue(deepestBean, lastField, value, valueType);
return;
}
 
final Method m = InjectionUtils.findMethodToInject(bean.getClass(), fieldName, value == null ? valueType : value.getClass());
 
if (m == null) {
 
// try field...
 
final Field field = InjectionUtils.findFieldToInject(bean.getClass(), fieldName, value == null ? valueType : value.getClass());
if (field != null) {
// if field is a primitive (not a wrapper or void), convert a null to its default value
if (field.getType().isPrimitive() && value == null) {
value = InjectionUtils.getDefaultValueForPrimitive(field.getType());
}
try {
 
field.set(bean, value);
 
} catch (final Exception e) {
 
e.printStackTrace();
 
throw new BeanException(e);
}
} else {
// if Long and can be expressed as integer, try integer...
if (value instanceof Long) {
Long l = (Long) value;
if (l.longValue() <= Integer.MAX_VALUE && l.longValue() >= Integer.MIN_VALUE) {
injectValue(bean, fieldName, l.intValue(), Integer.class); // recursion...
return;
}
}
// Field can be a GenericType (Object). If value is null nothing will be injected..
if (value != null)
throw new BeanException("Cannot find field or method to inject: " + bean + " / " + fieldName);
}
 
} else {
// if field is a primitive (not a wrapper or void), convert a null to its default value
Class<?> paramType = m.getParameterTypes()[0];
if (paramType.isPrimitive() && value == null) {
value = InjectionUtils.getDefaultValueForPrimitive(paramType);
}
try {
m.invoke(bean, value);
 
} catch (final Exception e) {
 
e.printStackTrace();
 
throw new BeanException(e);
}
}
}
 
/**
* Some databases will sort before applying the limit (MySql), others will not (Oracle). Handle each one accordingly.
*
* Note: This base implementation does nothing.
*
* @param sb
* @param orderBy
* @param limit
* @return A string builder with the the SQL modified for the limit operation
*/
protected StringBuilder handleLimit(final StringBuilder sb, final OrderBy orderBy, final Limit limit) {
 
return sb;
}
 
/**
* Build the column/field list for a SQL SELECT statement based on the bean configuration. Very useful to create select statements.
*
* @param beanClass
* the bean class
* @return the column/field list for a select
*/
@Override
public String buildSelect(final Class<? extends Object> beanClass) {
 
return buildSelectImpl(beanClass, null, null, null, true, true);
}
 
@Override
public String buildSelect(final Class<? extends Object> beanClass, Object... properties) {
return buildSelectImpl(beanClass, null, getProperties(properties), null, true, true);
}
 
/**
* Build a column/field list for a SQL SELECT statement based on the bean configuration. A table prefix will be used on each field. Very useful to create select statements on multiple tables (joins).
*
* @param beanClass
* the bean class
* @param tablePrefix
* the table prefix to use before each field
* @return the column/field list for a select
*/
@Override
public String buildSelect(final Class<? extends Object> beanClass, final String tablePrefix) {
 
return buildSelectImpl(beanClass, tablePrefix, null, null, true, true);
}
 
@Override
public String buildSelect(final Class<? extends Object> beanClass, final String tablePrefix, Object... properties) {
return buildSelectImpl(beanClass, tablePrefix, getProperties(properties), null, true, true);
}
 
/**
* Like buildSelect but you can exclude some properties from the resulting list. Useful when you have a bean with too many properties and you just want to fetch a few.
*
* Note: The list of properties to exclude contains 'property names' and NOT database column names.
*
* @param beanClass
* the bean class
* @param minus
* a list for property names to exclude
* @return the column/field list for a select
*/
@Override
public String buildSelectMinus(final Class<? extends Object> beanClass, final Object... minus) {
return buildSelectImpl(beanClass, null, null, getProperties(minus), true, true);
}
 
/**
* Same as buildSelectMinus with support for a database table prefix that will be applied on each field.
*
* @param beanClass
* the bean class
* @param tablePrefix
* the database table prefix
* @param minus
* a list of property names to exclude
* @return the column/field list for a select
*/
@Override
public String buildSelectMinus(final Class<? extends Object> beanClass, final String tablePrefix, final Object... minus) {
return buildSelectImpl(beanClass, tablePrefix, null, getProperties(minus), true, true);
}
 
protected String buildSelectImpl(final Class<? extends Object> beanClass, final String tablePrefix,
final String[] properties, final String[] minus, final boolean includePK, final boolean addSuffix) {
 
final BeanConfig bc = getConfigFor(beanClass);
 
if (bc == null) {
return null;
}
 
final StringBuilder sb = new StringBuilder(32 * bc.getNumberOfFields());
 
final Iterator<DBField> iter = bc.fields();
 
int count = 0;
 
while (iter.hasNext()) {
 
final DBField field = iter.next();
 
final String dbField = field.getDbName();
 
final String name = field.getName();
 
if (!field.isPK() || !includePK) { // always include PK
if (properties != null && !checkArray(name, properties, bc)) {
continue;
}
if (minus != null && checkArray(name, minus, bc)) {
continue;
}
}
 
if (count++ > 0) {
sb.append(",");
}
 
if (tablePrefix != null) {
 
sb.append(tablePrefix).append('.').append(dbField);
 
if (addSuffix) {
sb.append(' ');
 
sb.append(tablePrefix).append('_').append(dbField);
}
 
} else {
sb.append(dbField);
}
}
 
return sb.toString();
 
}
 
private boolean checkArray(final String value, final String[] array, final BeanConfig bc) {
 
String column = propertyToColumn(bc, value);
for (int i = 0; i < array.length; i++) {
if (propertyToColumn(bc, array[i]).equals(column)) {
return true;
}
}
 
return false;
}
 
/**
* Populate a bean (insert all its properties) from the results in a result set, based on the bean configuration.
*
* @param rset
* the result set from where to get the property values
* @param bean
* the bean to be populated
* @throws Exception
*/
@Override
public void populateBean(final ResultSet rset, final Object bean) {
 
populateBeanImpl(rset, bean, null, null, null, true);
}
 
@Override
public void populateBean(final ResultSet rset, final Object bean, Object... properties) {
populateBeanImpl(rset, bean, null, getProperties(properties), null, true);
}
 
/**
* Same as populateBean, but use a table prefix before fetching the values from the result set. Useful when there are multiple tables involved and you want to avoid field name clashing.
*
* @param rset
* the result set
* @param bean
* the bean to be populated
* @param tablePrefix
* the table prefix
*/
@Override
public void populateBean(final ResultSet rset, final Object bean, final String tablePrefix) {
 
populateBeanImpl(rset, bean, tablePrefix, null, null, true);
}
 
@Override
public void populateBean(final ResultSet rset, final Object bean, final String tablePrefix, Object... properties) {
populateBeanImpl(rset, bean, tablePrefix, getProperties(properties), null, true);
}
 
/**
* Same as populateBean, but exclude some fields when populating.
*
* @param rset
* @param bean
* @param minus
*/
@Override
public void populateBeanMinus(final ResultSet rset, final Object bean, final Object... minus) {
populateBeanImpl(rset, bean, null, null, getProperties(minus), true);
}
 
/**
* Same as populateBean, but exclude some fields when populating and use a table prefix in front of the field names.
*
* @param rset
* @param bean
* @param tablePrefix
* @param minus
*/
@Override
public void populateBeanMinus(final ResultSet rset, final Object bean, final String tablePrefix, final Object... minus) {
populateBeanImpl(rset, bean, tablePrefix, null, getProperties(minus), true);
}
 
protected void populateBeanImpl(final ResultSet rset, final Object bean, final String tablePrefix, final String[] properties, final String[] minus, boolean includePK) {
 
final BeanConfig bc = getConfigFor(bean.getClass());
 
if (bc == null) {
throw new BeanException("Cannot find bean config: " + bean.getClass());
}
 
final Iterator<DBField> iter = bc.fields();
 
final StringBuilder sbField = new StringBuilder(32);
 
while (iter.hasNext()) {
 
final DBField f = iter.next();
 
final String fieldName = f.getName();
if (!f.isPK() || !includePK) { // always populate PK
if (properties != null && !checkArray(fieldName, properties, bc)) {
continue;
}
if (minus != null && checkArray(fieldName, minus, bc)) {
continue;
}
}
 
final String dbFieldName = f.getDbName();
 
final DBType type = f.getType();
 
sbField.setLength(0);
 
if (tablePrefix != null) {
sbField.append(tablePrefix).append('_').append(dbFieldName);
} else {
sbField.append(dbFieldName);
}
 
try {
 
final Object value = type.getFromResultSet(rset, sbField.toString());
 
injectValue(bean, fieldName, value, type.getTypeClass());
 
} catch (Exception e) {
 
throw new BeanException(e);
}
}
}
 
/**
* Load a list of beans, but exclude some fields.
*
* @param <E>
* @param bean
* @param minus
* @param orderBy
* @param limit
* @return A list of beans
*/
@Override
public <E> List<E> loadListMinus(final E bean, final OrderBy orderBy, final Limit limit, final Object... minus) {
return loadListImpl(bean, orderBy, limit, null, getProperties(minus));
}
 
private <E> E checkUnique(final List<E> list) {
 
if (list == null || list.size() == 0) {
return null;
} else if (list.size() > 1) {
throw new BeanException("Query returned more than one bean!");
} else {
return list.get(0);
}
}
 
@Override
public <E> List<E> loadList(final E bean, final OrderBy orderBy, final Limit limit) {
 
return loadListImpl(bean, orderBy, limit, null, null);
}
 
@Override
public <E> List<E> loadList(final E bean, final OrderBy orderBy, final Limit limit, Object... properties) {
return loadListImpl(bean, orderBy, limit, getProperties(properties), null);
}
 
private <E> StringBuilder prepareListQuery(StringBuilder sb, BeanConfig bc, E bean, OrderBy orderBy, Limit limit, List<Value> values) {
 
sb.append(" FROM ").append(bc.getTableName()).append(" ");
 
Iterator<DBField> iter = bc.fields();
 
int count = 0;
 
while (iter.hasNext()) {
 
final DBField field = iter.next();
 
final String dbField = field.getDbName();
 
final Method m = findMethodToGet(bean, field.getName());
boolean isNestedProperty = field.getName().contains(".");
 
if (m == null) {
if (!isNestedProperty) {
throw new BeanException("Cannot find method to get field from bean: " + field.getName());
} else {
continue; // nested property not set!
}
}
 
final Class<? extends Object> returnType = m.getReturnType();
 
final Object value = getValueFromBean(bean, field.getName(), m);
 
if (!isSet(value, returnType)) {
continue;
}
 
if (count++ > 0) {
sb.append(" AND ");
} else {
sb.append(" WHERE ");
}
 
sb.append(dbField).append("=?");
 
values.add(new Value(field, value));
}
 
sb.append(buildOrderBy(orderBy, bc));
 
sb = handleLimit(sb, orderBy, limit);
 
return sb;
}
private String buildOrderBy(OrderBy orderBy, BeanConfig bc) {
if (orderBy != null && !orderBy.isEmpty()) {
String orderByString = orderBy.toString();
String[] orders = orderByString.trim().split("\\s*,\\s*");
for (String order : orders) {
if (order.contains(" ")) {
order = order.substring(0, order.indexOf(" "));
}
orderByString = orderByString.replace(order, propertyToColumn(bc, order));
}
StringBuilder sb = new StringBuilder();
sb.append(" order by ").append(orderByString).append(" ");
return sb.toString();
}
return " ";
}
/**
* Returns a database column name for a bean attribute.
* @param bc - The <code>BeanConfig</code> object
* @param property - A bean property
* @return The database column name found if exists, otherwise will return the
* given bean <code>property</code>
*/
public String propertyToColumn(BeanConfig bc, Object property) {
Iterator<DBField> it = bc.fields();
String propertyName = getProperties(new Object[] {property})[0];
while (it.hasNext()) {
DBField field = it.next();
if (propertyName.equalsIgnoreCase(field.getName()))
return field.getDbName();
}
return propertyName;
}
@Override
public String propertyToColumn(Class<? extends Object> clazz, Object property) {
return propertyToColumn(clazz, property, null);
}
@Override
public String propertyToColumn(Class<? extends Object> clazz, Object property, String alias) {
BeanConfig bc = getConfigFor(clazz);
if (alias == null)
return propertyToColumn(bc, property);
return alias+"."+propertyToColumn(bc, property);
}
@Override
public String buildTableName(Class<? extends Object> clazz) {
return getConfigFor(clazz).getTableName();
}
@Override
public QueryBuilder buildQuery() {
 
return new QueryBuilder(this);
}
 
@Override
public int countList(Object bean) {
return countListImpl(bean, null, null);
}
 
private int countListImpl(final Object bean, final OrderBy orderBy, final Limit limit) {
 
if (limit != null && limit.intValue() == 0) {
return 0;
}
 
final BeanConfig bc = getConfigFor(bean.getClass());
 
if (bc == null) {
throw new BeanException("Cannot find bean config: " + bean.getClass());
}
 
StringBuilder sb = new StringBuilder(32 * bc.getNumberOfFields());
 
sb.append("SELECT count(1)");
 
final List<Value> values = new LinkedList<Value>();
 
sb = prepareListQuery(sb, bc, bean, orderBy, limit, values);
 
PreparedStatement stmt = null;
 
ResultSet rset = null;
 
try {
 
final String sql = sb.toString();
 
if (DEBUG) {
System.out.println("COUNT LIST: " + sql);
}
 
stmt = conn.prepareStatement(sql);
 
final Iterator<Value> iter2 = values.iterator();
 
int index = 0;
 
while (iter2.hasNext()) {
 
final Value v = iter2.next();
 
v.field.getType().bindToStmt(stmt, ++index, v.value);
 
}
 
rset = stmt.executeQuery();
if (DEBUG_NATIVE) {
System.out.println("COUNT LIST (NATIVE): "+stmt);
}
 
rset.next();
 
return rset.getInt(1);
 
} catch (Exception e) {
 
throw new BeanException(e);
 
} finally {
 
close(stmt, rset);
}
}
 
private <E> List<E> loadListImpl(final E bean, final OrderBy orderBy, final Limit limit, final String[] properties, final String[] minus) {
 
if (limit != null && limit.intValue() == 0) {
return new ArrayList<E>();
}
 
final BeanConfig bc = getConfigFor(bean.getClass());
 
if (bc == null) {
throw new BeanException("Cannot find bean config: " + bean.getClass());
}
 
StringBuilder sb = new StringBuilder(32 * bc.getNumberOfFields());
 
Iterator<DBField> iter = bc.fields();
 
sb.append("SELECT ");
 
int count = 0;
 
while (iter.hasNext()) {
 
final DBField field = iter.next();
 
final String dbField = field.getDbName();
 
final String name = field.getName();
 
if (!field.isPK()) {
if (properties != null && !checkArray(name, properties, bc)) {
continue;
}
if (minus != null && checkArray(name, minus, bc)) {
continue;
}
}
 
if (count++ > 0) {
sb.append(",");
}
 
sb.append(dbField);
}
 
final List<Value> values = new LinkedList<Value>();
 
sb = prepareListQuery(sb, bc, bean, orderBy, limit, values);
 
PreparedStatement stmt = null;
 
ResultSet rset = null;
 
try {
 
final String sql = sb.toString();
if (DEBUG) {
System.out.println("LOAD LIST: "+sql);
}
stmt = conn.prepareStatement(sql);
 
final Iterator<Value> iter2 = values.iterator();
 
int index = 0;
 
while (iter2.hasNext()) {
 
final Value v = iter2.next();
 
v.field.getType().bindToStmt(stmt, ++index, v.value);
 
}
 
rset = stmt.executeQuery();
if (DEBUG_NATIVE) {
System.out.println("LOAD LIST (NATIVE): " + stmt);
}
 
final List<E> results = new LinkedList<E>();
 
final Class<? extends Object> beanKlass = bean.getClass();
 
int total = 0;
 
while (rset.next()) {
 
iter = bc.fields();
 
index = 0;
 
final E item = (E) beanKlass.newInstance(); // not sure how to
// handle generics
// here...
 
while (iter.hasNext()) {
 
final DBField f = iter.next();
 
final String fieldName = f.getName();
if (!f.isPK()) {
 
if (properties != null && !checkArray(fieldName, properties, bc)) {
continue;
}
if (minus != null && checkArray(fieldName, minus, bc)) {
continue;
}
}
 
final DBType type = f.getType();
 
final Object value = type.getFromResultSet(rset, ++index);
 
injectValue(item, fieldName, value, type.getTypeClass());
}
 
results.add(item);
 
total++;
 
if (limit != null && limit.intValue() > 0 && total == limit.intValue()) {
return results;
}
}
 
return results;
 
} catch (Exception e) {
 
throw new BeanException(e);
 
} finally {
 
close(stmt, rset);
}
}
 
/**
* if Boolean consider TRUE to be set and FALSE to be not set.
*
* if Character, cast to integer and assume it is set if different than 0
*
* if Number consider everything different than zero to be set.
*
* Otherwise returns TRUE for anything different than null and FALSE for null.
*
* @param value
* @param returnType
* @return true if is set
*/
protected boolean isSet(final Object value, final Class<? extends Object> returnType) {
 
if (value != null) {
if (returnType.equals(boolean.class) && value instanceof Boolean) {
 
// if Boolean consider TRUE to be set and FALSE to be not set
// (false = default value)
 
final boolean b = ((Boolean) value).booleanValue();
 
return b;
 
} else if (returnType.equals(char.class) && value instanceof Character) {
 
// if Character, cast to int and assume set if different than
// 0...
 
final int c = ((Character) value).charValue();
 
return c != 0;
 
} else if (returnType.isPrimitive() && !returnType.equals(boolean.class) && !returnType.equals(char.class) && value instanceof Number) {
 
// if number consider everything different than zero to be set...
 
final Number n = (Number) value;
 
if (n.doubleValue() != 0d) {
return true;
}
 
} else {
return true;
}
}
 
return false;
}
 
@Override
public int update(final Object bean, Object... forceNull) {
 
return update(bean, true, getProperties(forceNull));
}
 
@Override
public int updateAll(final Object bean) {
 
return update(bean, false, null);
}
 
private int update(final Object bean, final boolean dynUpdate, String[] nullProps) {
 
final Map<String, Value> fieldsLoaded = loaded.get(bean);
 
final BeanConfig bc = getConfigFor(bean.getClass());
 
if (bc == null) {
throw new BeanException("Cannot find bean config: " + bean.getClass());
}
 
if (bc.getNumberOfFields() == 0) {
throw new BeanException("BeanConfig has zero fields: " + bc);
}
 
final StringBuilder sb = new StringBuilder(32 * bc.getNumberOfFields());
 
sb.append("UPDATE ").append(bc.getTableName()).append(" SET ");
 
Iterator<DBField> iter = bc.fields();
 
int count = 0;
 
final List<Value> values = new LinkedList<Value>();
while (iter.hasNext()) {
 
final DBField dbField = iter.next();
 
if (dbField.isPK()) {
continue;
}
 
final DBType type = dbField.getType();
 
if (type instanceof AutoIncrementType) {
continue;
}
 
if (type instanceof AutoTimestampType) {
continue;
}
 
boolean isNowOnUpdate = type instanceof NowOnUpdateTimestampType || type instanceof NowOnInsertAndUpdateTimestampType;
 
final String fieldName = dbField.getName();
 
final String dbFieldName = dbField.getDbName();
 
if (!isNowOnUpdate) {
Method m = findMethodToGet(bean, fieldName);
Object value = null;
Class<? extends Object> returnType = null;
boolean isNestedProperty = fieldName.contains(".");
if (m == null && !isNestedProperty) {
throw new BeanException("Cannot find method to get field from bean: " + fieldName);
}
 
if (m != null) {
returnType = m.getReturnType();
value = getValueFromBean(bean, fieldName, m);
}
 
boolean update = false;
 
if (!dynUpdate) {
 
// if this is NOT a dynUpdate then update all properties with
// whatever value they have
 
update = true;
 
} else if (fieldsLoaded != null) {
 
// this is a dynUpdate, check if value is dirty, in other words,
// if it has changed since it was loaded...
 
final Value v = fieldsLoaded.get(fieldName);
 
if (v != null) {
if (value == null && v.value != null) {
update = true;
} else if (value != null && v.value == null) {
update = true;
} else if (value == null && v.value == null) {
update = false;
} else {
update = !value.equals(v.value);
}
}
 
} else {
 
// this is a dynUpdate, but bean was not previously loaded from
// the database...
// in this case only update if the property is considered to be
// SET...
 
update = isSet(value, returnType);
if (!update && nullProps != null) {
update = checkArray(fieldName, nullProps, bc);
//null in database column
value = null;
}
}
 
if (update) {
 
if (count++ > 0) {
sb.append(',');
}
 
sb.append(dbFieldName).append("=?");
 
values.add(new Value(dbField, value));
 
}
 
} else {
 
if (count++ > 0) {
sb.append(',');
}
sb.append(dbFieldName).append("=");
 
String nowCommand = getCurrentTimestampCommand();
 
if (nowCommand == null) {
 
sb.append("?");
 
values.add(new Value(dbField, new java.util.Date()));
 
} else {
 
sb.append(nowCommand);
}
}
}
 
if (count == 0) {
return 0;
}
 
sb.append(" WHERE ");
 
if (!bc.hasPK()) {
throw new BeanException("Cannot update bean without a PK!");
}
 
iter = bc.pks();
 
count = 0;
 
while (iter.hasNext()) {
 
final DBField dbField = iter.next();
 
final String fieldName = dbField.getName();
 
final String dbFieldName = dbField.getDbName();
 
final Object value = getValueFromBean(bean, fieldName);
 
if (value == null) {
throw new BeanException("pk is missing: " + dbField);
} else if (value instanceof Number) {
 
final Number n = (Number) value;
 
if (n.doubleValue() <= 0) {
throw new BeanException("Number pk is missing: " + dbField);
}
 
}
 
if (count++ > 0) {
sb.append(" AND ");
}
 
sb.append(dbFieldName).append("=?");
 
values.add(new Value(dbField, value));
 
}
 
if (values.isEmpty()) {
throw new BeanException("Bean is empty: " + bean + " / " + bc);
}
 
if (conn == null) {
throw new BeanException("Connection is null!");
}
 
PreparedStatement stmt = null;
 
try {
 
if (DEBUG) {
System.out.println("UPDATE SQL: " + sb.toString());
}
 
dispatchBeforeUpdate(bean);
stmt = conn.prepareStatement(sb.toString());
 
Iterator<Value> iter2 = values.iterator();
 
int index = 0;
 
while (iter2.hasNext()) {
 
final Value v = iter2.next();