【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
可以采用值development
和production
. 这test
是特殊的,因为它用于开发环境,但用于运行测试(测试模式)。
配置文件并放置在类路径的根目录后,您将使用无参数方法打开连接,如下所示:
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
未定义环境变量,则框架默认为 environmentdevelopment
。
插入记录的方式:
这是常规插入的操作步骤:
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()
方法的语义。
【ActiveJdbc】02的更多相关文章
- 【watcher】 #02 c# 中实现时间戳等,日期数字及大概率绝对随机数 实现
在Wacher的项目中,用到了很多时间记录的地方,为了将来能够和在线数据打通,我们使用了时间戳来记录时间信息 由于c# 没有现成的方法,所以我们重新写了一个Helper类来帮助我们使用这些公共函数 同 ...
- 【组合数学】 02 - Möbius反演公式
计数问题种类繁多,为了避免陷入漫无目的烧脑运动,我们先需要关注一些常用方法和结论.数学的抽象性和通用性是我们一直推崇的,从诸多特殊问题中发现一般性的方法,也总会让人兴奋和慨叹.一般教材多是以排列组合开 ...
- 【C】 02 - 程序结构和预处理
在正式进入C的语法之前,有必要对其整体外观和组成元素作一个浏览.这部分内容对大多数人是比较陌生的,但它们却是C的起点和骨架.而这些内容涉及的背景或细节又可以展开为专门的课题,这里也只是浅尝则止,说明个 ...
- 【hexo】02完成本地创建
获得一个github账号并创建repo,命名为yourname.github.io 搭桥到github 配置github账户信息(YourName和YourEail都替换成你自己的): 网站部署 $ ...
- 【二叉查找树】02不同的二叉查找树个数II【Unique Binary Search Trees II】
提到二叉查找树,就得想到二叉查找树的递归定义, 左子树的节点值都小于根节点,右子树的节点值都大于根节点. +++++++++++++++++++++++++++++++++++++++++++++++ ...
- 【JVM】02垃圾回收机制
垃圾回收 垃圾回收策略https://blog.csdn.net/u010425776/article/details/51189318 程序计数器.Java虚拟机栈.本地方法栈都是线程私有的,也就是 ...
- 【SpringCloud】02.微服务与SpringCloud
微服务的特点 一系列微小的服务共同组成 跑在自己的进程里 每个服务为独立的业务开发 独立部署 分布式管理 异构--不同的语言.不同类型的数据库 微服务架构的基础框架/组件 服务注册发现 服务网关(Se ...
- 【SpringBoot】02.编写HelloWorld
1.编写一个返回HelloWorld的Controller @Controller public class HelloWorld { @ResponseBody @RequestMapping(&q ...
- Shadow Map 原理和改进 【转】
http://blog.csdn.net/ronintao/article/details/51649664 参考 1.Common Techniques to Improve Shadow Dept ...
- 【scikit-learn】06:make_blobs聚类数据生成器
版权声明:本文为博主原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/kevinelstri/article/ ...
随机推荐
- 在 TypeScript 中,extends
extends 是一个关键字,用于指定类型参数的约束.它在类型参数的声明中使用,以确保类型参数满足特定的条件. 具体来说,extends 后面可以跟随一个类型,表示类型参数必须是该类型的子类型.在泛型 ...
- MS SQL SERVER 创建表、索引、添加字段等常用脚本
创建表: if not exists ( select 1 from sysobjects where id=object_id('PayChannelNm') ) create table [dbo ...
- 大一统的监控探针采集器 cprobe
需求背景 监控数据采集领域,比如 Prometheus 生态有非常多的 Exporter,虽然生态繁荣,但是无法达到开箱即用的大一统体验,Exporter 体系的核心问题有: 良莠不齐:有的 Expo ...
- 容器docker技术
我们先看看很久很久以前,服务器是怎么部署应用的! 由于物理机的诸多问题,后来出现了虚拟机. 但是虚拟化也是有局限性的,每一个虚拟机都是一个完整的操作系统,要分配系统资源,虚拟机多道一定程度时,操作系统 ...
- Diffusers实战
Smiling & Weeping ---- 一生拥有自由和爱,是我全部的野心 1. 环境准备 %pip install diffusers from huggingface_hub impo ...
- linux下安装oracle 11g(静默安装)
关闭selinux 关闭防火墙 检查安装依赖包 yum -y install binutils compat-libcap1 vsftpd gcc gcc-c++ glibc-devel glibc ...
- MAC10.12Caps Lock失灵
先说一下小弟的MAC系统是黑苹果来的,笔记本并没有那个显示大小写的指示灯,所以一开始的时候一直以为自己的键盘坏了还特意换了一个(结果质量比原来的更差),输入密码因为有大小写经常被提示密码错误所以蛋疼得 ...
- 19-Docker数据持久化
什么是Docker数据持久化 容器在运行时会在镜像层上加上一层:可写层. 当删除容器时,可写层就会一起被删除,数据丢失. 数据持久化就是就是将数据持久化保存,删除容器之后,数据仍然存在. 方法1-挂载 ...
- Debezium-Flink-Hudi:实时流式CDC
1. 什么是Debezium Debezium是一个开源的分布式平台,用于捕捉变化数据(change data capture)的场景.它可以捕捉数据库中的事件变化(例如表的增.删.改等),并将其转为 ...
- Linux C 读写超过2G的大文件 注意事项
背景 在项目中做大文件的增量读写,遇到了问题: fopen : Value too large for defined data type. 习惯性地根据这个提示查阅的有关资料显示: 1)工具链太老了 ...