GithubHelp home page GithubHelp logo

gaarason / database-all Goto Github PK

View Code? Open in Web Editor NEW
687.0 10.0 25.0 1.89 MB

Eloquent ORM for Java 8, 11, 17 and Spring boot 2.x , 3.x

License: MIT License

Java 99.80% FreeMarker 0.20%
laravel java orm database spring-boot starter eloquent-orm mysql model orm-framework orm-library eloquent

database-all's Introduction

database

Eloquent ORM for Java

简介 Introduction

  • 让连接数据库以及对数据库进行增删改查操作变得非常简单,不论希望使用原生 SQL、还是查询构造器,还是 Eloquent ORM。
  • Eloquent ORM 提供一个美观、简单的与数据库打交道的 ActiveRecord 实现,每个数据表都对应一个与该表数据结构对应的实体(Entity),以及的进行交互的模型(Model),通过模型类,你可以对数据表进行查询、插入、更新、删除等操作,并将结果反映到实体实例化的 java 对象中。
  • 对于关联关系 Eloquent ORM 提供了富有表现力的声明方式,与简洁的使用方法,并专注在内部进行查询与内存优化,在复杂的关系中有仍然有着良好的体验。
  • 支持原生Java8,Java11,Java17应用, 支持SpringBoot 2x 以及 3x ,兼容于其他常见的 ORM 框架, 以及常见的数据源 (DataSource)。

  • It makes connecting to the database and adding, deleting, modifying and querying the database very simple, whether you want to use native SQL, query builder, or Eloquent ORM.
  • Eloquent ORM provides a beautiful and simple ActiveRecord for working with databases Implementation, each data table corresponds to an entity (Entity) corresponding to the data structure of the table, and a model (Model) for interaction. Through the model class, you can query, insert, update, delete and other operations on the data table. , and reflect the results into the java object instantiated by the entity.
  • For relationships, Eloquent ORM provides expressive declaration methods and concise usage methods. It focuses on internal query and memory optimization, and still has a good experience in complex relationships.
  • Supports native Java8, Java11, Java17 applications, supports SpringBoot 2x and 3x, and is compatible with other common ORM frameworks and common data sources (DataSource).

目录

  • 以如下的方式在程序中查询数据 Query data in the program in the following way
  • 查询 Select : model.newQuery().select().where().get().toObject();
  • 更新 Update : model.newQuery().data().where().update();
  • 删除 Delete : model.newQuery().where().delete();
  • 插入 Insert : model.newQuery().column().value().insert();
// select * from student where id = 4 limit 1
Student student = studentModel.find(4).toObject();

// select * from student where id = 4 limit 1
Student student = studentModel.newQuery().query("select * from student where id= ? limit ? ", 4, 1).toObject();

// select name,age from student where id in (1, 2, 3)
List<Student> students = studentModel.newQuery()
        .select(Student::getName).select(Student::getAge)
        .whereIn(Student::getId, 1, 2, 3)
        .get().toObjectList();

// select id,name from student where id=3 or(age>11 and id=7 and(id between 4 and 10 and age>11))
List<Student> students = studentModel.newQuery().where("id", "3").orWhere(
                builder->builder.where("age", ">", "11").where("id", "7").andWhere(
            builder2->builder2.whereBetween("id", "4", "10").where("age", ">", "11")
        )
).select("id", "name").get().toObjectList();

// select * from student where id in (1, 2, 3)
// select * from teacher where id in (?, ?, ?)
// select * from father where id in (?, ?, ?)
// select * from house where owner_id in (?, ?, ?)
List<Student> students = studentModel.newQuery().whereIn("id", 1, 2, 3).get().with("teacher.father.house").toObjectList();

// select * from student where id = 8 limit 1
// select * from relation_student_teacher where student_id = 8 and teacher_id in (1, 2, 3)
// insert into relation_student_teacher set student_id = 8 and teacher_id = 3
studentModel.findOrFail(8).bind("teachers").attach( 1, 2, 3 );

Spring boot Quick start

1.引入仓库 pom.xml

<repositories>
    <repository>
        <id>jitpack.io</id>
        <url>https://jitpack.io</url>
    </repository>
</repositories>

2.引入依赖 pom.xml

latest-version

<dependency>
    <groupId>com.github.gaarason.database-all</groupId>
    <artifactId>database-spring-boot-starter</artifactId>
    <version>{latest-version}</version>
</dependency>

3.配置连接 application.properties

spring.datasource.url=jdbc:mysql://mysql.local/test_master_0?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=true&autoReconnect=true&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# 使用你喜欢的 datasource, 这边增加了 DruidDataSource 的支持, 使其符合 Spring 的指定风格
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource

# 雪花算法工作id, 默认是0
# gaarason.database.snow-flake.worker-id=1

# 包扫描路径, 默认是`@SpringBootApplication`所在的包
# 非 SpringBoot, 建议手动指定包扫描路径
# gaarason.database.scan.packages=you.package1,you.package2

4.快速开始 quick start

使用预置的 GeneralModel ,无需其他定义,即可进行查询。
Using the pre-built GeneralModel, no additional definitions are required to query.

@Resource
GeneralModel generalModel;

@Test
public void simpleQuery() {

    // select * from student where id = 3 limit 1
    Record<?, ?> record = generalModel.newQuery().from("student").where("id", 3).firstOrFail();

    // to map
    Map<String, Object> stringObjectMap = record.toMap();

    System.out.println(stringObjectMap);
}

完整体验 Complete experience

  • 借助 生成代码 Generate, 自动化地为每个数据表都定义一个与该表数据结构对应的实体(Entity), 以及的进行交互的模型(Model)
  • 在模型(Model)中, 通过 查询构造器 Query Builder 你可以对数据表进行查询、插入、更新、删除等操作,并将结果反映到 查询结果集 Record
  • 查询结果集 Record 中可以快速的将结果转化为的 java 实体(Entity)对象, 以及其他数据结构以及处理操作
  • 通过在实体(Entity)中应用各种的声明式注解进行 数据映射 Mapping, 便可以方便的在模型(Model)中应用诸如 关联关系 Relationship、ORM以及各种自定义操作

  • With the help of 生成代码 Generate, each data table is automatically defined with an entity (Entity) corresponding to the data structure of the table, and a model (Model) for interaction.
  • In the model, through the 查询构造器 Query Builder you can query, insert, update, delete and other operations on the data table, and reflect the results to the 查询结果集 Record in
  • In 查询结果集 Record, the results can be quickly converted into java entity objects, as well as other data structures and processing operations.
  • By applying various declarative annotations to 数据映射 Mapping in the Entity, you can easily apply 关联关系 Relationship, ORM and various custom operations

database-all's People

Contributors

xutengx avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

database-all's Issues

Springboot TransactionManager 报错

感觉是事物管理出问题了,我这边因为还使用了hibernate,会导致下面的配置报错。

@Bean
@ConditionalOnMissingBean
public GaarasonTransactionManager gaarasonTransactionManager() {
    logger.info("-------------------- gaarasonTransactionManager init ------------------");
    return new GaarasonTransactionManager(gaarasonDataSource());
}

报错截图
image

GaarasonDatabaseConfiguration自定义的代码,因为database-spring-boot-starter里没有配置@primary优先级,也会导致出问题

@Slf4j
@Configuration
@AutoConfigureBefore(DruidDataSourceAutoConfigure.class)
@EnableConfigurationProperties({GaarasonDatabaseProperties.class})
@Import({GeneralModel.class})
public class GaarasonDatabaseConfiguration {

    private static final Logger logger = LoggerFactory.getLogger(GaarasonDatabaseConfiguration.class);

    /**
     * 指定 model 扫描范围
     */
    GaarasonDatabaseConfiguration(ApplicationContext applicationContext, GaarasonDatabaseProperties gaarasonDatabaseProperties) {
        // 注册 model实例获取方式
        ModelInstanceProvider.register(modelClass -> {
            try {
                return ObjectUtils.typeCast(applicationContext.getBean(modelClass));
            } catch (BeansException e) {
                return ObjectUtils.typeCast(applicationContext.getBean(StringUtils.lowerFirstChar(modelClass.getSimpleName())));
            }
        });
        logger.info("Model instance provider has been registered success.");

        // 注册 雪花id实现
        final int workerId = gaarasonDatabaseProperties.getSnowFlake().getWorkerId();
        final int dataId = gaarasonDatabaseProperties.getSnowFlake().getDataId();
        ContainerProvider.register(IdGenerator.SnowFlakesID.class, clazz -> new SnowFlakeIdGenerator(workerId, dataId));

        logger.info("SnowFlakesID[ workId: {}, dataId: {}] instance has been registered success.", workerId, dataId);
    }

    @Primary
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource2")
    @ConditionalOnMissingBean
    public DataSource dataSourceDruidConfig() {
        logger.info("-------------------- dataSource druid config init ---------------------");
        return DruidDataSourceBuilder.create().build();
    }

    @Bean
    @ConditionalOnMissingBean
    public GaarasonDataSource gaarasonDataSource() {
        logger.info("-------------------- gaarasonDataSource init --------------------------");
        return ContainerProvider.getBean(GaarasonDataSourceConfig.class).build(Collections.singletonList(dataSourceDruidConfig()));
    }

    @Bean
    @ConditionalOnMissingBean
    public GaarasonTransactionManager gaarasonTransactionManager() {
        logger.info("-------------------- gaarasonTransactionManager init ------------------");
        return new GaarasonTransactionManager(gaarasonDataSource());
    }
}

请教怎么在多个数据源里让事务可以正常执行。

我在做created_at和updated_at自动生成的时候遇到了问题

在文档的事件中提到“允许你在模型生命周期中的多个时间点调用如下这些方法”。

然后我一开始直接复制文档代码,发现并不生效。然后在ORMEvent找到说明“其中以 record 为参数的事件, 仅在使用ORM风格时, 会触发”。

现在问题是这样的,在文档中并没有告知“使用ORM风格”是什么意思。我翻了Query和Model都没有提到ORM风格。且使用Query插入的a方式并不能触发creating和created。

我想询问的是是我使用方法有问题还是需要添加什么注解或者是我操作有什么问题,以及ORM风格是什么意思。

代码如下:
main:

        UserData userData=new UserData();
        userData.setNumber("123456");
        userDataModel.newQuery().insert(userData);

UserData(采用生成):

public class UserData extends BaseEntity {
    private static final long serialVersionUID = 1L;

    /** auto generator start **/


    @Column(name = "number", length = 12L, comment = "学生:学号 老师:工号")
    private String number;

    @Column(name = "created_at", nullable = true)
    private LocalDateTime createdAt;

    @Column(name = "updated_at", nullable = true)
    private LocalDateTime updatedAt;

    @Column(name = "deleted_at", nullable = true)
    private LocalDateTime deletedAt;


    /** auto generator end **/

    @Repository
    public static class Model extends BaseEntity.BaseModel<UserData, Long> {
    }
}

BaseEntity(采用生成):

public abstract class BaseEntity implements Serializable {
    private static final long serialVersionUID = 1L;

    /**
     * auto generator start
     **/


    @Primary()
    @Column(name = "id", unsigned = true)
    private Long id;

    @Column(name = "created_at", nullable = true)
    private LocalDateTime createdAt;

    @Column(name = "updated_at", nullable = true)
    private LocalDateTime updatedAt;

    @Column(name = "deleted_at", nullable = true)
    private LocalDateTime deletedAt;

    /**
     * auto generator end
     **/
    public abstract static class BaseModel<T extends BaseEntity, K> extends Model<T, K> {

        @Resource
        @Lazy
        protected GaarasonDataSource gaarasonDataSource;

        @Override
        public GaarasonDataSource getGaarasonDataSource() {
            return gaarasonDataSource;
        }

        /**
         * sql日志记录
         *
         * @param sql           带占位符的sql
         * @param parameterList 参数
         */
        @Override
        public void log(String sql, Collection<?> parameterList) {
            String format = String.format(sql.replace(" ? ", "\"%s\""), parameterList.toArray());
            System.out.println(format);
            //log.debug("SQL complete : {}", format);
        }

        @Override

        public boolean creating(Record<T, K> record) {
            System.out.println("orm creating");
            return super.creating(record);
        }

        /**
         * 是否启用软删除
         */
        @Override
        protected boolean softDeleting() {
            return false;
        }

        /**
         * 删除(软/硬删除)
         *
         * @param builder 查询构造器
         * @return 删除的行数
         */
        @Override
        public int delete(Builder<T, K> builder) {
            return softDeleting() ? softDelete(builder) : builder.forceDelete();
        }

        /**
         * 恢复软删除
         *
         * @param builder 查询构造器
         * @return 删除的行数
         */
        @Override
        public int restore(Builder<T, K> builder) {
            return softDeleteRestore(builder);
        }

        /**
         * 软删除查询作用域(反)
         *
         * @param builder 查询构造器
         */
        @Override
        protected void scopeSoftDeleteOnlyTrashed(Builder<T, K> builder) {
            builder.whereNotNull("deleted_at");
        }

        /**
         * 软删除查询作用域(反)
         *
         * @param builder 查询构造器
         */
        protected void scopeSoftDeleteWithTrashed(Builder<T, K> builder) {

        }

        /**
         * 软删除查询作用域
         *
         * @param builder 查询构造器
         */
        @Override
        protected void scopeSoftDelete(Builder<T, K> builder) {
            builder.whereNull("deleted_at");
        }


        /**
         * 软删除实现
         *
         * @param builder 查询构造器
         * @return 删除的行数
         */
        @Override
        protected int softDelete(Builder<T, K> builder) {
            return builder.data("deleted_at", LocalDateTime.now()).update();
        }

        /**
         * 恢复软删除实现
         *
         * @param builder 查询构造器
         * @return 恢复的行数
         */
        @Override
        protected int softDeleteRestore(Builder<T, K> builder) {
            return builder.data("deleted_at", null).update();
        }
    }
}

请问可否支持重写关联关系?

比如我想在belongsto里面需要用通过两个组合外键的形式来关联查询父表中的信息。但是好像不支持多列。请问我是否有办法重写BelongsToQueryRelation来达到我的目的呢?谢谢

希望尽量和Eloquent设计的api保持一致,这样有助于使用过Eloquent的人,更简单的上手,也不容易引起歧义。

还想提一个建议,希望尽量和Eloquent设计的api保持一致,这样有助于使用过Eloquent的人,更简单的上手,也不容易引起歧义。毕竟目前在其他语言中,都有Eloquent的实现,在我个人看来,Eloquent就是对ORM的一次重新定义,特别是在JAVA里。
另外我们知道,在laravel中的api中,对每一个方法的命名,每一个功能的实现,都经过反复的推敲,据作者所说,有时候为了一个命名都会消耗几天的时间。其实能在java中看到这个现实是很高兴的,对那些JPA+Hibernate、mybatis等框架表示要抓狂的感觉。我坦白我是刚转到java不久,没有那些沉重的历史包袱,特别深恶痛觉把sql写到xml中的方式。以上观点,仅代表自己,不接受反驳。

public Record<T, K> findOrNew(Object id) {
      Record<T, K> first = this.newQuery().where(this.getPrimaryKeyColumnName(), id).first();
        if (first != null) {
            return first;
        } else {
            return this.newRecord();
        }
}

public Record<T, K> firstOrNew(T entity) {
        Record<T, K> first = this.newQuery().where(entity).first();
        if (first != null) {
            return first;
        } else {
            Record<T, K> tkRecord = this.newRecord();
            tkRecord.getEntity(entity);
            return tkRecord;
        }
 }

就如上面两个方法,是我自己在BaseModel里面加的。
1、findOrNew是传入PrimaryKey值,获取记录,这样既简单又好理解。
2、firstOrNew是传入实体然后进行查询,一般情况下,除非知道实体里的值,才会实现。但是实际情况。我们从POST请求接收到的就是实体,这个时候不能作为where的参数,当然在我自己的项目中firstOrNew是有机会出场的,比如要多条件查询一个记录,就显得非常方便了,但是平时并不需要这样处理, 其实本项目内部已经有find方法的实现了。

where检索条件中的value类型问题

目前看到where中的value类型为String,针对比如int类型的字段,会导致mysql执行时将该字段类型转换为字符串,引起一些隐藏bug或索引失效的问题。所以whereParameterList是否应当设置为List而非List类型(并同步调整最后执行sql时的参数绑定逻辑)?

直接使用实例化Model对象, 报 NoSuchMethodException QueryBuilderConfig.<init>()

可以提供以下信息
bug类:

1 .使用的代码库的方式 ? (源码编译 / maven依赖 / 源码拷贝 ..)

repositories {
    mavenCentral()
    maven {
        url 'https://jitpack.io'
    }
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'
    implementation 'com.mysql:mysql-connector-j'
    implementation 'com.github.gaarason.database-all:database-spring-boot-starter:4.8.0'
}

2 .使用的代码库的方式版本 ? ( tag版本 / maven依赖版本 / commit hash ..)

3 .java版本
java 17

4 .框架以及版本 ( eg : spring boot 3.0.0 )
无框架

5 .数据库以及版本 ( eg : mysql 8.0.0 )
mysql8.0.27
6 .问题简述 ( 有必要的话, 可以贴下相关调用代码以及定义代码 )
以下是报错代码


public class Person {
    Integer id;
    String name;
    String firstname;
    String lastname;
    String addr;
}


public class PersonModel extends Model<Person, Integer> {
    @Override
    public GaarasonDataSource getGaarasonDataSource() {
        GaarasonDataSource build = GaarasonDataSourceBuilder.build(new Sdata2Application().dataSource());

        // 注释掉这行 就会报错 
//        new MysqlAutoconfiguration().init(build.getContainer());
        return build;
    }

    public static void main(String[] args) {
        var generalModel = new PersonModel();
        var record = generalModel.newQuery()
                .first();
        System.out.println("record = " + record);
    }
}

7 .预期效果

Exception in thread "main" gaarason.database.exception.ObjectNewInstanceException: Error instantiating object[interface gaarason.database.config.QueryBuilderConfig] with message : Error instantiating object[interface gaarason.database.config.QueryBuilderConfig]
	at gaarason.database.provider.ContainerProvider.getBeansInside(ContainerProvider.java:144)
	at gaarason.database.provider.ContainerProvider.getBeans(ContainerProvider.java:86)
	at gaarason.database.connection.GaarasonDataSourceWrapper.getQueryBuilder(GaarasonDataSourceWrapper.java:329)
	at gaarason.database.connection.GaarasonDataSourceWrapper.getQueryBuilder(GaarasonDataSourceWrapper.java:316)
	at gaarason.database.eloquent.ModelOfQuery.theBuilder(ModelOfQuery.java:50)
	at gaarason.database.eloquent.ModelOfQuery.newQuery(ModelOfQuery.java:55)
	at com.example.sdata2.PersonModel.main(PersonModel.java:23)
Caused by: gaarason.database.exception.ObjectNewInstanceException: Error instantiating object[interface gaarason.database.config.QueryBuilderConfig]
	at gaarason.database.util.ClassUtils.newInstance(ClassUtils.java:56)
	at gaarason.database.provider.ContainerProvider.lambda$defaultNewInstance$1(ContainerProvider.java:160)
	at gaarason.database.provider.ContainerProvider.getBeansInside(ContainerProvider.java:136)
	... 6 more
Caused by: java.lang.NoSuchMethodException: gaarason.database.config.QueryBuilderConfig.<init>()
	at java.base/java.lang.Class.getConstructor0(Class.java:3585)
	at java.base/java.lang.Class.getDeclaredConstructor(Class.java:2754)
	at gaarason.database.util.ClassUtils.newInstance(ClassUtils.java:52)
	... 8 more

Caused by: gaarason.database.exception.ObjectNewInstanceException: Error instantiating object[interface gaarason.database.config.QueryBuilderConfig]

Caused by: java.lang.NoSuchMethodException: gaarason.database.config.QueryBuilderConfig.<init>()

建议类:

感觉像是直接实例化Model对象的时候, 没有把 MysqlQueryBuilderConfig 这个类给注册到container中.

maven package error

Error:(40, 41) java: cannot find symbol
symbol: method create()
location: class gaarason.database.connection.GaarasonDataSourceBuilder.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.