# Elab-db 使用介绍

## 更新介绍:

#### 版本号: 2.0.4.12
- 通用接口类IBaseDaoSupport新增方法`selectByObjectToCount`方法，用于单表查询总数
- 新增动态处理参数`ListDynamicSearch`，用于处理sort、limit、>=、<=、in函数处理
    ```java
    List<String> list = new ArrayList<>();
    list.add("1");
    list.add("2");
    list.add("3");
    ListDynamicSearch listDynamicSearch = ListDynamicSearch.newBuilder().addInSearches("id", list).build();
    List<TTest> tTests = testDao.getTestList2(test, listDynamicSearch);
    ```
- 每个方法新增`@FieldParam注`解，用于传递普通非Model对象处理
    ```java
    public TTest selectByName(@FieldParam("id") String id, @FieldParam("username") String username);
    ```
- 新增`@EnableElabDB`注解，适用于SpringBoot启用DB配置
#### 版本号: 2.0.4.10

- 新增批量新增功能
- 批量修改，参考`IBaseDaoSupport`
- 新增SQL检测功能
  - join 表超过3张会提示警告。
  - union 超过3张会提示警告。

#### 版本号 : 2.0.4.4
- 增加通用的service业务处理
	- 接口继承 : ICommonService<?>
	- 实现继承 : CommonServiceAdaptor<?>
**业务特殊可以通过重写来覆盖**

- 查询分页结果的时候,可以指定order by
```
pageModel.setOrderby("order by id desc");
```

- 如果涉及多个库的增删改查操作如何指定库?
**通过catalog来指定,效果是在生成的sql语句中表名会变成 mvp.file 查询**
```
@Table(name = "file",catalog = "mvp")
```


修复若干BUG.


## 功能描述
- 单表的增删改差不需要写单独的SQL
- 动态参数通过$指定,但前提是必须要有值
- DAO只需要接口,就能够找到对应的sql文件中的sql
- 实现基于一对多的关系映射
- 参数可以通过对象或者Map的方式指定,SQL文件中的参数可以自由指定,没有限制

### 配置
基于注解配置:
```java
@Configuration
public class JdbcBeanConfig {

    @Bean
  public JdbcTemplate jdbcTemplate(@Autowired DataSource dataSource) {
	 JdbcTemplate jdbcTemplate = new JdbcTemplate();
	 jdbcTemplate.setDataSource(dataSource);
	 return jdbcTemplate;
  }

    @Bean
  public BasicBaseDao basicBaseDao(@Autowired JdbcTemplate jdbcTemplate) {
	 BasicBaseDao basicBaseDao = new BasicBaseDao();
	 basicBaseDao.setJdbcTemplate(jdbcTemplate);
	 return basicBaseDao;
  }

    @Bean
  public ConfigurableFactory getConfigurableFactory() {
	ConfigurableFactory configurableFactory = new ConfigurableFactory();
	// 配置文件的文件位置
	configurableFactory.setSqlConfigurableLocations("sql");
    return configurableFactory;
  }

    @Bean
  public DaoScannerConfigurer daoScannerConfigurer(@Autowired ConfigurableFactory configurableFactory) {
	  DaoScannerConfigurer daoScannerConfigurer = new DaoScannerConfigurer();
	  // db层要扫描的包
	  daoScannerConfigurer.setBasePackage("com.elab.service.business.daos.*");
	  // 持久层操作对象
	  daoScannerConfigurer.setBasicBaseDaoName("basicBaseDao");
	  daoScannerConfigurer.setConfigurableFactory(configurableFactory);
	 return daoScannerConfigurer;
  }

}

```

基于配置文件配置:
```xml

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="mysqlDataSource"/>
    </bean>

    <bean id="basicBaseDao" class="com.elab.core.dao.BasicBaseDao">
        <property name="jdbcTemplate" ref="jdbcTemplate"/>
    </bean>

    <!-- 构建一个配置工厂 -->
    <bean id="configurableFactory" class="com.elab.core.sql.ConfigurableFactory">
        <property name="sqlConfigurableLocations" value="sql"/>
    </bean>

    <!-- 扫描包 -->
    <bean id="daoScannerConfigurer" class="com.elab.core.spring.DaoScannerConfigurer">
        <property name="basePackage" value="com.db.service.dao"/>
        <property name="basicBaseDaoName" value="basicBaseDao"/>
        <property name="configurableFactory" ref="configurableFactory"/>
    </bean>
```


### 强制操作
#### 接口层
1. 必须实现IBaseDaoSupport接口,这样才会受框架的扫描
```java
// 指定配置文件的前缀路径 , 注意这里的配置文件为test-sql.xml , <TTest>构造参数对应的就是数据库的实体
@XmlGroupName("test")
public interface ITestDao extends IBaseDaoSupport<TTest> {

   public TTest getTestObject(String id);

   public List getTestList(TTest id);

   public TTest selectByName(@FieldParam("id") String id, @FieldParam("username") String username);

```
2. SQL文件通常放在resources/sql下面

SQL文件的规范参考

```xml
<!-- 这里面的name对应dao的接口层指定的XmlGroupName的值 -->
<sqlGroup name="test">
    <!-- 对应dao的接口层的方法 -->
    <sql id="getTestObject">
        select
        id
        ,username,name,sex,status,created,time,test_id,love_name
        from t_test
        where
        id = :id
    </sql>
</sqlGroup>
```

- 规范类似Mybatis.
- 增删改不需要指定，框架会通过语句识别执行sql类型
- 简单的增删改查不需要写SQL，复杂的增删改查需要手动写。不用写的sql在IBaseDaoSupport已经写明了。(Mybatis类似)

#### 实体层

- @Table 指定表名
- @Id : 指定主键, 默认以id字段为主键
- @Column 当数据库列名和实体属性名不一致时,可以使用该注解指定
- @Ignore 忽略当前实体的字段,非数据库字段可以通过这个注解指定
- @JoinTable 表关联操作
	- schema 对应的sql.xml配置文件中的,sqlGroup的name加上sql的id , 参考test.selectByExample
	- joinColumns 关联对象的属性名和数据库列名对应
		- name 属性名称
		- referencedColumnName  -> sql语句中的条件名称


参考实体 : **这里的一对多关系会根据你的属性对象来确定是返回一个或者多个**
```java

@Table(name = "t_test")
public class TTest {
 // 表字段 : t_test.id//    @javax.persistence.Column(name="ids")
  @Id
  private Integer id;

 // 表字段 : t_test.test_id  @Column(name = "test_id")
  @Column(name = "test_id")
  private String testId;

  @Ignore
  private String girlName;

// 对应的sql文件中的编号,参数就是JoinColumn中需要将实体和sql中的参数对应
  @JoinTable(schema = "test.selectByExample", joinColumns = {
            @JoinColumn(name = "id", referencedColumnName = "id"),
  @JoinColumn(name = "status", referencedColumnName = "status")
    })
    private TTest test;

  @JoinTable(schema = "test.selectByExample", joinColumns = {
            @JoinColumn(name = "testId", referencedColumnName = "test_id")
    })
    private List testList;
```

## 常用操作

下面是集成自IBaseDaoSupport的操作

1. 添加操作
```java
@Test
public void testInserCase() throws Exception {
    TTest test = new TTest();
	test.setStatus("1");
	test.setUsername("某某某xx111");
	// 这里是非手写的语句,集成自IBaseDaoSupport操作
	int insert = testDao.insert(test);
	System.out.println(insert);
}
```
2. 修改
```java
@Test
public void testUpdateCase() throws Exception {
	TTest test = new TTest();
	test.setId(1);
	test.setStatus("1");
	test.setUsername("某某某xx33333333");
	int insert = testDao.updateById(test);
	System.out.println(insert);
}
```

3. 查询

```java
@Test
  public void testQueryCase() throws Exception {
        TTest test = new TTest();
	test.setId(1123);
	test.setStatus("1");
  //        test.setUsername("某某某xx2121212");
	List tTests = testDao.selectByList(test);
	test.setId(1);
	TTest test1 = testDao.selectByObject(test);
	System.out.println(test1.toString());
	System.out.println(tTests.size());
  }

```

4. 单表特殊操作
```java
ListDynamicSearch.newBuilder().addInSearches("id", list)            // in 操作
                .limit(1)                                           // 大小
                .addLikeSearches("","")                             // like操作
                .dataRangeSearches("time",new Date(),new Date())    // 范围操作
                .orderBy("id",OrderBySearch.DESC);                  // 排序
// 普通方法追加动态参数
List<TTest> tTests = testDao.getTestList2(test, listDynamicSearch);

```


## 特殊操作

### 动态参数
1. 例如动态表名,或者动态字段
```xml
 1. select * from $table
 2. selct * from table order  by $column
```
1. 传值的时候,就传table这个字段
2. 传值的时候就传column -> id asc 等等

## bean对象手动设置
1. 实现RowMapper接口
```
// 该类已经是最底层的赋值方法了,可以根据具体业务去实现不同的处理,
// 如果对数据库的字段有特殊处理的，可以在这个转换成去实现，比如type转换、日期转换等等。
public class TestRowMapper implements RowMapper {

    @Override
  public TTest mapRow(ResultSet resultSet, int i) throws SQLException {
	  TTest test = new TTest();
	  int id = resultSet.getInt("id");
	  String username = resultSet.getString("username");
	  String name = resultSet.getString("name");
	  test.setId(id);
	  test.setUsername(username);
	  test.setName(name);
	  return test;
  }
}

// 然后接口层
可以通过公用的selectByMapper(参数,new TestRowMapper());

TTest test = new TTest();
test.setStatus("1");
TestRowMapper mapper = new TestRowMapper();
List tTests1 = testDao.selectByList(test);
List tTests = testDao.selectByMapper(test, mapper);

```

### in like 操作
如果是in like 等函数:
sql.xml中
```java
// sql
select * from table where name like :name
// java
model.setName("%mmm%");

// sql
select * from table where id in :idList
// java
List<String> list = new ArrayList();
list.add("1");
list.add("2");
list.add("3");
// 上面最好用对象包这这个list

```

# 拓展类
- SQLEventHandler : 所有SQL执行前后的接口都会回调该类
- CheckSqlProcess : 最终要执行的SQL回调。
- ISQLBuliderSupport: 自定义自动生成的接口

# 使用建议
1. 如果出现(columnA = :A or columnB = :B) 这种括号条件的话....希望传值不能为空!
2. 传值的时候参数必须带有一个以上!

## 加速开发

### 自动生成代码

[内部生成代码网站](http://192.168.0.25:8889/share;JSESSIONID=aa82cbce-e6d8-4816-af7f-fe0e01eb77f5)

> 帐号: admin 密码:111111

选择表结构生成特定的内部代码结构。