A Preliminary Study of CrateDB (3): JDBC

Table of contents

compatibility

Add Maven dependency

Use Java JDBC native way

Preparation

Code

data manipulation

code segment

Spring+CrateDB method

configuration file

code segment

Problems with DataSources

Spring+MyBatis+CrateDB method

configuration file

code segment


Other articles in this series:

A Preliminary Study of CrateDB (1): Docker Deployment of CrateDB Cluster

CrateDB Preliminary Study (2): PARTITION, SHARDING AND REPLICATION

CrateDB Preliminary Study (4): Optimistic Concurrency Control (Optimistic Concurrency Control)


This article briefly introduces connecting to CrateDB through JDBC and performing simple data operations.

The process is roughly similar to connecting to other databases (such as mysql), and you need to pay attention to driver and db version compatibility issues

compatibility

The jdbc driver and CrateDB version need to comply with the following compatibility

Notice:

  1. When the CrateDB version is later than 2.1.x, a user name must be provided when connecting through jdbc, and the default is crate
  2. In terms of implementation details , the data source cannot be used ( DataSource  is not supported. ) There are doubts here, see the Spring+CrateDB section

Add Maven dependency

  • Add bintray repository

<repository>
        <snapshots>
             <enabled>false</enabled>
        </snapshots>
        <id>cratedbmvn</id>
        <name>bintray</name>
        <url>http://dl.bintray.com/crate/crate</url>
  </repository>

  • Add crate-jdbc dependency in pom.xml (register CrateDB JDBC driver)

<!-- https://mvnrepository.com/artifact/io.crate/crate-jdbc -->
 <dependency>
      <groupId>io.crate</groupId>
      <artifactId>crate-jdbc</artifactId>
       <version>2.3.1</version>
  </dependency>

Use Java JDBC native way

Preparation

  • Start an instance via docker

sudo docker run --name=crate-test1 -p 4211:4200 -p 5432:5432 --rm -d crate

Note: 5432 is the default port for jdbc connection, see parameter psql.port for details

  • Add a new test table

Code

Use the properties method to establish the jdbc link. It has been mentioned in the compatibility description above that the user parameter (default crate ) needs to be set for the high version db.

Properties properties = new Properties();
properties.put("user", "crate");
Connection conn = DriverManager.getConnection(
                "crate://localhost:5432/", 
                properties);

Or use CrateDriver (check the validity of the connection URL)

Properties properties = new Properties();
properties.put("user", "crate");
// io.crate.client.jdbc.CrateDriver		
CrateDriver driver = new CrateDriver();
Connection conn = driver.connect("crate://localhost:5432/", properties);

The default schema is doc, if you want to switch:conn.setSchema("my_schema");

参数:

  • user: DB version 2.1.x or later must be set, if no custom database user has been set, it will be CrateDB superuser, namely crate
  • strict: When set to false, if features not supported by CrateDB (such as transactions) are used, the program will not throw an exception and execute silently; when set to true, an exception will be thrown. The default is false.
  • For other parameters, see the official documentation

data manipulation

Because the official said that datasource ( implementation details ) cannot be used , consider using the most primitive way for data manipulation (there is a question here, in fact, datasource can be used, see the Spring+CrateDB section below)

insert

PreparedStatement ps2 =	conn.prepareStatement("INSERT INTO test_tab VALUES(2,'cj')"); 
ps2.execute();

Inquire

PreparedStatement ps = conn.prepareStatement("select name from test_tab where id=1");
ResultSet rs = ps.executeQuery();
while (rs.next()) {
	String name = rs.getString("name");
	System.out.println("rs: " + name);
}

About FetchSize settings

Setting the fetch size can improve the query reading speed. To use the fetch size correctly in CrateDB, you need to set autoCommit to false

 * We are allowed to disable autoCommit (= manual commit) if strict mode is not enabled.
 * Manual commit is required for {@link org.postgresql.jdbc.PgStatement#setFetchSize(int)} to work correctly!
 * If autoCommit is true {@link org.postgresql.jdbc.PgStatement#executeInternal(CachedQuery, ParameterList, int)}
 * will never set the QueryExecutor.QUERY_FORWARD_CURSOR flag and therefore fetch all results at once instead of
 * batching them.

Official sample code

Before the query statement.setFetchSize(10);

 /**
 * fetch size and execution flag is correctly appied if autoCommit == false
 */
@Test
public void testFetchSizeNotIgnoredIfManualCommit() throws Exception {
    try (Connection connection = DriverManager.getConnection(getConnectionString())) {
        connection.setAutoCommit(false);
        try (Statement statement = connection.createStatement()) {
            statement.setFetchSize(10);
            statement.execute("select * from sys.summits");
            ResultSet rs = statement.getResultSet();
            assertEquals(10, rs.getFetchSize());
            Field rowsField = rs.getClass().getDeclaredField("rows");
            rowsField.setAccessible(true);
            List rows = (List) rowsField.get(rs);
            assertEquals(10, rows.size());
        }
    }
}

code segment

package nb.test.cratedb;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

/**
 * Hello world!
 *
 */
public class App {
	public static void main(String[] args) throws InterruptedException, SQLException {

		Connection conn = null;
		try {
			Properties properties = new Properties();
			properties.put("user", "crate");
			conn = DriverManager.getConnection("crate://localhost:5432/", properties);
			System.out.println("Connection: " + conn);

			PreparedStatement ps2 =	conn.prepareStatement("INSERT INTO test_tab VALUES(2,'cj')");
			ps2.execute();

			PreparedStatement ps = conn.prepareStatement("select id, name from test_tab");
			ResultSet rs = ps.executeQuery();
			while (rs.next()) {
				int id = rs.getInt("id");
				String name = rs.getString("name");
				System.out.println("id: " + id + ",   name: " + name);
			}

		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			conn.close();
		}

		Thread.sleep(10000);

	}
}

output

Official crate-jdbc usage example

Spring+CrateDB method

Use the original Spring-jdbc way to connect to CrateDB

configuration file

Add data source dependency jar package

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-dbcp2</artifactId>
    <version>2.6.0</version>
</dependency>

db.properties

Configure driver class name, url, user name (password is empty)

jdbc.driverClassName=io.crate.client.jdbc.CrateDriver
jdbc.url=crate://localhost:5432/
jdbc.username=crate
jdbc.password=

application.xml

Configure data source, java bean of JdbcTemplate

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://www.springframework.org/schema/beans" 
	xmlns:context="http://www.springframework.org/schema/context"   
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
     http://www.springframework.org/schema/context 
     http://www.springframework.org/schema/context/spring-context-4.0.xsd
     http://www.springframework.org/schema/aop
     http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
    
    
    <context:property-placeholder location="classpath:db.properties"/>
     
	<bean id="datasource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
		<property name="driverClassName" value="${jdbc.driverClassName}"></property>
		<property name="url" value="${jdbc.url}"></property>
		<property name="username" value="${jdbc.username}"></property>
		<property name="password" value="${jdbc.password}"></property>
		<property name="maxTotal" value="50" />
		<property name="maxWaitMillis" value="6000" />
		<property name="initialSize" value="10" />
		<property name="maxIdle" value="20"></property>
		<property name="minIdle" value="10" /> 
	</bean>
	
	<bean id="namedParameterJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
		<constructor-arg ref="datasource" />
	</bean>
	
</beans>

code segment

public static void main(String[] args) throws SQLException {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("application.xml");
		
		DataSource dbsource = (DataSource) ctx.getBean("datasource");
		NamedParameterJdbcTemplate namedTemplate = (NamedParameterJdbcTemplate) ctx.getBean("namedParameterJdbcTemplate");
		
		String sql = "SELECT id, name FROM doc.tmp1";
		Map<String, Object> paramsMap = new HashMap<String, Object>();
		SqlRowSet rowSet = namedTemplate.queryForRowSet(sql, paramsMap);
		while(rowSet.next()) {
			System.out.println("id: " + rowSet.getInt("id") + " , name: " + rowSet.getString("name"));
		}
	}

Problems with DataSources

Mentioned in the official CrateDB documentation

DataSource is not supported.

My understanding is that third-party data source jar packages can still be introduced to support, such as dbcp2 used in this example

To verify whether the data source really works, do a simple experiment:

In the above example, conn2 is closed, but it does not affect the query data of conn, indicating that conn2 and conn are indeed two different connections obtained from the data source.

Spring+MyBatis+CrateDB method

Introduce MyBatis as an ORM framework and test the connection based on the previous section

configuration file

Add the jar package of mybatis

<dependency>
	<groupId>org.mybatis</groupId>
	<artifactId>mybatis</artifactId>
	<version>3.4.5</version>
</dependency>

<dependency>
	<groupId>org.mybatis</groupId>
	<artifactId>mybatis-spring</artifactId>
	<version>1.3.2</version>
</dependency>

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration   
    PUBLIC "-//mybatis.org//DTD Config 3.0//EN"  
    "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<settings>
		<setting name="autoMappingUnknownColumnBehavior" value="WARNING" />
		<setting name="defaultStatementTimeout" value="25" />
	</settings>

	<typeAliases>
		<typeAlias type="nb.test.cratedb.User" alias="User" />
	</typeAliases>
</configuration>

Add the spring configuration file of mybatis

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
     http://www.springframework.org/schema/context 
     http://www.springframework.org/schema/context/spring-context-4.0.xsd
     http://www.springframework.org/schema/aop
     http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">

	<bean id="sqlSessionFactory"
		class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="datasource" />

		<property name="mapperLocations">
			<list>
				<value>classpath:nb/test/orm/*.xml</value>
			</list>
		</property>
		<property name="configLocation"
			value="classpath:mybatis-config.xml" />
	</bean>
	
	
	<bean id="mapperScannerConfigurerMotan" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="nb.test.orm" />
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
    </bean>

</beans>

code segment

Entity class

public class User implements Serializable {

	private static final long serialVersionUID = 2686795246219114561L;
	private int id;
	private String name;

    /* 忽略getter, setter等代码 */
}

Dao interface

@MapperScan
public interface UserDao {
	public User queryUserById(int id);
}

Mapper

<?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="nb.test.orm.UserDao">
  	
	<select id="queryUserById" parameterType="int" resultType="User">
		SELECT id, name  FROM doc.tmp1 t
			WHERE t.id = #{id}
	</select>
	
</mapper>

Service implementation, so simple that it can be ignored

@Service
public class UserService {

	@Autowired
	private UserDao userDao;
	
	public User getUser(int id) {
		return userDao.queryUserById(id);
	}
}

test code

public static void main(String[] args) {
		ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[]{"application.xml", "application-orm.xml"});
		UserService userService = (UserService) ctx.getBean("userService");
		User user = userService.getUser(1);
		System.out.println("User: " + user);
	}

Guess you like

Origin blog.csdn.net/gxf1027/article/details/104914382