3. 快速开发
本章分别展示了使用java和c语言接口进行LightDB开发的过程。
3.1. java开发
本节展示了用java代码如何连接LightDB数据库,以及基本的执行流程。更多高级的执行功能参考 LightDB-JDBC 说明
3.1.1. JDBC
3.1.1.1. 引入驱动依赖
<!-- https://mvnrepository.com/artifact/io.github.hslightdb/ltjdbc -->
<dependency>
<groupId>io.github.hslightdb</groupId>
<artifactId>ltjdbc</artifactId>
<version>42.2.24-23.1.0.1</version>
</dependency>
3.1.1.2. 加载连接驱动
Class.forName("org.postgresql.Driver");//加载LightDB连接驱动
3.1.1.3. 获取数据库连接
//连接之前需要准备数据库的url,用户名,密码
Connection newConnection = DriverManager.getConnection(Url,Username, Password);
//url的基本写法是:jdbcUrl=jdbc:postgresql://{host}:{port}/{database}?lightdbSyntaxCompatibleType=oracle
//{host}表示目标数据库IP
//{port}表示目标数据库端口
//{database}表示目标数据库名称
3.1.1.4. 执行sql和返回结果
//编写sql:如查询表的所有字段的内容select * from tableName
String sql="select * from tableName";
//调用获取到的数据库连接newConnection来调用prepareStatement方法创建PreparedStatement对象,同时该方法可以提高运行效率
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//调取preparedStatement对象的增删改查方法来得到结果,如查询executeQuery(),调用setString等来执行插入。调用executeUpdate()删除
//不用的方法返回不同的结果,细节参考`方法 <https://www.runoob.com/manual/jdk11api/java.sql/java/sql/PreparedStatement.html>`_
//以下是查询的返回结果,
ResultSet resultSet = preparedStatement.executeQuery();
//获取的resultSet的数据
while (resultSet.next()) {
// 支持自动类型转换
Double dou = resultSet.getObject(1, Double.class);
Assert.assertEquals(Double.valueOf(1.1), dou);
}
//关闭连接
resultSet.close();
preparedStatement.close();
connection.close();
3.1.1.5. 例子
Class.forName("org.postgresql.Driver");
Connection connection = DriverManager.getConnection("jdbc:postgresql://10.20.30.11:5432/fund60?lightdbSyntaxCompatibleType=oracle", "username", "password");
PreparedStatement preparedStatement = connection.prepareStatement("select to_number('1.1','9999.99')");
ResultSet resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
Double dou = resultSet.getObject(1, Double.class);
Assert.assertEquals(Double.valueOf(1.1), dou);
}
resultSet.close();
preparedStatement.close();
connection.close();
3.1.2. SpringBoot JdbcTemplate
3.1.2.1. 引入依赖
--引入spring-boot-starterjdbc依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
--引入LightDB的jdbc驱动
<dependency>
<groupId>io.github.hslightdb</groupId>
<artifactId>ltjdbc</artifactId>
<version>42.2.24-23.1.0.1</version>
</dependency>
3.1.2.2. 配置数据源信息
在配置文件application.properties里面配置数据库的url,用户名,密码,驱动
spring.datasource.url=jdbc:postgresql://{host}:{port}/{database}
spring.datasource.username=username
spring.datasource.password=password
spring.datasource.driver-class-name=org.postgresql.Driver
3.1.2.3. 获取jdbcTemplate
//可通过自动装配来获取
@Autowired
JdbcTemplate jdbcTemplate;
//手动获取
JdbcTemplate jdbcTemplate=new JdbcTemplate();
jdbcTemplate.setDataSource(dataSource);
3.1.2.4. 执行和返回结果
调取JdbcTemplate的增删改查等方法来执行sql,并且返回结果。更多方法,参考 文档
//增加
String insertSql="insert into person(id,user_name,password) values(?,?,?)";
jdbcTemplate.update(insertSql,1,"tom","123456");
//查
String selectSql="select * from person where id =1";
Map<String, Object> map = jdbcTemplate.queryForMap(selectSql);
//删除
jdbcTemplate.update("DELETE FROM Student where id = ? ",id);
3.1.3. MyBatis
3.1.3.1. 引入依赖
<!--mybatis依赖-->
<dependencies>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<!--(mysql连接类)jdbc依赖,mybatis仍然需要用到jdbc,只是不需要我们手动配置jdbc-->
<dependency>
<groupId>io.github.hslightdb</groupId>
<artifactId>ltjdbc</artifactId>
<version>42.2.24-23.1.0.1</version>
</dependency>
</dependencies>
3.1.3.2. 配置文件修改参数
#在配置文件里面设置驱动
driver=org.postgresql.Driver
url=jdbc:postgresql://{host}:{port}/{database}
username=root
password=root
3.1.3.3. 配置连接
private static InputStream inputStream;
//这个方法生成一个生产Sqlsession的工厂,即SqlSessionFactory
public static SqlSessionFactory createfactory() {
{
try {
inputStream = Resources.getResourceAsStream("mybatisconfig.xml");
} catch (IOException e) {
e.printStackTrace();
}
}
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过把这个工厂return出来,以便后续通过这个工厂获得SqlSession对象
return sqlSessionFactory;
}
//这个方法获得SqlSession对象,相当于JDBC中的statement
public static SqlSession getsqlsession(){
return createfactory().openSession();
}
3.1.3.4. 创建实体类和执行sql的接口
public interface StudentDao {
//查询全部用户
List<Student> getstudentinfo();
//根据id查询用户
Student getstudentbyid(int id);
List<Student> getstudentbyid2(HashMap<String, Object> map);
int addUser(Student student);
int updateStudent(Student student);
int deleteStudent(int id);
}
public class Student {
private int id;
private String stname;
private String sex;
private String classs;
private String telphone;
public Student() {
}
public Student(int id, String stname, String sex, String classs, String telphone) {
this.id = id;
this.stname = stname;
this.sex = sex;
this.classs = classs;
this.telphone = telphone;
}
}
3.1.3.5. 写sql语句
在接口对应的xml文件里面写需要的sql语句
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--绑定接口-->
<mapper namespace="Dao.StudentDao">
<!--查询-->
<select id="getstudentinfo" resultType="pojo.Student">
select * from student
</select>
<!--增加-->
<insert id="addUser" parameterType="pojo.Student" >
insert into student values(#{id},#{name},#{sex},#{classs},#{telphone})
</insert>
<!--修改-->
<update id="updateStudent" parameterType="pojo.Student">
update student set stname =#{name},classs=#{classs} where id =#{id};
</update>
<!--删除-->
<delete id="deleteStudent" parameterType="int">
delete from student where id =#{id}
</delete>
</mapper>
3.1.3.6. 调用
//通过GetSqlsession直接.getsqlsession这个静态方法获得SqlSession对象
SqlSession sqlsession = GetSqlsession.getsqlsession();
//通过SqlSession的.getMapper方法,传入你接口的class获得接口,这里是java的反射机制
StudentDao studentdao = sqlsession.getMapper(StudentDao.class);
//通过接口类反射得到的接口对象studentdao直接调用其内部的方法
List<Student> students = studentdao.getstudentinfo();
//遍历输出这个List
for (Student student : students) {
System.out.println(student);
}
//切记!!!用完一定要把sqlsession对象关闭,不然会造成资源占用
sqlsession.close();
3.1.4. JRESCloud3.X
是恒生自己开发的微服务框架,可通过该框架来配置数据库连接。这里举例结合Mybatis的使用方法。
3.1.4.1. 引入依赖
<!--引入JRESCloud3.X框架依赖-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.hundsun.jrescloud</groupId>
<artifactId>jrescloud-dependencies</artifactId>
<version>3.1.2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!--多数据源依赖-->
<dependency>
<groupId>com.hundsun.jrescloud.middleware</groupId>
<artifactId>jrescloud-starter-mybatis</artifactId>
</dependency>
<!--引入LigjhtDB的JDBC驱动依赖-->
<dependency>
<groupId>io.github.hslightdb</groupId>
<artifactId>ltjdbc</artifactId>
<version>42.2.24-23.1.0.1</version>
</dependency>
<!--引入MysqlB的JDBC驱动依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
3.1.4.2. 创建实体类
/**
* 多数据源注解@EnableCloudDataSource,开启多数据源功能
*/
@EnableCloudDataSource
@CloudApplication // 启动类注解,声明一个微服务应用
public class UnisqlMultiDataSourceApplication {
public static void main(String[] args) {
CloudBootstrap.run(UnisqlMultiDataSourceApplication.class, args);
}
}
3.1.4.3. 设置配置文件
在配置文件src/main/resources/application.properties中配置多数据源。配置数据源之前要确保驱动已经引入依赖。
hs.druid.validationQuery=select 1
hs.datasource.default.driverClassName=驱动
hs.datasource.default.url=数据库连接地址
hs.datasource.default.username=用户名
hs.datasource.default.password=密码
#事例
#引入lightDB数据库的驱动
hs.datasource.default.driverClassName=org.postgresql.Driver
#数据库的url
hs.datasource.default.url=jdbc:postgresql://{host}:{port}/{database}
#数据库的用户名
hs.datasource.default.username=test1
#数据库的密码
hs.datasource.default.password=test1
#引入Mysql数据库的驱动
hs.datasource.mysql.driverClassName=com.mysql.jdbc.Driver
hs.datasource.mysql.url=jdbc:mysql://10.20.30.193:5757/test?useSSL=false&serverTimezone=UTC
hs.datasource.mysql.username=root
hs.datasource.mysql.password=123456
基于数据库厂商标识编写配置文件
mybatis.mapper-locations=classpath:mapper/**/*.xml
hs.druid.validationQuery=select 1
hs.datasource.mysql.driverClassName=com.mysql.jdbc.Driver
hs.datasource.mysql.url=jdbc:mysql://10.20.30.193:5757/test?useSSL=false&serverTimezone=UTC
hs.datasource.mysql.username=root
hs.datasource.mysql.password=123456
hs.datasource.default.driverClassName=com.hundsun.lightdb.unisql.proxy.Driver
hs.datasource.default.url=jdbc:unisql:postgresql://10.20.30.199:54333/testdb1?sourceDialect=oracle&targetDialect=postgresql
hs.datasource.default.username=test1
hs.datasource.default.password=test1
3.1.4.4. 编写接口实现
基于普通的Mybatis:使用注解@TargetDataSource指定当前服务类或服务方法所使用的数据源:
public interface StudentDao {
@TargetDataSource("mysql")
List<Student> getstudentinfo();
//根据id查询用户
@TargetDataSource("mysql")
Student getstudentbyid(int id);
@TargetDataSource("default")
List<Student> getstudentbyid2(HashMap<String, Object> map);
@TargetDataSource("default")
int addUser(Student student);
@TargetDataSource("mysql")
int updateStudent(Student student);
@TargetDataSource("mysql")
int deleteStudent(int id);
}
public class Student {
private int id;
private String stname;
private String sex;
private String classs;
private String telphone;
public Student() {
}
public Student(int id, String stname, String sex, String classs, String telphone) {
this.id = id;
this.stname = stname;
this.sex = sex;
this.classs = classs;
this.telphone = telphone;
}
}
基于数据库厂商标识(databaseIdProvider): 使用java config准备mybatis自定义配置类配置数据库厂商标识(databaseIdProvider):
@Configuration
public class MybatisConfig {
@Bean
public DatabaseIdProvider databaseIdProvider() {
/**
* 注意:基于jrescloud 3.x ,多数据源,配置文件application.properties中default数据源对应的数据库产品最终决定databaseId的取值(只作用一次)
* 举例,default数据源为基于统一sql配置的数据库产品PostgreSQL且作为目标sql,但应用层使用的源sql为oracle,此时在properties中配置映射关系p.setProperty("PostgreSQL", "oracle"); 最终databaseId为oracle
*/
DatabaseIdProvider databaseIdProvider = new VendorDatabaseIdProvider();
Properties p = new Properties();
p.setProperty("MySQL", "mysql");
// 使用统一sql, 目标sql:postgresql 源sql:oracle
p.setProperty("PostgreSQL", "oracle");
databaseIdProvider.setProperties(p);
return databaseIdProvider;
}
}
3.1.4.5. 写sql语句
基于普通的Mybatis:在接口对应的xml文件里面写需要的sql语句
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--绑定接口-->
<mapper namespace="Dao.StudentDao">
<!--查询-->
<select id="getstudentinfo" resultType="pojo.Student">
select * from student
</select>
<!--增加-->
<insert id="addUser" parameterType="pojo.Student" >
insert into student values(#{id},#{name},#{sex},#{classs},#{telphone})
</insert>
<!--修改-->
<update id="updateStudent" parameterType="pojo.Student">
update student set stname =#{name},classs=#{classs} where id =#{id};
</update>
<!--删除-->
<delete id="deleteStudent" parameterType="int">
delete from student where id =#{id}
</delete>
</mapper>
基于数据库厂商标识(databaseIdProvider)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.example.unisql.multi.db.mapper.TestMapper">
<!--databaseId属性值指向源sql,这里是mysql-->
<select id="queryForList" resultType="map" databaseId="mysql">
select 1 from dual
</select>
<!--databaseId属性值指向源sql,这里是oracle-->
<select id="queryForList" resultType="map" databaseId="oracle">
select nation, listagg(city, ',') within GROUP (order by city1, city2 desc) from temp group by nation
</select>
</mapper>
3.1.4.6. 调用
//通过GetSqlsession直接.getsqlsession这个静态方法获得SqlSession对象
SqlSession sqlsession = GetSqlsession.getsqlsession();
//通过SqlSession的.getMapper方法,传入你接口的class获得接口,这里是java的反射机制
StudentDao studentdao = sqlsession.getMapper(StudentDao.class);
//通过接口类反射得到的接口对象studentdao直接调用其内部的方法
List<Student> students = studentdao.getstudentinfo();
//遍历输出这个List
for (Student student : students) {
System.out.println(student);
}
//切记!!!用完一定要把sqlsession对象关闭,不然会造成资源占用
sqlsession.close();
3.2. c开发
本节仅展示最基础的使用功能,更多C API接口可查看 官网 说明
准备测试:
--建表及生成测试数据
CREATE SCHEMA testlibpq3;
SET search_path = testlibpq3;
CREATE TABLE test1 (i int4, t text, b bytea);
INSERT INTO test1 values (1, 'joe''s place', '\000\001\002\003\004');
INSERT INTO test1 values (2, 'ho there', '\004\003\002\001\000');
--确保libpq已经安装
[lightdb@node101 testlibpq]$ whereis libpq
libpq: /usr/lib64/libpq.so /usr/include/libpq
使用c语言接口libpq开发第一个LightDB时,大致的执行步骤如下:
1. 包含头文件
#include "libpq-fe.h"
2. 连接数据库
conninfo = "host=127.0.0.1 port=5432 dbname = postgres user=lightdb password=!QAZ2wsx";
conn = PQconnectdb(conninfo);
3. 执行SQL语句
res = PQexec(conn, "SELECT * from test1 where name=''");
res = PQexec(conn, "delete from test1 where id=3");
4. 获取查询结果
PQgetvalue(res, 0, 0);
5. 清理结果
PQclear(res);
6. 关闭连接
PQfinish(conn);
下面使用一个样例来展示使用c语言接口libpq进行LightDB开发的过程
/*
* Test the C version of libpq, the LightDB frontend library.
*/
#include <stdio.h>
#include <stdlib.h>
#include "libpq-fe.h"
static void
exit_nicely(PGconn *conn)
{
PQfinish(conn);
exit(1);
}
int
main(int argc, char **argv)
{
const char *conninfo;
PGconn *conn;
PGresult *res;
int nFields;
int i,
j;
/*
* 设置数据库连接串
*/
conninfo = "host=127.0.0.1 port=5432 dbname = postgres user=lightdb password=!QAZ2wsx";
/* 连接 */
conn = PQconnectdb(conninfo);
/* Check to see that the backend connection was successfully made */
if (PQstatus(conn) != CONNECTION_OK)
{
fprintf(stderr, "Connection to database failed: %s",
PQerrorMessage(conn));
exit_nicely(conn);
}
/* 设置search_path,只允许查询testlibpq3这个schema下的表 */
res = PQexec(conn, "SET search_path = testlibpq3");
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr, "SET failed: %s", PQerrorMessage(conn));
PQclear(res);
exit_nicely(conn);
}
PQclear(res);
/*
* 执行select语句
*/
res = PQexec(conn, "select * from test1");
if (PQresultStatus(res) != PGRES_TUPLES_OK)
{
fprintf(stderr, "SELECT failed: %s", PQerrorMessage(conn));
PQclear(res);
exit_nicely(conn);
}
/* 输出列名 */
nFields = PQnfields(res);
for (i = 0; i < nFields; i++)
printf("%-15s", PQfname(res, i));
printf("\n");
/* 输出具体行 */
for (i = 0; i < PQntuples(res); i++)
{
for (j = 0; j < nFields; j++){
printf("%-15s", PQgetvalue(res, i, j));
}
printf("\n");
}
/* 清空查询结果 */
PQclear(res);
/* 关闭连接 */
PQfinish(conn);
return 0;
}
使用如下命令进行编译:
cc -o testlibpq3 testlibpq3.c -L /home/lightdb/stage/lightdb-x/lib -lpq -I/home/lightdb/stage/lightdb-x/include -g
执行编译出来的二进制文件testlibpq3,得到的结果如下:
[lightdb@node101 testlibpq]$ ./testlibpq3
i t b
1 joe's place \x0001020304
2 ho there \x0403020100