精华内容
下载资源
问答
  • Easy Save 3.0.3

    2019-02-02 10:11:31
    Easy Save可以实现在游戏中保存进度的功能。它高效且易于使用,只需一行代码就可以保存、读取或加密存档文件。
  • Unity EasySave3插件 与 中文图文教程详解-万能数据保存插件多平台支持,EasySave2和EasySave3插件源码; 里面附带中文使用文档.
  • Unity3D U3D 热门插件EasySave3中文简单入门教程,非EasySave2,这个插件使用起来本来就挺简单,有中文翻译更是让那些英语渣而且懒得机翻的童鞋省心了。
  • EasySave3.unitypackage

    2018-12-03 21:13:59
    EasySave2和EasySave3插件源码; 里面附带中文使用文档.
  • DataSave DataSave

    2018-05-04 11:16:14
    DataSave DataSave DataSave DataSave DataSave DataSave
  • 实用工具,偶得,分享下希望有帮助。
  • Easy Save - The Complete Save Load Asset v3.3.0Easy Save - The Complete Save Load Asset v3.3.0Easy Save - The Complete Save Load Asset v3.3.0
  • save-ps-to-svg 1.0.zip

    2017-06-12 19:27:13
    支持 PhotoShop 将形状图片转化为 svg路径的脚本
  • save-ps-to-svg1.0.jsx

    2017-06-12 17:43:43
    直接 PhotoShop 直接将形状文件转化导出为 SVG路径的脚本
  • filesave 用于下载

    2014-10-31 21:58:47
    file save 下载
  • DIIIROS.SaveEdit_1.3.18.142

    2015-11-21 14:57:21
    DIIIROS.SaveEdit_1.3.18.142
  • Django Signals-掌握pre_save和post_save

    千次阅读 2020-07-18 10:18:22
    Use pre_save like a pro) Pre_save (django.db.models.signals.pre_save) is provoked just before the model save() method is called, or you could say model save method is called only after pre_save is ...

    Django, with it’s experienced developer community and regular updates have become a reliable framework to build stable and maintainable websites. Not to forget the easy-to-understand the documentation it provides, makes it easier for the beginners to get their way started in Django

    Django,凭借其经验丰富的开发人员社区和定期更新,已成为构建稳定且可维护的网站的可靠框架。 别忘了它提供的易于理解的文档 ,使初学者更容易在Django中入门

    Without wasting much time on what Django is, let’s jump right into one of it’s most crucial topics- Signals

    在不花太多时间讨论Django是什么的情况下,让我们直接进入它最重要的主题之一- 信号

    什么是信号 (What are Signals)

    Signals, as the name suggests, allow applications to get notified when a certain event occurs. Suppose you want to notify the author of an article whenever someone comments or reacts on the article, but there are several places in your codebase to comment on an article or react on the article. How do you do it? You guessed it right, using signals. Signal hooks some piece of code to be executed as soon as a specific model’s save method is triggered.

    顾名思义,信号允许应用程序在发生特定事件时得到通知 。 假设您想在有人发表评论或对文章做出React时通知文章作者,但是您的代码库中有很多地方可以评论文章或对文章做出React。 你怎么做呢? 您使用信号猜对了。 特定模型的保存方法一被触发,Signal就会钩住要执行的某些代码。

    To have a clearer idea of the above example, let’s define the models.

    为了更清楚地了解上面的示例,让我们定义模型。

    何时使用信号 (When to use Signals)

    Signals are best used when multiple pieces of code are interested in the same model instance events. To understand model instance events in simpler terms, it means a row creation, updating or deletion events.

    当多个代码段对同一模型实例事件感兴趣时,最好使用信号。 为了用更简单的术语理解模型实例事件,这意味着创建行,更新或删除事件。

    如何使用信号 (How to use Signals)

    While there are many ways to use signals, my favourite way is to use the ‘@receiver’ decorator.

    尽管有很多使用信号的方法,但我最喜欢的方法是使用'@receiver'装饰器。

    Here is an example

    这是一个例子

    Image for post
    signals.py
    signal.py

    This might seem a bit confusing right now if you are a beginner, but let me help you out here.

    如果您是初学者,现在可能看起来有些混乱,但是让我在这里为您提供帮助。

    The receiver decorator her tells the code that the function(‘notify_user’ here) is about to receive a signal(post_save signal in this case). Now there are many types of Django signals, post_save(django.db.models.signals.post_save) is one of it. Let’s go through some of the important signals separately.

    接收方装饰器她告诉代码该函数(此处为'notify_user')即将接收信号(在这种情况下为post_save信号)。 现在有许多类型的Django信号, post_save ( django.db.models.signals.post_save )是其中之一。 让我们分别浏览一些重要信号。

    1.使用post_save的技巧 (1. Tips to use post_save)

    As the name suggests, it is called just after the Django model save() function has done its job. The sender parameter here defines the Model from which we are trying to receive the signal. So now if I am to convert the above python code in English, I would say:

    顾名思义,它是在Django模型save()函数完成其工作之后调用的。 这里的sender参数定义了我们试图从中接收信号的模型。 因此,现在如果我要将上述python代码转换为英语,我会说:

    Call the function ‘notifiy_author’ after the istance of ‘ArticleComments’ is saved

    保存“ ArticleComments”的位置 ,调用函数“ notifiy_author”

    Whenever we use signals, we get to use some variables. One of those variables, as you can see in the above code snippet is ‘instance’. This is nothing but the instance of the model ArticleComments which is being saved. So if I want to fetch the author of the comment, I can easily use:

    每当我们使用信号时,我们都会使用一些变量。 如您在上面的代码片段中所见,这些变量之一是'instance' 。 这不过是正在保存的ArticleComments模型的实例。 因此,如果我想获取评论的作者,则可以轻松使用:

    instance.article.author
    Image for post

    Now a perk about using post_save signal is that it provides us with a variable named created. This is a flag, which returns True if this post_save signal is called when a new instance(or row) of a model was created.

    现在,有关使用post_save信号的好处是,它为我们提供了一个名为created的变量。 这是一个标志,如果在创建模型的新实例(或行)时调用此post_save信号,则返回True。

    Following points should be kept in mind while using post_save:1. There are no special signals like pre_create or post_create. Whenever we call Model function create(), it calls the save signals.2. You cannot modify the value of the any instance’s fields(for ex: ‘instance.comment’ here) inside post_save, without calling Django save() method again, which is not(never) a good practice to call inside a signal of the same model(Can you guess why?)

    使用post_save时应牢记以下几点:1。 没有像pre_create或post_create这样的特殊信号。 每当我们调用模型函数create()时,它都会调用保存信号。2。 您不能在post_save内修改任何实例字段的值(例如,此处为“ instance.comment”),而无需再次调用Django save()方法,这不是(永远) 在同一信号内调用的好习惯模型 (您能猜出为什么吗?)

    2.像专业人士一样使用pre_save (2. Use pre_save like a pro)

    Pre_save (django.db.models.signals.pre_save) is provoked just before the model save() method is called, or you could say model save method is called only after pre_save is called and done its job free of errors.

    Pre_save( django.db.models.signals.pre_save )是在调用模型save()方法之前引发的,或者可以说只有在调用pre_save并完成其工作而没有错误之后,才调用模型保存方法。

    We know how to notify the author when a new comment is posted(the same way you can create a signal on the creation of ArticleReaction too), but what if I want to notify the author when the reaction is modified? pre_save comes in handy for similar cases.

    我们知道如何在发布新评论时通知作者(也可以在创建ArticleReaction时创建信号的方式),但是如果我想在修改React后通知作者怎么办? pre_save在类似情况下非常有用。

    Image for post
    signals.py
    signal.py

    We do not get ‘created’ variable to use in pre_save. No worries, we have a workaround for that too.

    我们没有在pre_save中使用“创建”变量。 不用担心,我们也有解决方法。

    All the model instances(or rows) have an auto-generated primary key which is name ‘id’. This id is numerically incremented as instances of the model are created. But the ‘id’ can only be generated/assigned after the creation of the row. Hence in pre_save, if we try to access the instance.id before the instance(or row) is created, it will return us None. So the condition on line 10 in the above snippet is nothing but a replica of ‘created’ from post_save.

    所有模型实例(或行)都有一个自动生成的主键,名称为'id'。 创建模型实例时,此id会按数字递增。 但是“ id”只能在创建行生成/分配。 因此,在pre_save中,如果我们尝试在创建实例(或行)之前访问instance.id,它将返回None。 因此,以上代码段中第10行的条件仅是post_save中“ created”的副本。

    Image for post
    line 10
    第10行

    (Notice how I am using ‘row’ to refer an instance of a model. It will help you to have a clearer imagination of what’s happenning behind the scenes. Similarly, attributes/firelds can be referred with another term ‘column’)

    (请注意,我是如何使用“行”来引用模型实例的。这将帮助您更清楚地了解幕后发生的事情。类似地,属性/对象也可以用另一个术语“列”来引用)

    Our problem statement was to notify the author if the reaction is changed. Let’s try to backtrace it. To find if the reaction was changed, we need the current reaction and the previous reaction. If the current reaction and the previous reaction does not match, then it concludes that the reaction was changed and hence we need to notify the author about it. But how exactly can we get the previous and the current reactions? To understand that, we have to know one VERY IMPORTANT property about the variable instance in post_save and pre_save:

    我们的问题陈述是,如果React发生更改,则通知作者。 让我们尝试回溯它。 为了确定React是否发生变化,我们需要当前React和先前React。 如果当前React和先前React不匹配,则得出结论,React已更改,因此我们需要将其通知作者。 但是,我们究竟如何才能获得先前和当前的React呢? 要了解这一点,我们必须了解有关post_save和pre_save中的变量实例的一个非常重要的属性:

    The post_save’s instance has the attributes with values which are already saved in your model, but the pre_save’s instance has the attributes with values which are yet to be saved in your model.

    post_save实例的属性值已保存在模型中,而pre_save实例的属性值已保存在模型中。

    To make the above line more clearly, let’s take an example. Some user named ‘Ravi’ has already reacted with a ‘Like’. Ravi has a habit of reading everything twice. After reading the article again, he decided to change his reaction to ‘Love’.

    为了使以上内容更加清晰,我们来看一个例子。 一些名为“ Ravi”的用户已经做出了“赞”的React。 拉维有阅读两次所有内容的习惯。 再次阅读文章后,他决定将自己的React更改为“爱”。

    Image for post

    Let’s dive back inside our code again. Pre_save is called as soon as Ravi changed the reaction. Since the instance(or row) was already created, we move directly to the else condition in Line 14. Using the above-highlighted property, we can say that the variable ‘instance’ will have the new value ‘Love’ for its attribute ‘reaction’. Let’s name this modified variable ‘instance’ as ‘created’ (Line 15). Now we just need to get the old reaction. Remember that the ‘Love’ reaction has not been saved in our model yet(since we are still in pre_save). So what will we get if we try to get a model instance of ArticleReaction with the id provided by pre_save? We will get the instance with the reaction ‘Like’. Now let’s name this as ‘previous’(line 16). As we now have both old and new instances, we can easily compare these reactions and code are conditions accordingly.

    让我们再次跳回代码内部。 Ravi更改React后,将立即调用Pre_save。 由于已经创建了实例(或行),因此我们直接移至第14行中的else条件。使用上面突出显示的属性,我们可以说变量“ instance”为其属性“”具有新的值“ Love”React'。 让我们将此修改后的变量“实例”命名为“创建”(第15行)。 现在我们只需要得到旧的React。 请记住,“爱”React尚未保存在我们的模型中(因为我们仍处于pre_save状态)。 那么,如果我们尝试使用pre_save提供的ID来获取ArticleReaction的模型实例,将会得到什么呢? 我们将获得带有“ Like”React的实例。 现在,将其命名为“ previous”(第16行)。 由于现在有了新旧实例,我们可以轻松地比较这些React,并且代码相应地是条件。

    Image for post
    line 15 and 16
    第15和16行

    Since pre_save is called right before the model save() method, you can also modify the instance’s fields as per the requirement. For example, if we are using pre_save for ArticleComments and we want to check and remove any abuse words from comments before it is saved in our model, we can do it like this:

    由于pre_save在模型save()方法之前被调用,因此您还可以根据需求修改实例的字段 。 例如,如果我们在文章评论中使用pre_save,并且想要在注释中删除任何滥用词,然后再将其保存在模型中,则可以这样进行:

    if is_abuse(instance.comment):
    instance.comment = remove_abusive(instance.comment)

    Assuming that is_abusive and remove_abusive is your custom method. Also notice that we are not calling instance.save() after changing the instance.comment. Can you tell why?

    假设is_abusive和remove_abusive是您的自定义方法。 还要注意,在更改instance.comment之后,我们没有调用instance.save()。 你能说出为什么吗?

    3.其他信号 (3. Other Signals)

    There many more signals you can use, which you can find here, but this blog was just an attempt to give you the idea of how you can use signals effectively.

    您可以在这里找到更多可以使用的信号,但是此博客只是尝试向您提供如何有效使用信号的想法。

    在我们完成之前 (Before we finish)

    Even though signals come in handy when you want to perform actions behind the scenes, you have to be very careful about how you use it.

    即使您想在幕后执行操作时,即使信号会派上用场,您也必须非常谨慎地使用它。

    1. Do not compromise speed: putting too much load on pre_save or post_save signals might make the model save() method slow.

      不要牺牲速度 :在pre_save或post_save信号上增加过多的负载可能会使模型save()方法变慢。

    2. Lost in the loop: Calling the save() method for the sender model inside the post_save or pre_save will keep calling the signals repetitively.

      迷失在循环中:在post_save或pre_save内部调用sender模型的save()方法将继续重复调用信号。

    3. Remember the use cases: We use post_save when we are interested more in the creation of a model instance without modifying the values, while we use pre_save when we are more into the monitoring the change in model instance’s value, or if we are into modifying the instance’s attribute’s values ourselves.

      记住用例:当我们对模型实例的创建更感兴趣而不修改值时,我们使用post_save;而当我们更想监视模型实例的值的变化时,或者如果我们要修改模型时,则使用pre_save。实例属性的值本身。

    4. update() and save signals don’t get along: Django model ‘update()’ method does not invoke any kind of pre_save or post_save signals.

      update()和save信号不兼容:Django模型的update()方法不会调用任何pre_save或post_save信号。

    翻译自: https://medium.com/@singhgautam7/django-signals-master-pre-save-and-post-save-422889b2839

    展开全文
  • Spring-Data-Jpa 保存时save和saveAndFlush的区别 Jpa是我们经常用到的ORM框架,使用它可以快速便捷的操作数据库,那么它有一个保存方法,你肯定不会陌生,就是save方法和saveAndFlush,这两个方法可能会经常用到,...

    Spring-Data-Jpa 保存时save和saveAndFlush的区别

    Jpa是我们经常用到的ORM框架,使用它可以快速便捷的操作数据库,那么它有一个保存方法,你肯定不会陌生,就是save方法和saveAndFlush,这两个方法可能会经常用到,那么什么时候使用save方法,什么时候使用saveAndFlush呢,下面就进行简单总结一下。

    Jpa save

    首先创建一个表,进行完整的代码演示。

    -- auto-generated definition
    create table t_user
    (
        id              int auto_increment primary key,
        name            varchar(255) not null,
        age             int          not null,
        is_deleted      tinyint      null,
        created_at      datetime     null,
        last_updated_at datetime     null,
        created_by      mediumtext   not null
    );
    
    

    上述我创建了一个t_user表,然后创建相应的entity.

    @Entity
    @Data
    @ToString
    @Table(name = "t_user")
    @EntityListeners(value = AuditingEntityListener.class)
    public class UserEntity extends AbstractAggregateRoot<UserEntity> {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "id", columnDefinition = "int")
        private Integer id;
        /**
         * 年龄
         */
        @Column(name = "age", columnDefinition = "int")
        private Integer age;
        /**
         * 名称
         */
        @Column(name = "name", columnDefinition = "varchar")
        private String name;
    
        @CreatedDate
        @Column(name = "created_at", columnDefinition = "datetime")
        private LocalDateTime createdAt;
    
        @LastModifiedDate
        @Column(name = "last_updated_at", columnDefinition = "datetime")
        private LocalDateTime lastUpdatedAt;
    
        @CreatedBy
        @Column(name = "created_by", columnDefinition = "long")
        private Long createdBy;
    
        @Column(name = "is_deleted", columnDefinition = "tinyint")
        private Integer isDeleted;
    
    }
    

    上述创建好之后,再建立一个UserRepository,就可以使用了reposity来进行操作了。
    下面直接列出service层代码,我去随机生成用户名,然后进行更新.

    下面列出Repository代码

    public interface UserRepository extends JpaRepository<UserEntity, Integer>, CustomUserRepository {
    }
    
    
    @Transactional(rollbackFor = Exception.class)
        public void updateName() {
            UserEntity userEntity = userRepository.findById(1).orElseThrow(() -> new RuntimeException("error"));
            String str = UUID.randomUUID().toString();
            System.out.println(str);
            userEntity.setName(str);
            // 使用save进行保存
            userRepository.save(userEntity);
            // 使用saveAndFlush进行保存
            userRepository.saveAndFlush(userEntity);
        }
    
    

    上述代码执行完毕之后,不管是save还是saveAndFlush都执行成功,那么二者究竟有何不同呢。

    底层实现

    其实我们在使用jpa的时候,直接根据Entity来编写Repository层代码,而Repository是一个接口,那么在IOC容器中肯定是Spring帮我们生成了动态代理类,从而帮助我们进行增强逻辑,实现和数据库层面的交互。我们不妨直接在service层打断点,然后看看具体的repository对象是什么。
    repository

    通过上述打断点来到了service方法里面,定位到repository其实是一个SimpleJpaRepository,这个SimpleJpaRepository 是由 jpa 来实现的,它一定实现了Repository接口,我们点进这个类里面的具体源码。

    下面是我在SimpleJpaRepository里面找到的具体方法的源码。

    /*
    	 * (non-Javadoc)
    	 * @see org.springframework.data.repository.CrudRepository#save(java.lang.Object)
    	 */
    	@Transactional
    	@Override
    	public <S extends T> S save(S entity) {
        // 这里的em其实是EntityManager,它是javax定义的规范,这里jpa使用了它,
        // 可以看到,首先save的时候,去判断这个entity是不是新的,如果是新的就去save,对应到数据库里面其实就是增加了一条记录。isNew其实就是判断entity里面有没有id值,如果有就是更新,没有的话,认为是新增记录。
    		if (entityInformation.isNew(entity)) {
    			em.persist(entity);
    			return entity;
    		} else {
        // 如果不是新的,那么就进行merge,其实就是update.
    			return em.merge(entity);
    		}
    	}
      
    /// 下面是saveAndFlush源码,它会首先调用save方法去保存,然后其次调用了一个方法
    
    	/*
    	 * (non-Javadoc)
    	 * @see org.springframework.data.jpa.repository.JpaRepository#saveAndFlush(java.lang.Object)
    	 */
    	@Transactional
    	@Override
    	public <S extends T> S saveAndFlush(S entity) {
    
    		S result = save(entity);
        /// 多调用了一个 flush 方法
    		flush();
    
    		return result;
    	}
      
      /*
       * flush方法仅仅由entityManager又去调用了它里面的flush方法
    	 * (non-Javadoc)
    	 * @see org.springframework.data.jpa.repository.JpaRepository#flush()
    	 */
    	@Transactional
    	@Override
    	public void flush() {
    		em.flush();
    	}
      
    

    下面截取了isNew的核心方法,其实就是判断有没有ID值,如果entity里面有id不为空,那么就认为你是更新,否则就是save保存。

    
    public boolean isNew(T entity) {
    
    		ID id = getId(entity);
    		Class<ID> idType = getIdType();
    
    		if (!idType.isPrimitive()) {
    			return id == null;
    		}
    
    		if (id instanceof Number) {
    			return ((Number) id).longValue() == 0L;
    		}
    
    		throw new IllegalArgumentException(String.format("Unsupported primitive id type %s!", idType));
    	}
    
    

    通过上述代码可以看到 saveAndFlush和save方法其实就差了一个entityManager的flush方法。其实从方法名字也可以看的出来的。

    那么em.flush究竟做了哪些事呢。

    遇到的坑

    开启两个事务 A和B,都修改id为1的这条数据,同时设置JPA将sql语句打印至控制台 便于观察,执行情况, 表中数据如下:

    [
      {
        "id": 1,
        "name": "f7c8264c-b213-4c8f-b642-0fa1a819ade7",
        "age": 43,
        "is_deleted": 0,
        "created_at": "2021-01-04 18:26:32",
        "last_updated_at": "2021-01-18 00:35:16",
        "created_by": "0"
      }
    ]
    

    可以看到name是一个随机字符串, 年龄是43。


    事务A(线程A)事务B(线程B)
    更新用户姓名(更新为随机字符串)更新用户年龄 (更新为随机数字)
    save(userEntity)save(userEntity)
    事务卡在这儿不提交
    事务提交

    观看上述执行流程,会发生什么情况呢?

    首先看上述流程对应的代码演示, 注意 两个方法都加了事务哦

    
    // 定义了两个方法,一个修改name,一个修改age。说一下这里为啥用随机字符串和随机数字
    
    // ps: 如果jpa发现你的entity数据没有变更,是不会执行更新的呦,所以 我这里进行了随机字符串设置,便于我进行测试。
    
        // 对应上面流程的事务A
        @Transactional(rollbackFor = Exception.class)
        public void updateName() {
            UserEntity userEntity = userRepository.findById(1).orElseThrow(() -> new RuntimeException("error"));
            String str = UUID.randomUUID().toString();
            // 将生成的随机字符串进行打印,便于我对比数据库更新情况。
            System.out.println(str);
            userEntity.setName(str);
            userRepository.save(userEntity);
            
            // 睡上几分钟,sleep代码省略....
        }
    
        // 对应上述流程的事务B
        @Transactional
        public void updateAge() {
            UserEntity userEntity = userRepository.findById(1).orElseThrow(() -> new RuntimeException("error"));
            int random = ThreadLocalRandom.current().nextInt(100);
            // 打印生成的随机数字
            System.out.println("random : " + random);
            userEntity.setAge(random);
            userRepository.save(userEntity);
        }
    
    

    我当时按照数据库行锁理论,首先想到了肯定会阻塞,由于事务A先执行了save操作,然后事务卡在下面了,那么事务B肯定就没办法执行喽。但是并没有哎,事务B仍然顺利执行。

    然后我观察控制台,发现并没有任何输出,这就表示了,sql没发送到mysql服务器,那么mysql端肯定不会给你加行锁喽。

    debug情况展示.

    在这里插入图片描述

    可以看到save方法执行完成,事务没有提交的时候,是不会将update语句发送至mysql服务器的, 没有任何的update相关sql打印。

    下面写一个controller 来进行访问修改年龄的接口,看看会不会卡住, 这里便于演示,我直接用Get请求了。

      @GetMapping("/user/age")
      public String updateAge() {
            userService.updateAge();
            return "OK";
      }
    

    结果如下:
    在这里插入图片描述

    左边部分请求更改姓名接口,会进行sleep住,右边部分直接请求修改年龄,可以看到一下就执行完了,没有任何卡住。

    然后果断 改成saveAndFlush 再试一次, 对应的执行流程如下:

    事务A(线程A)事务B(线程B)
    更新用户姓名(更新为随机字符串)更新用户年龄 (更新为随机数字)
    saveAndFlush(userEntity)save(userEntity)
    事务卡在这儿不提交
    事务提交

    发现这次符合预期,事务B果然卡住了,等待事务A执行结束。

    对应的代码如下, 与上述代码差别不大,只是事务A 对应的save操作换成了saveAndFlush()

        
        // 对应上面流程的 事务A
        @Transactional(rollbackFor = Exception.class)
        public void updateName() throws InterruptedException {
            UserEntity userEntity = userRepository.findById(1).orElseThrow(() -> new RuntimeException("error"));
            String str = UUID.randomUUID().toString();
            System.out.println(str);
            userEntity.setName(str);
            // 注意 换成了saveAndFlush()
            userRepository.saveAndFlush(userEntity);
    
            TimeUnit.SECONDS.sleep(2000);
        }
    
        @Transactional
        public void updateAge() {
            UserEntity userEntity = userRepository.findById(1).orElseThrow(() -> new RuntimeException("error"));
            int random = ThreadLocalRandom.current().nextInt(100);
            System.out.println("random : " + random);
            userEntity.setAge(random);
            userRepository.save(userEntity);
        }
    
    

    debug执行情况如下:

    在这里插入图片描述

    可以清晰的看到久违的update语句终于打印出来了,这时候 如果执行更改年龄的操作,必然会卡住,继续写个controller。

      @GetMapping("/user/age")
      public String updateAge() {
            userService.updateAge();
            return "OK";
      }
    

    Controller方法同上,为了方便测试,直接使用了Get方法进行测试。

    在这里插入图片描述

    左边部分依旧修改姓名,会进行sleep几分钟,右边修改年龄,可以看到,修改年龄的请求被阻塞住了。

    上面就是save和saveAndFlush最明显的区别,save等到事务进行提交时,才进行doFlush,刷新sql至MySQL服务器,而saveAndFlush会直接立刻马上的将SQL发送至MySQL服务端。所以在使用的时候需要注意,如果有更新之后发送消息的场景,使用save需谨慎。

    例如,下面代码:

    @Transactional(rollbackFor = Exception.class)
        public void updateName() throws InterruptedException {
            UserEntity userEntity = userRepository.findById(1).orElseThrow(() -> new RuntimeException("error"));
            String str = UUID.randomUUID().toString();
            System.out.println(str);
            userEntity.setName(str);
            userRepository.save(userEntity);
            
            // 发送消息至rabbitMQ
            rabbitTemplate.sendAndConvert("更新用户名称");
        }
    
    

    上面代码由于在执行过程中,直接在事务中发消息,可能会导致mq消息已经发送到exchange,而userEntitiy在事务提交的时候 因字段错误或其他异常,会在将sql发送至mysql服务器时,由服务端报出错误。但是这时候MQ消息已经发送出去了,就导致了事务的不一致性。
    关于解决方式以及原理,我会在后续事务相关的文章中,继续介绍。

    使用总结

    • save和saveAndFlush其实底层多了一个entityManager的flush操作。而这个flush操作会将执行的sql发送至数据库服务器。而save方法需等到事务提交的时候,才会进行发送sql执行sql语句。

    • 在使用的时候,如果save使用不当,当前事务不提交,这时候其他事务过来进行修改数据,可能会产生数据覆盖的情况。

    • 而在使用saveAndFlush的时候,当前事务不提交,其他事务过来的时候修改同一行记录,会产生锁等待现象,如果使用saveAndFlush建议将saveAndFlush操作放在最后执行,最大粒度的减少锁等待时间。

    如果有收获的话,欢迎点赞,留言,转发哦~

    展开全文
  • Image.Save 方法

    千次阅读 2020-08-24 10:54:24
    Save(String, ImageCodecInfo, EncoderParameters) 使用指定的编码器和图像编码器参数,将该 Image 保存到指定的文件。 Save(Stream, ImageCodecInfo, EncoderParameters) 使用指定的编码器和图像编码器参数,将该...

    Namespace:System.Drawing
    Assembly:System.Drawing.dll

    将此图像以指定的格式保存到指定的流中。

    重载

    方法名称说明
    Save(String, ImageCodecInfo, EncoderParameters)使用指定的编码器和图像编码器参数,将该 Image 保存到指定的文件。
    Save(Stream, ImageCodecInfo, EncoderParameters)使用指定的编码器和图像编码器参数,将该图像保存到指定的流。
    Save(String, ImageFormat)将此 Image 以指定格式保存到指定文件。
    Save(Stream, ImageFormat)将此图像以指定的格式保存到指定的流中。
    Save(String)将该 Image 保存到指定的文件或流。

    Save(String, ImageCodecInfo, EncoderParameters)

    使用指定的编码器和图像编码器参数,将该 Image 保存到指定的文件。

    public void Save (string filename, System.Drawing.Imaging.ImageCodecInfo encoder, System.Drawing.Imaging.EncoderParameters encoderParams);
    

    参数

    filename String
    字符串,包含要将此 Image 保存到的文件的名称。

    encoder ImageCodecInfo
    用于此 ImageCodecInfoImage

    encoderParams EncoderParameters
    用于该 EncoderParametersImage

    异常

    ArgumentNullException

    filenameencodernull.

    ExternalException

    该图像以错误的图像格式保存。
    - 或 -
    该图像被保存到创建该图像的文件。

    示例

    下面的示例从 BMP 文件创建一个 Bitmap 对象。 该代码将位图保存为三个 JPEG 文件,每个文件都有不同的质量级别。

    using System;
    using System.Drawing;
    using System.Drawing.Imaging;
    class Example_SetJPEGQuality
    {
        public static void Main()
        {
            Bitmap myBitmap;
            ImageCodecInfo myImageCodecInfo;
            Encoder myEncoder;
            EncoderParameter myEncoderParameter;
            EncoderParameters myEncoderParameters;
                         
            // Create a Bitmap object based on a BMP file.
            myBitmap = new Bitmap("Shapes.bmp");
                         
            // Get an ImageCodecInfo object that represents the JPEG codec.
            myImageCodecInfo = GetEncoderInfo("image/jpeg");
                         
            // Create an Encoder object based on the GUID
                         
            // for the Quality parameter category.
            myEncoder = Encoder.Quality;
                         
            // Create an EncoderParameters object.
                         
            // An EncoderParameters object has an array of EncoderParameter
                         
            // objects. In this case, there is only one
                         
            // EncoderParameter object in the array.
            myEncoderParameters = new EncoderParameters(1);
                         
            // Save the bitmap as a JPEG file with quality level 25.
            myEncoderParameter = new EncoderParameter(myEncoder, 25L);
            myEncoderParameters.Param[0] = myEncoderParameter;
            myBitmap.Save("Shapes025.jpg", myImageCodecInfo, myEncoderParameters);
                         
            // Save the bitmap as a JPEG file with quality level 50.
            myEncoderParameter = new EncoderParameter(myEncoder, 50L);
            myEncoderParameters.Param[0] = myEncoderParameter;
            myBitmap.Save("Shapes050.jpg", myImageCodecInfo, myEncoderParameters);
                         
            // Save the bitmap as a JPEG file with quality level 75.
            myEncoderParameter = new EncoderParameter(myEncoder, 75L);
            myEncoderParameters.Param[0] = myEncoderParameter;
            myBitmap.Save("Shapes075.jpg", myImageCodecInfo, myEncoderParameters);
        }
        private static ImageCodecInfo GetEncoderInfo(String mimeType)
        {
            int j;
            ImageCodecInfo[] encoders;
            encoders = ImageCodecInfo.GetImageEncoders();
            for(j = 0; j < encoders.Length; ++j)
            {
                if(encoders[j].MimeType == mimeType)
                    return encoders[j];
            }
            return null;
        }
    }
    

    备注

    不允许将图像保存到从中构建它的文件,并且会引发异常。

    Save(Stream, ImageCodecInfo, EncoderParameters)

    使用指定的编码器和图像编码器参数,将该图像保存到指定的流。

    public void Save (System.IO.Stream stream, System.Drawing.Imaging.ImageCodecInfo encoder, System.Drawing.Imaging.EncoderParameters encoderParams);
    

    参数

    stream Stream
    将在其中保存图像的 Stream

    encoder ImageCodecInfo
    用于此 ImageCodecInfoImage

    encoderParams EncoderParameters
    一个 EncoderParameters,它指定图像编码器使用的参数。

    异常

    ArgumentNullException
    streamnull

    ExternalException
    该图像以错误的图像格式保存。

    备注

    不要将图像保存到用于构造映像的相同流中。 这样做可能会损坏流。
    必须将该图像保存到流中偏移量为零的位置。 如果在保存映像之前已向流中写入任何其他数据,则流中的图像数据将损坏。

    Save(String, ImageFormat)

    将此 Image 以指定格式保存到指定文件。

    public void Save (string filename, System.Drawing.Imaging.ImageFormat format);
    

    参数

    filename String
    字符串,包含要将此 Image 保存到的文件的名称。

    format ImageFormat
    用于此 ImageFormatImage

    异常

    ArgumentNullException
    filenameformatnull.

    ExternalException
    该图像以错误的图像格式保存。
    - 或 -
    该图像被保存到创建该图像的文件。

    示例

    下面的代码示例演示如何从类型构造位图,以及如何使用 Save 方法。 若要运行此示例,请将代码粘贴到 Windows 窗体中。 处理窗体的 Paint 事件,并调用 ConstructFromResourceSaveAsGif 方法,并将 e 作为 PaintEventArgs

    private void ConstructFromResourceSaveAsGif(PaintEventArgs e)
    {
    
        // Construct a bitmap from the button image resource.
        Bitmap bmp1 = new Bitmap(typeof(Button), "Button.bmp");
    
        // Save the image as a GIF.
        bmp1.Save("c:\\button.gif", System.Drawing.Imaging.ImageFormat.Gif);
    
        // Construct a new image from the GIF file.
        Bitmap bmp2 = new Bitmap("c:\\button.gif");
    
        // Draw the two images.
        e.Graphics.DrawImage(bmp1, new Point(10, 10));
        e.Graphics.DrawImage(bmp2, new Point(10, 40));
    
        // Dispose of the image files.
        bmp1.Dispose();
        bmp2.Dispose();
    }
    

    Save(Stream, ImageFormat)

    将此图像以指定的格式保存到指定的流中。

    public void Save (System.IO.Stream stream, System.Drawing.Imaging.ImageFormat format);
    

    参数

    stream Stream
    将在其中保存图像的 Stream

    format ImageFormat
    ImageFormat,指定保存的图像的格式。

    异常

    ArgumentNullException
    streamformatnull

    ExternalException
    该图像以错误的图像格式保存

    备注

    应避免将图像保存到用于构造它的同一个流中。 这样做可能会损坏流。
    必须将该图像保存到流中偏移量为零的位置。 如果在保存映像之前已向流中写入任何其他数据,则流中的图像数据将损坏。

    Save(String)

    将该 Image 保存到指定的文件或流。

    public void Save (string filename);
    

    参数

    filename String
    字符串,包含要将此 Image 保存到的文件的名称。

    异常

    ArgumentNullException
    filenamenull.

    ExternalException
    该图像以错误的图像格式保存。
    - 或 -
    该图像被保存到创建该图像的文件。

    示例

    下面的代码示例演示如何调用 Save 方法。 此示例旨在与 Windows 窗体一起使用。 创建一个包含名为 Button5的按钮的窗体。 将代码粘贴到窗体中,并将该方法与按钮的 Click 事件相关联。

    private void Button5_Click(System.Object sender, System.EventArgs e)
    {
        try
        {
            if (image1 != null)
            {
                image1.Save("c:\\myBitmap.bmp");
                Button5.Text = "Saved file.";
            }
        }
        catch(Exception)
        {
            MessageBox.Show("There was a problem saving the file." +
                "Check the file permissions.");
        }
    }
    

    备注

    如果图像的文件格式不存在编码器,则使用可移植网络图形(PNG)编码器。 当使用 Save 方法将图形图像保存为 Windows 图元文件格式(WMF)或增强型图元文件格式(EMF)文件时,生成的文件将另存为可移植网络图形(PNG)文件。 出现此行为是因为 .NET FrameworkGDI+ 组件没有可用于将文件另存为 .wmf.emf 文件的编码器。

    不允许将图像保存到从中构建它的文件,并且会引发异常。

    展开全文
  • keras保存模型中的save()和save_weights()

    万次阅读 多人点赞 2019-01-23 16:38:23
    今天做了一个关于keras保存模型的实验...同样是h5文件用save()和save_weight()保存效果是不一样的。 我们用宇宙最通用的数据集MNIST来做这个实验,首先设计一个两层全连接网络: inputs = Input(shape=(784, )) ...

    今天做了一个关于keras保存模型的实验,希望有助于大家了解keras保存模型的区别。


    我们知道keras的模型一般保存为后缀名为h5的文件,比如final_model.h5。同样是h5文件用save()和save_weight()保存效果是不一样的。

    我们用宇宙最通用的数据集MNIST来做这个实验,首先设计一个两层全连接网络:

    inputs = Input(shape=(784, ))
    x = Dense(64, activation='relu')(inputs)
    x = Dense(64, activation='relu')(x)
    y = Dense(10, activation='softmax')(x)
    
    model = Model(inputs=inputs, outputs=y)

    然后,导入MNIST数据训练,分别用两种方式保存模型,在这里我还把未训练的模型也保存下来,如下:

    from keras.models import Model
    from keras.layers import Input, Dense
    from keras.datasets import mnist
    from keras.utils import np_utils
    
    
    (x_train, y_train), (x_test, y_test) = mnist.load_data()
    x_train=x_train.reshape(x_train.shape[0],-1)/255.0
    x_test=x_test.reshape(x_test.shape[0],-1)/255.0
    y_train=np_utils.to_categorical(y_train,num_classes=10)
    y_test=np_utils.to_categorical(y_test,num_classes=10)
    
    inputs = Input(shape=(784, ))
    x = Dense(64, activation='relu')(inputs)
    x = Dense(64, activation='relu')(x)
    y = Dense(10, activation='softmax')(x)
    
    model = Model(inputs=inputs, outputs=y)
    
    model.save('m1.h5')
    model.summary()
    model.compile(loss='categorical_crossentropy', optimizer='sgd', metrics=['accuracy'])
    model.fit(x_train, y_train, batch_size=32, epochs=10)
    #loss,accuracy=model.evaluate(x_test,y_test)
    
    model.save('m2.h5')
    model.save_weights('m3.h5')
    

    如上可见,我一共保存了m1.h5, m2.h5, m3.h5 这三个h5文件。那么,我们来看看这三个玩意儿有什么区别。首先,看看大小:

    m2表示save()保存的模型结果,它既保持了模型的图结构,又保存了模型的参数。所以它的size最大的。

    m1表示save()保存的训练前的模型结果,它保存了模型的图结构,但应该没有保存模型的初始化参数,所以它的size要比m2小很多。

    m3表示save_weights()保存的模型结果,它只保存了模型的参数,但并没有保存模型的图结构。所以它的size也要比m2小很多。

     

    通过可视化工具,我们发现:(打开m1和m2均可以显示出以下结构)

    而打开m3的时候,可视化工具报错了。由此可以论证, save_weights()是不含有模型结构信息的。


    加载模型

    两种不同方法保存的模型文件也需要用不同的加载方法。

    from keras.models import load_model
    
    model = load_model('m1.h5')
    #model = load_model('m2.h5')
    #model = load_model('m3.h5')
    model.summary()
    

     只有加载m3.h5的时候,这段代码才会报错。其他输出如下:

    可见,由save()保存下来的h5文件才可以直接通过load_model()打开

    那么,我们保存下来的参数(m3.h5)该怎么打开呢?

    这就稍微复杂一点了,因为m3不含有模型结构信息,所以我们需要把模型结构再描述一遍才可以加载m3,如下:

    from keras.models import Model
    from keras.layers import Input, Dense
    
    
    inputs = Input(shape=(784, ))
    x = Dense(64, activation='relu')(inputs)
    x = Dense(64, activation='relu')(x)
    y = Dense(10, activation='softmax')(x)
    
    model = Model(inputs=inputs, outputs=y)
    model.load_weights('m3.h5')

    以上把m3换成m1和m2也是没有问题的!可见,save()保存的模型除了占用内存大一点以外,其他的优点太明显了。所以,在不怎么缺硬盘空间的情况下,还是建议大家多用save()来存。

    注意!如果要load_weights(),必须保证你描述的有参数计算结构与h5文件中完全一致!什么叫有参数计算结构呢?就是有参数坑,直接填进去就行了。我们把上面的非参数结构换了一下,发现h5文件依然可以加载成功,比如将softmax换成relu,依然不影响加载。

     

    对于keras的save()和save_weights(),完全没问题了吧

     

    展开全文
  • Matlab工具使用(一):Save语法

    千次阅读 2019-02-22 14:42:22
    save 将工作区变量保存到文件中 全页折叠 语法 save(filename) save(filename,variables) save(filename,variables,fmt) save(filename,variables,version) save(filename,variables,version,'-no...
  • docker save与docker export的区别

    万次阅读 多人点赞 2017-09-25 20:29:36
    docker save和docker export都能导出镜像包,咋看起来区别似乎不大。本文就针对这个问题,试图搞清楚docker save和docker export的功能是什么?适用于什么应用场景? 本文的测试的Docker版本如下,不保证所有版本的...
  • model.save()保存了模型的图结构和模型的参数,保存模型的后缀是.hdf5。 model. save_weights ()只保存了模型的参数,并没有保存模型的图结构,保存模型的后缀使用.h5。 所以使用save_weights保存的模型比使用save...
  • numpy save & load

    千次阅读 2020-04-12 10:13:09
    numpy.save 保存一个数组到一个二进制的文件中,保存格式是.npy 参数介绍 numpy.save(file, arr, allow_pickle=True, fix_imports=True) file:文件名/文件路径 arr:要存储的数组 allow_pickle:布尔值,允许使用...
  • 使用方法1.[Easy Save3存储支持的类型](https://docs.moodkie.com/easy-save-3/es3-supported-types/)2.设置3.Keys, Paths and LocationsFilePlayerPrefsResourcesMemory5.加密6.保存并加载字符串和字节到文件7.保存...
  • canvas.save(Canvas.CLIP_SAVE_FLAG); 改为: canvas.save(); 相关文档:https://developer.android.com/sdk/api_diff/28/changes/android.graphics.Canvas 涉及到的自定义类: package com.exam...
  • PyTorch:模型save和load

    千次阅读 2020-10-28 23:06:25
    A common PyTorch convention is to save models using either a.ptor.pthfile extension. 保存加载整个模型(不推荐) 保存整个网络模型 (网络结构+权重参数) torch.save(model, 'net.pth')加载整个网络...
  • SpringBoot实现JPA的save操作

    千次阅读 2019-11-03 19:54:30
      在一次参与公司的技术讨论会上,一位同事在演示SpringBoot的JPA的操作时,发现SpringBoot的JPA的save操作时,发现会先有select再insert,然后老板说,我们在网关已经处理过select了,我们调用save肯定是想直接...
  • 本文档提供了关于PyTorch模型的保存和加载的各种用例的解决方案。 可以随意阅读整个文档,或者跳过所需的代码以获得所需的用例。 ...torch.save: 将序列化对象保存到磁盘。此函数使用Python的 p...
  • %文件夹以VC中的数字命名 VC = [5 10 20 30 40 50]; V = 30; for i=1:1:8 %判断相应的文件夹 if V == VC(i) break; end ...%画出在该速度下的某个变量相应曲线;...saveas(gcf,['E:/desk/pic/' num2str(VC(i))...
  • docker中save与load的使用及注意事项

    千次阅读 2019-07-16 18:23:03
    对于没有私有仓库来说,将本地镜像放到其它服务器上执行时,可以使用save和load方法,前者用来把镜像保存一个tar文件,后台从一个tar文件恢复成一个镜像,这个功能对于开发者来说还是很方便的!下面就带大家来实现...
  • 表达式.SaveAs(FileName, FileFormat, Password, WriteResPassword, ReadOnlyRecommended, CreateBackup, AccessMode, ConflictResolution, AddToMru, TextCodepage, TextVisualLayout, Local) 表达式 一个代表 ...
  • Spring JPA save 实现主键重复抛异常

    千次阅读 2019-11-07 09:29:51
    作为数据库的主键,唯一性已经保证了不会出现一个订单有多个锁的情况,若不希望自己主动地 find 后再 save,那就必须让 JPA 固定的生成 insert sql,利用 db 报错来发现重复锁的问题 除此以外第二个问题,每次 ...
  • MATLAB的save用法

    万次阅读 多人点赞 2018-09-11 22:37:09
    save 将工作区变量保存到文件中 语法 save(filename) save(filename,variables) save(filename,variables,fmt) save(filename,variables,version) save(filename,variables,version,'-nocompression') ...
  • 搜集的VC操作Excel的方法以及SaveAs 的用法大全 可以应用在VS2005的开发环境下 需要的朋友拿走

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,363,623
精华内容 545,449
关键字:

save