【ActiveJdbc】02

 

一、基本的数据库操作

数据模型层:

import org.javalite.activejdbc.Model;

数据访问层:

import org.javalite.activejdbc.Base;
import org.javalite.activejdbc.DB;

 

基础的查询方法:

    @Test
    public void commonQuery() {
//        数据集读取
//        List<Map> usersList = Base.findAll("select * from users where company_id = ? ", companyId);
//        for(Map  record: userList){
//            System.out.println("first_name: " + record.get("first_name"));
//            System.out.println("last_name: " + record.get("last_name"));
//        }

//        单个值的读取
//        Long  lastLoginTime = Convert.toLong(Base.firstCell("select time from logins  where user_id  ? order by created_at limit 1", 123));


//        单个列读取        
//        List ssns = Base.firstColumn("select ssn from people where first_name = ?", "John");
//        ssns.forEach(System.out::println);
    }

 

二、Setter & Getter

ActiveJdbc提供的读写方式:

    @Test
    public void commonQuery() {

        // 读方法
        Employee employee = Employee.findById(2);
        
        Object columnName = employee.get("columnName");
        String colName = columnName.toString();

        
        // 写方法
        Employee employee1 = new Employee();
        
        employee1.set("colName1", "value1");
        employee1.set("colName2", "value2");
        employee1.set("colName3", "value3");
        employee1.save();
    }

没有JavaBean方式的?作者的意思是你自己重写就行了

package cn.cloud9.entity;

import org.javalite.activejdbc.Model;
import org.javalite.activejdbc.annotations.Table;

@Table("people")
public class Employee extends Model {

    public void setFirstName(String firstName){
        set("first_name", firstName);
    }
    public String getFirstName(){
        return getString("first_name");
    }
}

 

类型转换问题

作者提供了一些类型可以直接获取的方法:

这里我就列举四种常用的:

employee.getString("columnName");
employee.getInteger(
"columnName");
employee.getDate(
"asdasd");
employee.getBigDecimal(
"asdasd");

 

三、数据库表和模型名称的对应

一般来说ActiveJdbc默认将类的名字全大写识别成表名称

如果表名含有特殊符号不能直接识别,可以加上@Table注解声明

package cn.cloud9.entity;

import org.javalite.activejdbc.Model;
import org.javalite.activejdbc.annotations.Table;

@Table("people")
public class Employee extends Model {

}

 

四、连接管理

线程连接传播

ActiveJDBC 模型在运行时利用在当前线程上找到的连接。

在任何 DB 操作之前,此连接由 Base 或 DB 类放在本地线程上。

这种方法允许更简洁的 API,不需要像其他 Java ORM 那样需要 DB Session 或持久管理器。

这是一个简单的程序:

public static void main(String[] args) {
   Base.open("com.mysql.jdbc.Driver", "jdbc:mysql://localhost/test", "the_user", "the_password");
   Employee.findAll().dump();
   Base.close();
}

在第 2 行,Base 类将打开一个新连接并将其附加到当前线程。此连接也将标有名称default

在第 3 行,从线程中查找连接并由模型使用(并将结果转储到 STDIO)

在第 4 行,连接关闭并从线程中清除。

 

Base用于单个库的连接访问,而DB支持多个库多个服务器实例的访问

ActiveJDBC 有一个逻辑数据库的概念但是,一个应用程序可以同时连接到多个数据库。

在这种情况下,ActiveJDBC 允许为不同的数据库分配不同的逻辑名称。

例如,一个人可能有一个包含会计数据的 Oracle 数据库和一个包含库存控制数据的 MySQL 数据库。

在这种情况下,您可能希望将会计数据库和库存数据库作为分配给这些数据库的逻辑名称。

 

打开和关闭连接是通过类 Base 或 DB 完成的。DB 类用于系统中有多个数据库的情况,例如会计库存

例子:

new DB("inventory").open("com.mysql.jdbc.Driver", "jdbc:mysql://localhost/test", "dbuser", "...");

在此代码示例中,打开了一个数据库连接,并连接到名称为inventory的本地线程

类 Base 和 DB 相互镜像,具有完全相同的 API,除了:

  • DB 上的所有方法都是实例方法,而 Base 类上的所有方法都是静态方法。
  • 类 DB 构造函数接受 DB 名称,而 Base 始终使用 DB 名称操作:默认

这意味着这些行是等效的:

new DB("default").open("com.mysql.jdbc.Driver", "jdbc:mysql://localhost/test", "root", "p@ssw0rd");

和:

Base.open("com.mysql.jdbc.Driver", "jdbc:mysql://localhost/test", "root", "p@ssw0rd");

Base如果系统中只有一个数据库,请使用class,否则使用DB

测试:

    @Test
    public void commonQuery() {
        new DB("default")
                .open(
                        "com.mysql.cj.jdbc.Driver",
                        "jdbc:mysql://localhost:3308/atguigu-syt?serverTimeZone=Asia/Shanghai",
                        "root",
                        "123456"
                );

        Employee employee = Employee.findById(1);
        System.out.println(employee);
    }

 

多个库的模型设置:

与多个数据库关联的模型

ActiveJDBC 允许在表示来自不同数据库的表的应用程序中混合使用模型。

默认情况下,模型属于数据库默认值,但模型与数据库的关联可以用注释覆盖@DbName

package cn.cloud9.entity;

import org.javalite.activejdbc.Model;
import org.javalite.activejdbc.annotations.DbName;
import org.javalite.activejdbc.annotations.Table;

@DbName("atguigu-syt")
@Table("people")
public class Employee extends Model {

}

就是需要标注这个模型是对应哪个库下的哪张表

 

作者提供的多库操作案例:

多数据库示例
请参阅此处的来源:multimple-db-example。

对于这个例子,我们将有两个模型,一个代表 Oracle 数据库中的表,另一个代表 MySQL

这两个模型定义如下:

@DbName("corporation")
public class Employee extends Model {}
和:

@DbName("university")
public class Student  extends Model {}
主类如下所示:

public class Main {
    public static void main(String[] args) {
        new DB("corporation").open("com.mysql.jdbc.Driver", "jdbc:mysql://localhost/test", "root", "p@ssw0rd");
        new DB("university").open("oracle.jdbc.driver.OracleDriver", "jdbc:oracle:thin:@localhost:1521:xe", "activejdbc", "activejdbc");

        Employee.deleteAll();
        Student.deleteAll();

        Employee.createIt("first_name", "John", "last_name", "Doe");
        Employee.createIt("first_name", "Jane", "last_name", "Smith");

        Student.createIt("first_name", "Mike", "last_name", "Myers");
        Student.createIt("first_name", "Steven", "last_name", "Spielberg");

        System.out.println("*** Employees ***");
        Employee.findAll().dump();
        System.out.println("*** Students ***");
        Student.findAll().dump();

        new DB("corporation").close();
        new DB("university").close();
    }
}
// 在这个应用程序开始时,两个命名连接被打开,然后我们继续使用与这些连接关联的模型。在应用程序结束时,两个命名连接被关闭。类 DB 是轻量级的,可以不保留对它的引用,而是每次都创建一个新实例。如果你确实想保留一个引用,那也没什么坏处。

 

五、连接池操作:

和Tomcat的JNDI结合操作:

ActiveJDBC 接受到现有池的 JNDI 连接 URL。

它提供了一些DB.open()Base.open()方法,以开放游泳池的连接。

 

如果使用采用标准 JDBC 参数的方法版本,则不使用池。

这只是一种打开全新连接的便捷方法,例如:

Base.open("com.mysql.jdbc.Driver", "jdbc:mysql://localhost/test", "root", "pwd");

 

但是,如果使用此调用:

Base.open("java:comp/env/jdbc/testdb");

然后它将使用 JDNI 名称从池中查找连接。

通常这是从容器内调用的,名称指向在容器级别配置的池化 JNDI 数据源。

 

如果不是JNDI提供的连接池,则提供DataSource数据源来入参

如果你想直接使用某个连接池,你可以通过向 Base/DB 类提供数据源来实现:

new DB("default").open(datasourceInstance);
//or:
Base.open(datasourceInstance);

 

配置文件与多个环境:

为不同环境配置多个连接的最简单方法是使用属性文件。

按照惯例,这个文件被调用database.properties并位于类路径的根目录。

以下是此类文件的示例:

development.driver=com.mysql.jdbc.Driver
development.username=user1
development.password=pwd
development.url=jdbc:mysql://localhost/acme_development

test.driver=com.mysql.jdbc.Driver
test.username=user2
test.password=pwd
test.url=jdbc:mysql://localhost/acme_test

production.jndi=java:comp/env/jdbc/acme

为了使其工作,您需要将环境变量配置ACTIVE_ENV为等于属性集键的值。

根据上面的文件,ACTIVE_ENV可以采用值developmentproductiontest是特殊的,因为它用于开发环境,但用于运行测试(测试模式)。

配置文件并放置在类路径的根目录后,您将使用无参数方法打开连接,如下所示:

org.javalite.activejdbc.connection_config.DBConfiguration.loadConfiguration("/database.properties); 
// The previous line is necessary starting with version 2.3.2-j8.

new DB("default").open();
//or: 
Base.open();

第一行只需要在开始时调用一次即可从文件加载配置。

将选择与当前环境相关的配置并用于打开连接。

这使得开发存在于不同环境中的应用程序变得容易,并且只需知道在每个环境中连接的位置。

如果ACTIVE_ENV未定义环境变量,则框架默认为 environment development

 

插入记录的方式:

这是常规插入的操作步骤:

Person p = new Person();
p.set("first_name", "John");
p.set("last_name", "Doe");
p.set("dob", "1935-12-06");
p.saveIt();

 

使用方法链来操作:

Person p = new Person();
p.set("name", "John")
    .set("last_name", "Doe")
    .set("dob", "1935-12-06")
    .saveIt();

 

使用重载的可变参数注入:

Person p = new Person();
p.set(
    "first_name",  "Sam", 
    "last_name", "Margulis", 
    "dob", "2001-01-07"
);
p.saveIt();

 

支持数组形式的批处理:

String[] names = {"first_name", "last_name", "dob"};
Object[] values = {"John", "Doe", dob}
new Person().set(names, values).saveIt();

要求Key数组和Value数组的长度一致

 

直接从Map填充值:
作者还贴心的提供了一个fromMap方法,

Map可以理解为从请求中封装好的装填数据

Map values = ... initialize map
Person p = new Person();
p.fromMap(values);
p.saveIt();

 

save 和 saveIt方法的区别?

ActiveJDBC 类 Model 提供了两种保存实体的方法:save()saveIt()这两种方法都将在保存期间涉及验证,

但在方法 save() 的情况下,将静默退出而不抛出异常。

如果验证失败,该实例将附加一个错误集合。这在 Web 应用程序的上下文中非常有用。下面是一个例子:

Person person = new Person();
person.fromMap(requestParams);
if(person.save()) //<<<===  will not throw exception and will not save in case there are validation errors. 
    //show page success
else{
     request.setAttribute("errors", person.errors());
     //show errors page, or same page so that user can correct errors.
}

saveIt()如果出现验证问题,方法将抛出异常。

save()方法在 Web 应用程序的上下文中更有意义,而saveIt()在非 Web 应用程序情况下更有用 - 批量插入、测试等。

 

总结一下,作者意思推荐使用saveIt去处理插入,因为会抛出异常信息,对批量处理操作更好

 

或者直接调用Create & CreateIt

类 Model 还提供了两种创建记录的便捷方法:create()createIt()

这两种方法在语义上是有区别的,和save()saveIt()方法之间是一样的,只是在这种情况下,ActiveJDBC 一步创建并尝试保存对象。

Person p = Person.create("first_name", "Sam", "last_name", "Margulis", "dob", "2001-01-07");
p.saveIt();

或者:

Person p = Person.createIt("first_name", "Sam", "last_name", "Margulis", "dob", "2001-01-07");

create()createIt()方法接受的参数,其中名称交错值的列表。

这类似于上面描述的 varargs setter,但也包括save()saveIt()方法的语义。

posted @ 2021-07-21 17:00  emdzz  阅读(232)  评论(0编辑  收藏  举报