什么是 Markdown ?

# Anima

<p align="center">
    <a href="https://github.com/biezhi/anima/wiki"><img src="screenshot/cover.png" width="623"/></a>
</p>

`Anima` allows you to query database like `SQL` and `Stream`.
a simple DSL syntax, supports multiple databases, integrates well with Java8, 
supports multiple relational mappings, and is a database manipulation tool.

**[Document](https://github.com/biezhi/anima/wiki)**

[![Travis Build](https://travis-ci.org/biezhi/anima.svg?branch=master)](https://travis-ci.org/biezhi/anima)
[![](https://img.shields.io/maven-central/v/io.github.biezhi/anima.svg)](https://mvnrepository.com/artifact/io.github.biezhi/anima)

## Feature

- Simple DSL 
- H2、MySQL、SQLite、PostgreSQL、Oracle、SqlServer 
- Paging support 
- Flexible configuration 
- Connection pool support
- Support `LocalDate`、`LocalDateTime`
- Support lambda expression
- Relationship (`hasOne`、`hasMany`、`belongsTo`)
- SQL performance statistics
- Based Java8

# Usage

**Latest snapshot version**

> If you want to prioritize new features or some BUG fixes you can use it, you need to specify the snapshot repository in `pom.xml`

```xml
<repository>
    <id>snapshots-repo</id>
    <url>https://oss.sonatype.org/content/repositories/snapshots</url>
    <releases>
        <enabled>false</enabled>
    </releases>
    <snapshots>
        <enabled>true</enabled>
    </snapshots>
</repository>

<dependency>
    <groupId>io.github.biezhi</groupId>
    <artifactId>anima</artifactId>
    <version>0.2.4-SNAPSHOT</version>
</dependency>
```

Here's the `RELEASE` version.

**As Gradle**

```java
compile 'io.github.biezhi:anima:0.2.3'
```

**As Maven**

```xml
<dependency>
    <groupId>io.github.biezhi</groupId>
    <artifactId>anima</artifactId>
    <version>0.2.2</version>
</dependency>
```

> 📒 Although `Anima` can also be used by adding a jar package, we do not recommend doing this.

## Examples

**Open Connection**

```java
// MySQL
Anima.open("jdbc:mysql://127.0.0.1:3306/demo", "root", "123456");

// SQLite
Anima.open("jdbc:sqlite:./demo.db");

// H2
Anima.open("jdbc:h2:file:~/demo;FILE_LOCK=FS;PAGE_SIZE=1024;CACHE_SIZE=8192", "sa", "");

// DataSource
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl(blade.environment().getOrNull("jdbc.url"));
dataSource.setUsername(blade.environment().getOrNull("jdbc.username"));
dataSource.setPassword(blade.environment().getOrNull("jdbc.password"));
Anima.open(dataSource);
```

> 📕 This operation only needs one time

```java
public class User extends Model {
    
    private Integer id;
    private String  userName;
    private Integer age;
    
    public User() {
    }
    
    public User(String userName, Integer age) {
        this.userName = userName;
        this.age = age;
    }
    
}
```

Table Structure

```sql
CREATE TABLE `users` (
  `id` IDENTITY PRIMARY KEY,
  `user_name` varchar(50) NOT NULL,
  `age` int(11)
)
```

### Query

```java
long count = select().from(User.class).count();
// SELECT COUNT(*) FROM users

long count = select().from(User.class).where("age > ?", 15).isNotNull("user_name").count();
// SELECT COUNT(*) FROM users WHERE age > ? AND user_name IS NOT NULL

User user = select().from(User.class).byId(2);
// SELECT * FROM users WHERE id = ?

List<User> users = select().from(User.class).byIds(1, 2, 3);
// SELECT * FROM users WHERE id IN (?, ?, ?)

String name = select().bySQL(String.class, "select user_name from users limit 1").one();

List<String> names = select().bySQL(String.class, "select user_name from users limit ?", 3);

List<User> users = select().from(User.class).all();
// SELECT * FROM users

List<User> users = select().from(User.class).like("user_name", "%o%").all();
// SELECT * FROM users WHERE user_name LIKE ?
```

**Limit**

```java
List<User> users = select().from(User.class).order("id desc").limit(5);
// SELECT * FROM users ORDER BY id desc
```

**Paging**

```java
Page<User> userPage = select().from(User.class).order("id desc").page(1, 3);
// SELECT * FROM users ORDER BY id desc LIMIT ?, ?
```

**Map**

```java
select().from(User.class).map(User::getUserName).limit(3).collect(Collectors.toList());
```

**Filter**

```java
select().from(User.class).filter(u -> u.getAge() > 10).collect(Collectors.toList());
```

**Lambda**

```java
User user = select().from(User.class).where(User::getUserName).eq("jack").one();
// SELECT * FROM users WHERE user_name = ?
```

```java
List<User> user = select().from(User.class)
                .where(User::getUserName).notNull()
                .and(User::getAge).gt(10)
                .all();
// SELECT * FROM users WHERE user_name IS NOT NULL AND age > ?
```

```java
select().from(User.class).order(User::getId, OrderBy.DESC).order(User::getAge, OrderBy.ASC).all();
// SELECT * FROM users ORDER BY  id DESC, age ASC
```

**Join**

```java
@Table(name = "order_info")
@Data
public class OrderInfo extends Model {

    private Long id;

    private Integer uid;

    @Column(name = "productname")
    private String productName;

    private LocalDateTime createTime;

    @Ignore
    private User user;
    
    @Ignore
    private Address address;

}
```

```java
// HasOne
OrderInfo orderInfo = select().from(OrderInfo.class)
        .join(
            Joins.with(Address.class).as(OrderInfo::getAddress)
                 .on(OrderInfo::getId, Address::getOrderId)
        ).byId(3);

orderInfo = select().from(OrderInfo.class)
        .join(
            Joins.with(Address.class).as(OrderInfo::getAddress)
                 .on(OrderInfo::getId, Address::getOrderId)
        )
        .join(
                Joins.with(User.class).as(OrderInfo::getUser)
                        .on(OrderInfo::getUid, User::getId)
        ).byId(3);

// ManyToOne
orderInfo = select().from(OrderInfo.class)
        .join(
            Joins.with(User.class).as(OrderInfo::getUser)
                 .on(OrderInfo::getUid, User::getId)
        ).byId(3);

// OneToMany
UserDto userDto = select().from(UserDto.class).join(
            Joins.with(OrderInfo.class).as(UserDto::getOrders)
                 .on(UserDto::getId, OrderInfo::getUid)
        ).byId(1);
```

### Insert

```java
Integer id = new User("biezhi", 100).save().asInt();
// INSERT INTO users(id,user_name,age) VALUES (?,?,?)
```

or

```java
Anima.save(new User("jack", 100));
```

**Batch Save**

```java
List<User> users = new ArrayList<>();
users.add(new User("user1", 10));
users.add(new User("user2", 11));
users.add(new User("user3", 12));
Anima.saveBatch(users);
```

> 📘 This operation will begin a transaction and rollback when there is a transaction that is unsuccessful.

### Update

```java
int result  = update().from(User.class).set("user_name", newName).where("id", 1).execute();
// UPDATE users SET username = ? WHERE id = ?
```

or

```java
int result = update().from(User.class).set("user_name", newName).where("id", 1).execute();
// UPDATE users SET user_name = ? WHERE id = ?
```

or

```java
User user = new User();
user.setId(1);
user.setUserName("jack");
user.update();
// UPDATE users SET user_name = ? WHERE id = ?
```

```java
update().from(User.class).set(User::getUserName, "base64").updateById(2);
```

```java
update().from(User.class).set(User::getUserName, "base64").where(User::getId).eq(2).execute();
```

### Delete

```java
int result = delete().from(User.class).where("id", 1).execute();
// DELETE FROM users WHERE id = ?
```

or

```java
User user = new User();
user.setAge(15);
user.setUserName("jack");
user.delete();
// DELETE FROM users WHERE user_name = ? and age = ?
```

```java
delete().from(User.class).where(User::getId).deleteById(3);
delete().from(User.class).where(User::getId).eq(1).execute();
delete().from(User.class).where(User::getAge).lte(20).execute();
```

### Transaction

```java
Anima.atomic(() -> {
    int a = 1 / 0;
    new User("apple", 666).save();
}).catchException(e -> Assert.assertEquals(ArithmeticException.class, e.getClass()));
```

> 📗 `Anima` uses the `atomic` method to complete a transaction. normally, the code will not throw an exception. 
> when a `RuntimeException` is caught, the transaction will be `rollback`.

## Test Code

See [here](https://github.com/biezhi/anima/tree/master/src/test/java/io/github/biezhi/anima)

## License

Apache2

什么是 Markdown ?

它的优点

  • 专注你的文字内容而不是排版样式,安心写作。
  • 轻松的导出 HTML、PDF 和本身的 .md 文件。
  • 纯文本内容,兼容所有的文本编辑器与字处理软件。
  • 随时修改你的文章版本,不必像文字处理软件生成若干文件版本导致混乱。
  • 可读、直观、学习成本低。

什么是 Markdown ?

使用 markdown 的误区

We believe that writing is about content, about what you want to say – not about fancy formatting.

我们坚信写作写的是内容,所思所想,而不是花样格式。
Ulysses for Mac

什么是 Markdown ?

支持的编辑器

在线

Windows

Mac

什么是 Markdown ?

markdown 语法

# 一级标题

## 二级标题

### 三级标题
## 无序列表

* 王爵的技术小黑屋
* 萌新 UP 主
* 不会写代码的程序员

## 有序列表

1. 我们都是地球人
2. 为啥你就不会 markdown?
3. 看完还不会就要被安排
## 链接的写法

[王爵的技术小黑屋](https://www.youtube.com/biezhi)


## 带 Title

[王爵的技术小黑屋](https://www.youtube.com/biezhi "此处可能有炸弹")

什么是 Markdown ?

markdown 语法

## 图片

![](https://i.loli.net/2018/07/19/5b509930126d1.jpg)

## 带 Title

![alt](https://i.loli.net/2018/07/19/5b509930126d1.jpg "嘤嘤嘤")

## 引用方式

![alt][img01]


[img01]: https://i.loli.net/2018/07/19/5b5099f425674.jpg "会不会markdown"

什么是 Markdown ?

markdown 语法

> 澳门首家线上赌场,美女荷官在线发牌!
### 面朝大海,春暖花开

> 从明天起,做一个幸福的人   
> 喂马、劈柴,周游世界  
> 从明天起,关心粮食和蔬菜  
> 我有一所房子,面朝大海,春暖花开  
> 从明天起,和每一个亲人通信  
> 告诉他们我的幸福  
> 那幸福的闪电告诉我的  
> 我将告诉每一个人  
> 给每一条河每一座山取一个温暖的名字  
> 陌生人,我也为你祝福  
> 愿你有一个灿烂的前程  
> 愿你有情人终成眷属  
> 愿你在尘世获得幸福  
> 我只愿面朝大海,春暖花开  

多行引用

**粗体**

__粗体__


*看,我斜了没*

_真的很斜_

***粗体+斜体***

~~此处的故事只能用泪水掩盖~~

什么是 Markdown ?

markdown 语法

# 群里单身女生名单

| 姓名   | 年龄 |    三围    |
| ----- |:----:| ----------:|
| 罗欲凤 | 18   | 18, 27, 30 |
| 秋刀鱼 | 26   | 28, 25, 33 |
| 窝不行 | 22   | 23, 28, 35 |
`单行代码引用`


```go
package main

import "fmt"

func main(){

   fmt.Println("王爵的技术小黑屋");

}
```
分割线

***

什么是 Markdown?

By biezhi

什么是 Markdown?

  • 2,277