Skip to content

Commit

Permalink
Fix the Errors that was founded by dividing CN examples document (#14373
Browse files Browse the repository at this point in the history
)
  • Loading branch information
Cheese authored Aug 11, 2023
1 parent 65eb0e6 commit 003f645
Show file tree
Hide file tree
Showing 7 changed files with 43 additions and 68 deletions.
2 changes: 1 addition & 1 deletion develop/dev-guide-choose-driver-or-orm.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ implementation 'org.mybatis:mybatis:3.5.9'
implementation 'mysql:mysql-connector-java:5.1.49'
```

For an example of using MyBatis to build a TiDB application, see [Build a simple CRUD app with TiDB and Mybatis](/develop/dev-guide-sample-application-java-mybatis.md).
For an example of using MyBatis to build a TiDB application, see [Build a simple CRUD app with TiDB and MyBatis](/develop/dev-guide-sample-application-java-mybatis.md).

</div>

Expand Down
51 changes: 13 additions & 38 deletions develop/dev-guide-sample-application-golang-gorm.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ See [Create a TiDB Serverless cluster](/develop/dev-guide-build-cluster-in-cloud
git clone https://github.com/pingcap-inc/tidb-example-golang.git
```

Compared with GORM, the go-sql-driver/mysql implementation might be not a best practice, because you need to write error handling logic, close `*sql.Rows` manually and cannot reuse code easily, which makes your code slightly redundant.

The following instructions take `v1.23.5` as an example.

To adapt TiDB transactions, write a toolkit [util](https://github.com/pingcap-inc/tidb-example-golang/tree/main/util) according to the following code:
Expand All @@ -54,49 +52,26 @@ To adapt TiDB transactions, write a toolkit [util](https://github.com/pingcap-in
package util

import (
"context"
"database/sql"
"gorm.io/gorm"
)

type TiDBSqlTx struct {
*sql.Tx
conn *sql.Conn
pessimistic bool
}

func TiDBSqlBegin(db *sql.DB, pessimistic bool) (*TiDBSqlTx, error) {
ctx := context.Background()
conn, err := db.Conn(ctx)
if err != nil {
return nil, err
// TiDBGormBegin start a TiDB and Gorm transaction as a block. If no error is returned, the transaction will be committed. Otherwise, the transaction will be rolled back.
func TiDBGormBegin(db *gorm.DB, pessimistic bool, fc func(tx *gorm.DB) error) (err error) {
session := db.Session(&gorm.Session{})
if session.Error != nil {
return session.Error
}

if pessimistic {
_, err = conn.ExecContext(ctx, "set @@tidb_txn_mode=?", "pessimistic")
session = session.Exec("set @@tidb_txn_mode=pessimistic")
} else {
_, err = conn.ExecContext(ctx, "set @@tidb_txn_mode=?", "optimistic")
}
if err != nil {
return nil, err
}
tx, err := conn.BeginTx(ctx, nil)
if err != nil {
return nil, err
session = session.Exec("set @@tidb_txn_mode=optimistic")
}
return &TiDBSqlTx{
conn: conn,
Tx: tx,
pessimistic: pessimistic,
}, nil
}

func (tx *TiDBSqlTx) Commit() error {
defer tx.conn.Close()
return tx.Tx.Commit()
}

func (tx *TiDBSqlTx) Rollback() error {
defer tx.conn.Close()
return tx.Tx.Rollback()
if session.Error != nil {
return session.Error
}
return session.Transaction(fc)
}
```

Expand Down
2 changes: 1 addition & 1 deletion develop/dev-guide-sample-application-golang-sql-driver.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ CREATE TABLE player (
);
```

`sqldriver.go` is the main body of the `sqldriver`. TiDB is highly compatible with the MySQL protocol, so you need to initialize a MySQL source instance `db, err := sql.Open("mysql", dsn)` to connect to TiDB. Then, you can use `dao.go` to read, edit, add, and delete data.
`sqldriver.go` is the main body of the `sqldriver`. Compared with GORM, the go-sql-driver/mysql implementation might be not a best practice, because you need to write error handling logic, close `*sql.Rows` manually and cannot reuse code easily, which makes your code slightly redundant. TiDB is highly compatible with the MySQL protocol, so you need to initialize a MySQL source instance `db, err := sql.Open("mysql", dsn)` to connect to TiDB. Then, you can use `dao.go` to read, edit, add, and delete data.

```go
package main
Expand Down
16 changes: 7 additions & 9 deletions develop/dev-guide-sample-application-java-hibernate.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ summary: Learn how to build a simple CRUD application with TiDB and Hibernate.

# Build a Simple CRUD App with TiDB and Hibernate

[Hibernate](https://hibernate.org/) is a popular open-source Java ORM, and it supports TiDB dialect starting from `v6.0.0.Beta2`, which fits TiDB features well.

This document describes how to use TiDB and Hibernate to build a simple CRUD application.

> **Note:**
Expand Down Expand Up @@ -44,7 +46,7 @@ git clone https://github.com/pingcap-inc/tidb-example-java.git

Compared with Hibernate, the JDBC implementation might be not a best practice, because you need to write error handling logic manually and cannot reuse code easily, which makes your code slightly redundant.

Hibernate is a popular open-source Java ORM, and it supports TiDB dialect starting from `v6.0.0.Beta2`, which fits TiDB features well. The following instructions take `v6.0.0.Beta2` as an example.
The following instructions take `v6.0.0.Beta2` as an example.

Change to the `plain-java-hibernate` directory:

Expand Down Expand Up @@ -335,11 +337,7 @@ public class HibernateExample

The following content introduces how to run the code step by step.

### Step 3.1 Table initialization

No need to initialize tables manually.

### Step 3.2 Modify parameters for TiDB Cloud
### Step 3.1 Modify parameters for TiDB Cloud

If you are using a TiDB Serverless cluster, modify the `hibernate.connection.url`, `hibernate.connection.username`, `hibernate.connection.password` in `hibernate.cfg.xml`.

Expand Down Expand Up @@ -403,20 +401,20 @@ In this case, you can modify the parameters as follows:
</hibernate-configuration>
```

### Step 3.3 Run
### Step 3.2 Run

To run the code, you can run `make build` and `make run` respectively:

```shell
make build # this command executes `mvn clean package`
make run # this command executes `java -jar target/plain-java-jdbc-0.0.1-jar-with-dependencies.jar`
make run # this command executes `java -jar target/plain-java-hibernate-0.0.1-jar-with-dependencies.jar`
```

Or you can use the native commands:

```shell
mvn clean package
java -jar target/plain-java-jdbc-0.0.1-jar-with-dependencies.jar
java -jar target/plain-java-hibernate-0.0.1-jar-with-dependencies.jar
```

Or run the `make` command directly, which is a combination of `make build` and `make run`.
Expand Down
36 changes: 19 additions & 17 deletions develop/dev-guide-sample-application-java-mybatis.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
---
title: Build a Simple CRUD App with TiDB and Mybatis
summary: Learn how to build a simple CRUD application with TiDB and Mybatis.
title: Build a Simple CRUD App with TiDB and MyBatis
summary: Learn how to build a simple CRUD application with TiDB and MyBatis.
---

<!-- markdownlint-disable MD024 -->
<!-- markdownlint-disable MD029 -->

# Build a Simple CRUD App with TiDB and Mybatis
# Build a Simple CRUD App with TiDB and MyBatis

This document describes how to use TiDB and Mybatis to build a simple CRUD application.
[MyBatis](https://mybatis.org/mybatis-3/index.html) is a popular open-source Java class persistence framework.

This document describes how to use TiDB and MyBatis to build a simple CRUD application.

> **Note:**
>
Expand Down Expand Up @@ -42,9 +44,9 @@ See [Create a TiDB Serverless cluster](/develop/dev-guide-build-cluster-in-cloud
git clone https://github.com/pingcap-inc/tidb-example-java.git
```

Compared with [Mybatis](https://mybatis.org/mybatis-3/index.html), the JDBC implementation might be not a best practice, because you need to write error handling logic manually and cannot reuse code easily, which makes your code slightly redundant.
Compared with [MyBatis](https://mybatis.org/mybatis-3/index.html), the JDBC implementation might be not a best practice, because you need to write error handling logic manually and cannot reuse code easily, which makes your code slightly redundant.

Mybatis is a popular open-source Java class persistence framework. The following uses [MyBatis Generator](https://mybatis.org/generator/quickstart.html) as a Maven plugin to generate the persistence layer code.
The following uses [MyBatis Generator](https://mybatis.org/generator/quickstart.html) as a Maven plugin to generate the persistence layer code.

Change to the `plain-java-mybatis` directory:

Expand Down Expand Up @@ -84,9 +86,9 @@ The automatically generated files are:

- `src/main/java/com/pingcap/model/Player.java`: The `Player` entity class.
- `src/main/java/com/pingcap/model/PlayerMapper.java`: The interface of `PlayerMapper`.
- `src/main/resources/mapper/PlayerMapper.xml`: The XML mapping of `Player`. Mybatis uses this configuration to automatically generate the implementation class of the `PlayerMapper` interface.
- `src/main/resources/mapper/PlayerMapper.xml`: The XML mapping of `Player`. MyBatis uses this configuration to automatically generate the implementation class of the `PlayerMapper` interface.

The strategy for generating these files is written in `mybatis-generator.xml`, which is the configuration file for [Mybatis Generator](https://mybatis.org/generator/quickstart.html). There are comments in the following configuration file to describe how to use it.
The strategy for generating these files is written in `mybatis-generator.xml`, which is the configuration file for [MyBatis Generator](https://mybatis.org/generator/quickstart.html). There are comments in the following configuration file to describe how to use it.

```xml
<!DOCTYPE generatorConfiguration PUBLIC
Expand Down Expand Up @@ -146,7 +148,7 @@ The strategy for generating these files is written in `mybatis-generator.xml`, w
Java code mapper interface file will be generated at ${targetProject}/${targetPackage}
javaClientGenerator.type (context.targetRuntime is MyBatis3):
This attribute indicated Mybatis how to implement interface.
This attribute indicated MyBatis how to implement interface.
It has ANNOTATEDMAPPER / MIXEDMAPPER / XMLMAPPER 3 selection to choice.
-->
<javaClientGenerator type="XMLMAPPER" targetPackage="com.pingcap.model" targetProject="src/main/java"/>
Expand Down Expand Up @@ -200,7 +202,7 @@ Once included in the Maven plugin, you can delete the old generated files and ma
>
> The property `configuration.overwrite` in `mybatis-generator.xml` only ensures that the generated Java code files are overwritten. But the XML mapping files are still written as appended. Therefore, it is recommended to delete the old file before Mybaits Generator generating a new one.
`Player.java` is a data entity class file generated using Mybatis Generator, which is a mapping of database tables in the application. Each property of the `Player` class corresponds to a field in the `player` table.
`Player.java` is a data entity class file generated using MyBatis Generator, which is a mapping of database tables in the application. Each property of the `Player` class corresponds to a field in the `player` table.

```java
package com.pingcap.model;
Expand Down Expand Up @@ -248,7 +250,7 @@ public class Player {
}
```

`PlayerMapper.java` is a mapping interface file generated using Mybatis Generator. This file only defines the interface, and the implementation classes of interface are automatically generated using XML or annotations.
`PlayerMapper.java` is a mapping interface file generated using MyBatis Generator. This file only defines the interface, and the implementation classes of interface are automatically generated using XML or annotations.

```java
package com.pingcap.model;
Expand All @@ -270,7 +272,7 @@ public interface PlayerMapper {
}
```

`PlayerMapper.xml` is a mapping XML file generated using Mybatis Generator. Mybatis uses this to automatically generate the implementation class of the `PlayerMapper` interface.
`PlayerMapper.xml` is a mapping XML file generated using MyBatis Generator. MyBatis uses this to automatically generate the implementation class of the `PlayerMapper` interface.

```xml
<?xml version="1.0" encoding="UTF-8"?>
Expand Down Expand Up @@ -348,7 +350,7 @@ public interface PlayerMapper {
</mapper>
```

Since Mybatis Generator needs to generate the source code from the table definition, the table needs to be created first. To create the table, you can use `dbinit.sql`.
Since MyBatis Generator needs to generate the source code from the table definition, the table needs to be created first. To create the table, you can use `dbinit.sql`.

```sql
USE test;
Expand All @@ -362,7 +364,7 @@ CREATE TABLE player (
);
```

Split the interface `PlayerMapperEx` additionally to extend from `PlayerMapper` and write a matching `PlayerMapperEx.xml` file. Avoid changing `PlayerMapper.java` and `PlayerMapper.xml` directly. This is to avoid overwrite by Mybatis Generator.
Split the interface `PlayerMapperEx` additionally to extend from `PlayerMapper` and write a matching `PlayerMapperEx.xml` file. Avoid changing `PlayerMapper.java` and `PlayerMapper.xml` directly. This is to avoid overwrite by MyBatis Generator.

Define the added interface in `PlayerMapperEx.java`:

Expand Down Expand Up @@ -419,7 +421,7 @@ Define the mapping rules in `PlayerMapperEx.xml`:
</mapper>
```

`PlayerDAO.java` is a class used to manage data, in which `DAO` means [Data Access Object](https://en.wikipedia.org/wiki/Data_access_object). The class defines a set of data manipulation methods for writing data. In it, Mybatis encapsulates a large number of operations such as object mapping and CRUD of basic objects, which greatly simplifies the code.
`PlayerDAO.java` is a class used to manage data, in which `DAO` means [Data Access Object](https://en.wikipedia.org/wiki/Data_access_object). The class defines a set of data manipulation methods for writing data. In it, MyBatis encapsulates a large number of operations such as object mapping and CRUD of basic objects, which greatly simplifies the code.

```java
package com.pingcap.dao;
Expand Down Expand Up @@ -613,7 +615,7 @@ The following content introduces how to run the code step by step.

### Step 3.1 Table initialization

When using Mybatis, you need to initialize the database tables manually. If you are using a local cluster, and MySQL client has been installed locally, you can run it directly in the `plain-java-mybatis` directory:
When using MyBatis, you need to initialize the database tables manually. If you are using a local cluster, and MySQL client has been installed locally, you can run it directly in the `plain-java-mybatis` directory:

```shell
make prepare
Expand Down Expand Up @@ -738,4 +740,4 @@ Or run the `make` command directly, which is a combination of `make prepare`, `m

## Step 4. Expected output

[Mybatis Expected Output](https://github.com/pingcap-inc/tidb-example-java/blob/main/Expected-Output.md#plain-java-mybatis)
[MyBatis Expected Output](https://github.com/pingcap-inc/tidb-example-java/blob/main/Expected-Output.md#plain-java-mybatis)
2 changes: 1 addition & 1 deletion develop/dev-guide-sample-application-python-peewee.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ trade_example()

Compared with using drivers directly, peewee provides an abstraction for the specific details of different databases when you create a database connection. In addition, peewee encapsulates some operations such as session management and CRUD of basic objects, which greatly simplifies the code.

The `Player` class is a mapping of a table to attributes in the application. Each attribute of `Player` corresponds to a field in the `player` table. To provide SQLAlchemy with more information, the attribute is defined as `id = Column(String(36), primary_key=True)` to indicate the field type and its additional attributes. For example, `id = Column(String(36), primary_key=True)` indicates that the `id` attribute is `String` type, the corresponding field in database is `VARCHAR` type, the length is `36`, and it is a primary key.
The `Player` class is a mapping of a table to attributes in the application. Each attribute of `Player` corresponds to a field in the `player` table. To provide peewee with more information, the attribute is defined as `id = CharField(max_length=36, primary_key=True)` to indicate the field type and its additional attributes. For example, `id = CharField(max_length=36, primary_key=True)` indicates that the `id` attribute is `String` type, the corresponding field in database is `VARCHAR` type, the length is `36`, and it is a primary key.

For more information about how to use peewee, refer to [peewee documentation](http://docs.peewee-orm.com/en/latest/).

Expand Down
2 changes: 1 addition & 1 deletion develop/dev-guide-third-party-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ If you encounter problems when connecting to TiDB using the tools listed in this
<td>v3.5.10</td>
<td>Full</td>
<td>N/A</td>
<td><a href="/tidb/dev/dev-guide-sample-application-java-mybatis">Build a Simple CRUD App with TiDB and Mybatis</a></td>
<td><a href="/tidb/dev/dev-guide-sample-application-java-mybatis">Build a Simple CRUD App with TiDB and MyBatis</a></td>
</tr>
<tr>
<td><a href="https://spring.io/projects/spring-data-jpa/" target="_blank" referrerpolicy="no-referrer-when-downgrade">Spring Data JPA</a></td>
Expand Down

0 comments on commit 003f645

Please sign in to comment.