O LindormTable é compatível com o protocolo MySQL, o que permite usar o framework de Mapeamento Objeto-Relacional (ORM) MyBatis para criar aplicações Java. O MyBatis separa o SQL do código da aplicação ao permitir a definição da lógica de acesso a dados em interfaces de mapper, mantendo a lógica de negócios livre de SQL embutido.
Ao concluir este tutorial, você terá:
Adicionado as dependências do MyBatis e do driver JDBC do MySQL a um projeto Maven
Configurado o arquivo
mybatis-config.xmlpara conexão com o LindormTableDefinido uma interface de mapper com operações de criação, leitura, upsert e exclusão
Executado uma demonstração funcional no LindormTable
Pré-requisitos
Antes de começar, verifique se você possui:
O recurso de compatibilidade com MySQL ativado na sua instância do LindormTable. Para mais detalhes, consulte Ativar o recurso de compatibilidade com MySQL.
JDK 1.8 ou posterior instalado
Seu endereço IP de cliente adicionado à lista de permissões da sua instância do Lindorm. Para mais detalhes, consulte Configurar listas de permissões.
Configure o projeto
Etapa 1: Adicione as dependências
No seu projeto Maven, adicione as seguintes dependências ao bloco dependencies no arquivo pom.xml:
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.14</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.3.0</version>
</dependency>
Etapa 2: Configure a conexão
Na pasta resources, crie o arquivo mybatis-config.xml com as configurações de conexão para o LindormTable:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://<MySQL-compatible endpoint>:33060/<database>?sslMode=disabled&allowPublicKeyRetrieval=true&useServerPrepStmts=true&useLocalSessionState=true&rewriteBatchedStatements=true&cachePrepStmts=true&prepStmtCacheSize=100&prepStmtCacheSqlLimit=50000000"/>
<property name="username" value="<username>"/>
<property name="password" value="<password>"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper class="org.example.UserMapper"/>
</mappers>
</configuration>
Substitua os seguintes espaços reservados:
|
Espaço reservado |
Descrição |
|
|
Endpoint compatível com MySQL da sua instância. Para obter esse valor, consulte Visualizar endpoints. |
|
|
Nome do banco de dados para conexão. Se omitido, o cliente se conecta ao banco de dados padrão. |
|
|
Nome de usuário do banco de dados. |
|
|
Senha do banco de dados. Para redefini-la, consulte Alterar senha de usuário. |
Escolha do endpoint adequado
|
Tipo de acesso |
Endpoint a ser usado |
|
A partir de uma instância do Elastic Compute Service (ECS) na mesma Virtual Private Cloud (VPC) |
Endereço VPC do endpoint compatível com MySQL |
|
Via internet |
Endereço público do endpoint compatível com MySQL |
Se sua aplicação for executada em uma instância ECS, use o endpoint VPC para garantir maior segurança e menor latência. Para conectar via internet, ative primeiro o endpoint público: no console, acesse Database Connection > Wide Table Engine e clique em Enable Public Endpoint.
Para obter detalhes sobre os parâmetros da string de conexão e como eles melhoram o desempenho, consulte Configuração de conexão.
Etapa 3: Defina o modelo de dados
Crie uma classe User para representar as linhas da tabela de demonstração:
package org.example;
import java.nio.charset.StandardCharsets;
import java.sql.Date;
import java.sql.Timestamp;
public class User {
private int userId;
private String userName;
private double height;
private long score;
private Timestamp createTime;
private Date birthday;
private byte[] digest;
public User(int userId, String userName, double height, long score,
Timestamp createTime, Date birthday, byte[] digest) {
this.userId = userId;
this.userName = userName;
this.height = height;
this.score = score;
this.createTime = createTime;
this.birthday = birthday;
this.digest = digest;
}
public int getUserId() { return userId; }
public void setUserId(int userId) { this.userId = userId; }
public String getUserName() { return userName; }
public void setUserName(String userName) { this.userName = userName; }
public double getHeight() { return height; }
public void setHeight(double height) { this.height = height; }
public long getScore() { return score; }
public void setScore(long score) { this.score = score; }
public Timestamp getCreateTime() { return createTime; }
public void setCreateTime(Timestamp createTime) { this.createTime = createTime; }
public Date getBirthday() { return birthday; }
public void setBirthday(Date birthday) { this.birthday = birthday; }
public byte[] getDigest() { return digest; }
public void setDigest(byte[] digest) { this.digest = digest; }
@Override
public String toString() {
return "User{" + "userId=" + userId + ", userName='" + userName + '\'' +
", height=" + height + ", score=" + score + ", createTime=" + createTime +
", birthday=" + birthday + ", digest=" + new String(digest, StandardCharsets.UTF_8) + '}';
}
}
Etapa 4: Crie o mapper
Crie uma interface UserMapper. Cada método tem uma anotação com a instrução SQL correspondente executada no LindormTable:
package org.example;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import java.util.List;
public interface UserMapper {
@Update("create table if not exists demo_user(`id` INT, `name` VARCHAR, `height` DOUBLE, `score` BIGINT, `createtime` TIMESTAMP, `birthday` DATE, digest VARBINARY, primary key(id))")
void createUserTable();
@Update("drop table if exists demo_user")
void dropUserTable();
@Insert("upsert into demo_user(`id`,`name`,`height`,`score`,`createtime`,`birthday`,`digest`) values(#{userId},#{userName},#{height},#{score},#{createTime},#{birthday},#{digest})")
int upsertUser(User user);
@Delete("delete from demo_user where `id` = #{userId}")
int deleteUser(@Param("userId") int userId);
@Select("select * from demo_user where `id` = #{userId}")
User selectOneUser(@Param("userId") int userId);
@Select("select * from demo_user")
List<User> selectAllUser();
}
Todas as operações de escrita usam upsert em vez de insert — esta é a sintaxe preferencial do LindormTable para inserir ou atualizar linhas em uma única instrução.
Etapa 5: Escreva o código da aplicação
Carregue a configuração, abra uma SqlSession e execute operações CRUD por meio do mapper:
package org.example;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.sql.Date;
import java.sql.Timestamp;
public class MybatisDemo {
public static void main(String[] args) throws Exception {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
try (SqlSession session = sqlSessionFactory.openSession()) {
UserMapper mapper = session.getMapper(UserMapper.class);
// Create the table
mapper.createUserTable();
// Verify the table is empty
System.out.println(mapper.selectAllUser());
// Insert two users
User user1 = new User(1, "zhangsan", 1.8, 100,
new Timestamp(System.currentTimeMillis()),
Date.valueOf("1995-03-02"),
"hello".getBytes(StandardCharsets.UTF_8));
User user2 = new User(2, "lisi", 1.7, 90,
new Timestamp(System.currentTimeMillis()),
Date.valueOf("1996-08-02"),
"world".getBytes(StandardCharsets.UTF_8));
mapper.upsertUser(user1);
mapper.upsertUser(user2);
// Query all users and a single user
System.out.println(mapper.selectAllUser());
System.out.println(mapper.selectOneUser(1));
// Delete user1 and verify
mapper.deleteUser(1);
System.out.println(mapper.selectAllUser());
// Update user2's score using upsert and verify
user2.setScore(99);
mapper.upsertUser(user2);
System.out.println(mapper.selectAllUser());
// Clean up
mapper.dropUserTable();
}
}
}
Exemplo completo
Baixe o projeto de exemplo completo: mybatis-demo.zip.
Após uma execução bem-sucedida, a saída será semelhante a esta:
[User{userId=1, userName='zhangsan', height=1.8, score=100, createTime=2023-12-02 09:39:17.63, birthday=1995-03-02, digest=hello}, User{userId=2, userName='lisi', height=1.7, score=90, createTime=2023-12-02 09:39:17.63, birthday=1996-08-02, digest=world}]
User{userId=1, userName='zhangsan', height=1.8, score=100, createTime=2023-12-02 09:39:17.63, birthday=1995-03-02, digest=hello}
[User{userId=2, userName='lisi', height=1.7, score=90, createTime=2023-12-02 09:39:17.63, birthday=1996-08-02, digest=world}]
[User{userId=2, userName='lisi', height=1.7, score=99, createTime=2023-12-02 09:39:17.63, birthday=1996-08-02, digest=world}]
Perguntas frequentes
Por que o método selectAllUser() lança a exceção "ExecutionPlaceholder cannot be cast to java.util.List"?
O erro completo é:
### Cause: java.lang.ClassCastException: class org.apache.ibatis.executor.ExecutionPlaceholder cannot be cast to class java.util.List
Os objetos SqlSession e Mapper no MyBatis não são seguros para threads. Esse erro ocorre quando múltiplas threads acessam simultaneamente a mesma SqlSession ou o mesmo Mapper. Certifique-se de que cada thread crie sua própria SqlSession e obtenha seu próprio mapper a partir dela.
Qual a diferença entre os espaços reservados #{} e ${}?
|
** |
** |
|
|
Implementação |
Vinculação de parâmetros pré-compilados via JDBC |
Substituição direta de string |
|
Risco de injeção de SQL |
Nenhum |
Sim |
|
Desempenho |
Alto — o plano de execução é reutilizável |
Baixo — cada instrução é analisada novamente |
|
Quando usar |
Para vincular valores dinâmicos, como condições |
Para injetar fragmentos SQL, como nomes de tabelas ou colunas |
Use #{} para todos os valores de parâmetros. Reserve ${} apenas para estruturas SQL dinâmicas em que a vinculação parametrizada não for possível.
O espaço reservado #{} só gera uma consulta verdadeiramente parametrizada quando useServerPrepStmts=true está definido na string de conexão. Sem essa configuração, o driver JDBC do MySQL reescreve a instrução como um literal de string em tempo de execução, ignorando a pré-compilação. Para mais detalhes, consulte Configuração de conexão.
Próximos passos
Documentação do MyBatis — sintaxe XML de mapper, SQL dinâmico e configurações avançadas
Conexão via Java JDBC — parâmetros de string de conexão e ajuste de desempenho para o LindormTable