首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

具有自定义包装类型的Diesel

在使用 Diesel(一个用于 Rust 的 ORM 和查询构建器)时,有时您可能需要处理自定义类型。Diesel 提供了扩展机制,允许您定义和使用自定义类型。以下是一个示例,展示如何在 Diesel 中创建和使用自定义包装类型。

示例:自定义包装类型

假设我们有一个自定义类型 Email,它是一个包装类型,用于验证和存储电子邮件地址。

1. 定义自定义类型

首先,定义一个新的类型 Email,并实现必要的特性(traits)以便与 Diesel 一起使用。

代码语言:javascript
复制
use diesel::backend::Backend;
use diesel::deserialize::{self, FromSql};
use diesel::serialize::{self, IsNull, Output, ToSql};
use diesel::sql_types::Text;
use std::io::Write;
use std::str::FromStr;

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Email(String);

impl FromStr for Email {
    type Err = &'static str;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s.contains('@') {
            Ok(Email(s.to_string()))
        } else {
            Err("Invalid email format")
        }
    }
}

impl ToString for Email {
    fn to_string(&self) -> String {
        self.0.clone()
    }
}

// Implementing ToSql for Email
impl<DB: Backend> ToSql<Text, DB> for Email {
    fn to_sql<W: Write>(&self, out: &mut Output<W, DB>) -> serialize::Result {
        out.write_all(self.0.as_bytes())?;
        Ok(IsNull::No)
    }
}

// Implementing FromSql for Email
impl<DB: Backend> FromSql<Text, DB> for Email {
    fn from_sql(bytes: Option<&DB::RawValue>) -> deserialize::Result<Self> {
        let bytes = not_none!(bytes);
        let s = std::str::from_utf8(bytes)?;
        Email::from_str(s).map_err(|_| "Invalid email format".into())
    }
}

2. 使用自定义类型与 Diesel 模型

接下来,定义一个 Diesel 模型,并使用自定义类型 Email

代码语言:javascript
复制
use diesel::prelude::*;
use diesel::sql_types::Text;

table! {
    users (id) {
        id -> Integer,
        email -> Text,
    }
}

#[derive(Queryable, Insertable)]
#[table_name = "users"]
pub struct User {
    pub id: i32,
    pub email: Email,
}

3. 运行示例

以下是一个完整的示例,展示如何使用自定义类型 Email 与 Diesel 进行数据库操作。

代码语言:javascript
复制
#[macro_use]
extern crate diesel;
extern crate dotenv;

use diesel::prelude::*;
use diesel::sqlite::SqliteConnection;
use dotenv::dotenv;
use std::env;

mod schema {
    table! {
        users (id) {
            id -> Integer,
            email -> Text,
        }
    }
}

use self::schema::users;
use self::schema::users::dsl::*;

#[derive(Debug, Queryable, Insertable)]
#[table_name = "users"]
pub struct User {
    pub id: i32,
    pub email: Email,
}

fn establish_connection() -> SqliteConnection {
    dotenv().ok();

    let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
    SqliteConnection::establish(&database_url).expect(&format!("Error connecting to {}", database_url))
}

fn main() {
    let connection = establish_connection();

    // Create a new user
    let new_user = User {
        id: 1,
        email: "user@example.com".parse().expect("Invalid email format"),
    };

    // Insert the new user into the database
    diesel::insert_into(users)
        .values(&new_user)
        .execute(&connection)
        .expect("Error inserting new user");

    // Query the user from the database
    let results = users
        .filter(id.eq(1))
        .load::<User>(&connection)
        .expect("Error loading user");

    for user in results {
        println!("Found user: {:?}", user);
    }
}

总结

通过上述步骤,您可以在 Diesel 中定义和使用自定义包装类型。关键步骤包括:

  1. 定义自定义类型并实现 FromStrToString
  2. 实现 ToSqlFromSql 特性,以便 Diesel 能够序列化和反序列化自定义类型。
  3. 在 Diesel 模型中使用自定义类型,并进行数据库操作。
页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

自定义属性包装类型添加类 @Published 能力

,但适用于 NSUbiquitousKeyValueStore ),来展示如何为其他自定义属性包装类型添加可访问包裹其类实例属性或方法能力。...本文中为其他属性包装类型添加类似 @Published 能力是指 —— 无需显式设置,属性包装类型便可访问包裹其类实例属性或方法。...propertyWrapper 来自定义属性包装类型。...与 掌握 Result builders[6] 一文中介绍 @resultBuilder 类似,编译器在最终编译前,首先会对用户自定义属性包装类型代码进行转译。...@PublishedObject —— @Published 引用类型版本 @Published 只能胜任包装值为值类型场景,当 wrappedValue 为引用类型时,仅改变包装属性内容并不会对外发布通知

3.3K20
  • 02 java包装类型缓存机制

    02 java包装类型缓存机制 Java 基本数据类型包装类型大部分都用到了缓存机制来提升性能。...Byte,Short,Integer,Long 这 4 种包装类默认创建了数值 [-128,127] 相应类型缓存数据,Character 创建了数值在 [0,127] 范围缓存数据,Boolean...Integer源码 可以看到 当我们需要转换值在 -128>=x<=127 这个区间 会采用堆中引用 不信看看下面的测试 测试 可以看到 俩个对象在jvm中内存地址是一样 从来说明 使用是缓存数据...如果超出对应范围仍然会去创建新对象,缓存范围区间大小只是在性能和资源之间权衡。 两种浮点数类型包装类 Float,Double 并没有实现缓存机制。 下面我们来看一下问题。...记住:所有整型包装类对象之间值比较,全部使用 equals 方法比较什么是装箱拆箱

    22510

    01 java基本类型包装类型区别?

    基本类型包装类型区别?...1 包装类型可以为 null,而基本类型不可以 数据库查询结果可能是 null,如果使用基本类型的话,因为要自动拆箱(将包装类型转为基本类型,比如说把 Integer 对象转换成 int 值),就会抛出...3 虚拟机中存放位置不同 基本数据类型局部变量存放在 Java 虚拟机栈中局部变量表中 基本数据类型成员变量(未被 static 修饰 )存放在 Java 虚拟机堆中 包装类型属于对象类型,我们知道几乎所有对象实例都存在于堆中...⚠️注意 : 基本数据类型存放在栈中是一个常见误区! 基本数据类型成员变量如果没有被 static 修饰的话(不建议这么使用,应该要使用基本数据类型对应包装类型),就存放在堆中。...会产生异常 class BasicTypeVar{ private int x; } 4 基本类型包装类型更高效 包装类属于对象类型占用空间大, 基本数据类型占用空间非常小。

    19010

    包装类型与基本数据类型异同

    包装类型与基本数据类型异同 一、基本数据类型: Java 语言提供了八种基本类型:六种数字类型(四个整数型,两个浮点型), 一种字符类型,还有一种布尔型。...三、基本类型包装类型异同 1、在 Java 中,一切皆对象,但八大基本类型却不是对象。 2、声明方式不同,基本类型无需通过 new 关键字来创建,而包装类型需 new 关键字。...3、存储方式及位置不同,基本类型是直接存储变量值保存在栈中能高 效存取,包装类型需要通过引用指向实例,具体实例保存在堆中。...4、初始值不同,包装类型初始值为 null,基本类型初始值视具体类型而定,比如 int 类型初始值为 0,boolean 类型为 false。...5、使用方式不同,比如与集合类合作使用时只能使用包装类型

    56430

    基本数据类型包装

    基本数据类型包装包装类基本知识 JAVA 并不是纯面向对象语言。Java 语言是一个面向对象语言,但是 Java 中基本数据类型却是不面向对象。...包装类均位于 java.lang 包,包装类和基本数据类型对应关系如下表所示: 基本数据类型 包装类 byte Byte boolean Boolean short Short char Character...包装用途 对于包装类说,这些类用途主要包含两种: 1、作为和基本数据类型对应类型存在,方便涉及到对象操作。...2、包含每种基本数据类型相关属性如最大值、最小值等,以及相关操作方法(这些操作方法作用是在基本类型数据、包装类对象、字符串之间提供转化!)。...自动装箱过程:每当需要一种类型对象时,这种基本类型就自动地封装到与它相同类型包装中。

    76220

    Java基本数据类型包装

    数据类型包装类 Java语言是一个面向对象语言,但是Java中基本数据类型却是不面向对象,这在实际使用时存在很多不便,为了解决这个不足,在设计类时为每个基本数据类型设计了一个对应类进行代表...,这样八个和基本数据类型对应类统称为包装类(Wrapper Class),有些地方也翻译为外覆类或数据类型类。...包装类均位于java.lang包,包装类和基本数据类型对应关系如下表所示: ?...包装用途 对于包装类说,这些类用途主要包含两种: a、作为和基本数据类型对应类型存在,方便涉及到对象操作。...则字符串s值是”1000”。 自动拆箱和装箱 自动装箱过程:每当需要一种类型对象时,这种基本类型就自动地封装到与它相同类型包装中。

    79530

    面试官:兄弟,说说基本类型包装类型区别吧

    他当时扔了一个面试题把我砸懵了:说说基本类型包装类型区别吧。...Java 每个基本类型都对应了一个包装类型,比如说 int 包装类型为 Integer,double 包装类型为 Double。基本类型包装类型区别主要有以下 4 点。...03、基本类型包装类型更高效 基本类型在栈中直接存储具体数值,而包装类型则存储是堆中引用。 ? 很显然,相比较于基本类型而言,包装类型需要占用更多内存空间。...03、两个包装类型值可以相同,但却不相等 两个包装类型值可以相同,但却不相等——这句话怎么理解呢?来看一段代码就明明白白了。...把基本类型转换成包装类型过程叫做装箱(boxing)。反之,把包装类型转换成基本类型过程叫做拆箱(unboxing)。

    54351

    定制自己数据类型(二次加工标准类型(包装))

    ---恢复内容开始--- 包装:python为大家提供了标准数据类型,以及丰富内置方法,其实在很多场景下我们都需要基于标准数据类型来定制我们自己数据类型,新增/改写方法,这就用到了我们刚学继承/派生知识...(其他标准类型均可以通过下面的方式进行二次加工) 定制了子类Listappend,多了类型检查功能 class List(list):#继承list所有的属性,也可以派生出自己新,比如append...index=len(self)//2 return self[index] l=List([1,2,3,4]) print(l) l.append(5) print(l) 授权:授权是包装一个特性..., 包装一个类型通常是对已存在类型一些定制,这种做法可以新建,修改或删除原有产品功能。...实现授权关键点就是覆盖__getattr__方法 # 授权:授权是包装一个特性,包装一个类型通常是对已经存在类型一些定制,这种做法可以新建, # 修改或删除原有产品功能。其他则保持原样。

    42910

    JVM - 基本类型包装类和对象池

    接下来我们也顺便看下基本类型包装类和起对应对象池 JDK1.8 ---- 八大基本类型 Java基本类型共有八种,基本类型可以分为三类, 字符类型char 布尔类型boolean 数值类型byte、...java中基本类型包装大部分都实现了常量池技术(严格来说应该叫对象池,在堆上),这些类是Byte,Short,Integer,Long,Character,Boolean,另外两种浮点数类型包装类...另外Byte,Short,Integer,Long,Character这5种整型包装类也只是在对应值小于等于127时才可使用对象池,也即对象不负责创建和管理大于127这些类对象。...版本 1.8 public class BasicTypePoolTest { public static void main(String[] args) { //5种整形包装类...true; Boolean bool2 = true; System.out.println(bool1 == bool2);//输出true //浮点类型包装类没有实现对象池技术

    48610

    面试官:兄弟,说说基本类型包装类型区别吧

    Java 每个基本类型都对应了一个包装类型,比如说 int 包装类型为 Integer,double 包装类型为 Double。基本类型包装类型区别主要有以下 4 点。...基本类型包装类型更高效 基本类型在栈中直接存储具体数值,而包装类型则存储是堆中引用。 很显然,相比较于基本类型而言,包装类型需要占用更多内存空间。...两个包装类型值可以相同,但却不相等 两个包装类型值可以相同,但却不相等——这句话怎么理解呢?来看一段代码就明明白白了。...换句话说就是:将“==”操作符应用于包装类型比较时候,其结果很可能会和预期不符。 自动装箱和自动拆箱 既然有了基本类型包装类型,肯定有些时候要在它们之间进行转换。...把基本类型转换成包装类型过程叫做装箱(boxing)。反之,把包装类型转换成基本类型过程叫做拆箱(unboxing)。

    2.7K40

    对基本类型包装类常量池补充

    在前文JAVA-常量及常量池中,对java中各种常量池进行分析。在具体细节中,并不完善。现在对数据类型包装类常量池进行相应补充。有很多细节也是面试中容易遗漏地方。...意思是说,IntegerCache对-128-127之间数据自动装箱支持。在IntegerCache第一次使用时候通过static构造方法进行初始化。...for(int i = 0; i < cache.length; i++) cache[i] = new Long(i - 128); } } 作为Long包装内部类...总结 对于java中8种基本数据类型,存在Cache情况如下: 原始类型 缓存类型 范围 是否可调整 int IntegerCache -128-127 通过-XX:AutoBoxCacheMax...在系统中数字在一个较小范围内变化时候,可以通过缓存方式,提前创建好。

    48610

    【Rust 基础篇】Rust Newtype模式:类型安全包装

    在Rust中,Newtype模式是一种常见编程模式,用于创建类型安全包装器。Newtype模式通过定义新结构体包装器来包装现有的类型,从而在不引入运行时开销情况下提供额外类型安全性。...Newtype模式是一种常见编程模式,用于创建类型安全包装器。在Rust中,Newtype模式通过定义新结构体包装器来包装现有的类型,从而在不引入运行时开销情况下提供额外类型安全性。...通过将现有类型包装在Newtype结构体中,我们可以防止将不同含义数据类型进行混用,从而减少出错可能性。...但要注意,Newtype包装方法调用可能会稍微增加一点性能开销。 4.2 Newtype包装器和类型转换 Newtype包装器在编译时提供了更强类型安全性,但也意味着需要进行一些类型转换操作。...在使用Newtype包装器时,需要注意类型转换情况。 结论 RustNewtype模式允许通过定义新结构体包装器来包装现有类型,增强类型安全性并增加语义表达力。

    34640

    面试官:兄弟,说说基本类型包装类型区别吧

    Java 每个基本类型都对应了一个包装类型,比如说 int 包装类型为 Integer,double 包装类型为 Double。基本类型包装类型区别主要有以下 4 点。...基本类型包装类型更高效 基本类型在栈中直接存储具体数值,而包装类型则存储是堆中引用。 很显然,相比较于基本类型而言,包装类型需要占用更多内存空间。...两个包装类型值可以相同,但却不相等 两个包装类型值可以相同,但却不相等——这句话怎么理解呢?来看一段代码就明明白白了。...换句话说就是:将“==”操作符应用于包装类型比较时候,其结果很可能会和预期不符。 自动装箱和自动拆箱 既然有了基本类型包装类型,肯定有些时候要在它们之间进行转换。...把基本类型转换成包装类型过程叫做装箱(boxing)。反之,把包装类型转换成基本类型过程叫做拆箱(unboxing)。

    53710

    第47节:Java当中基本类型包装

    标题图 Java当中基本类型包装类 01 基本数据类型对象包装类 什么是基本数据类型对象包装类呢?就是把基本数据类型封装成对象,这样就可以提供更多操作基本数值功能了。...基本数据类型对象包装类8个: 基本数据类型 包装类 byte Byte short Short int Integet long Long float Float double Double boolean...int包装成为对象包装类。...基本数据类型对象包装类,就是为了提供更多操作方法,这里Integer类中Java提供了多个方法,而且Integer类能够在int类型和String类型之间互相进行转换,还可以处理一些int类型有关一些常量和方法等...(String nm) 返回是 static Integer,确定具有指定名称系统属性整数值 getInteger(String nm, int val) 返回是static Integer,确定具有指定名称系统属性整数值

    46120

    【JAVASE】Java 包装秘密:解开数据类型谜团

    包装类 在 Java 中,有一些基本数据类型,如 int、float、boolean 等。这些基本数据类型是简单数据类型,可以直接操作和使用。...包装类是将基本数据类型包装成对象类 1、基本数据类型和对应包装类 基本数据类型 包装类 byte Byte short Short int Integer long Long float Float...2、包装用途 (1)安全性:通过使用包装类,可以避免直接使用原始数据类型,从而提高代码安全性和可维护性。...3、包装用法 (1)创建包装对象: Integer integerObj = new Integer(10); (2)使用自动装箱: 装箱是指将基本数据类型转换为对应包装类对象过程。...对象 (3)使用自动拆箱: 拆箱是指将包装类对象转换回基本数据类型过程。

    9110

    【Rust日报】Diesel 发布新版本 2.2.0

    Diesel 发布新版本 2.2.0 Diesel 是一个安全且高性能查询构建器和用 Rust 编写 ORM。此版本包含多项新功能并改进了现有功能。...Diesel 现在提供了一个过程宏属性,用于推断查询正确返回类型。现在可以检测Diesel提供连接实现,以执行记录和性能测量。...我们依赖项包装了本机数据库驱动程序,现在支持所有构建数据库驱动程序作为 . cargo build 这使我们能够轻松地分发 diesel-cli 静态预编译版本。...最后,我们与 Rust 团队合作,稳定属性,以自定义编译器发出错误消息。现在,Diesel使用它来提高某些难以理解错误消息质量。...初始化包管理器 gpm init 添加新类型 gpm type add Change your shell config at ~/.gpm/types.toml

    13910
    领券