Spring-boot 注解学习

目录

@Compnent

@Bean

@CopmponentScan

@Configuration

@Autowired

Lombok常用的注解

@Retention

@ControllerAdvice

@ResponseStatus

JPA相关注解

@Entity 

@Table 

@Id 

@GeneratedValue

@Temporal

@OneToMany,@ManyToOne,@ManyToMany

@JoinColumn


@Compnent

标注Spring管理的Bean,使用@Component注解在一个类上,表示将此类标记为Spring容器中的一个Bean。相当于配置文件中的 <bean id="" class=""/>。当我们的类不属于各种归类的时候(不属于@Controller、@Services等的时候),我们就可以使用@Component来标注这个类。

实例:

@Component("conversionImpl")
//其实默认的spring中的Bean id 为 conversionImpl(首字母小写)
public class ConversionImpl implements Conversion {
    @Autowired
    private RedisClient redisClient;
}

源码分析:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface Component {
    String value() default "";
}

-value @Component默认值为该类首字母小写的类名,当然你也可以自定义。

@Bean

Spring的@Bean注解用于告诉方法,产生一个Bean对象,然后这个Bean对象交给Spring管理。产生这个Bean对象的方法Spring只会调用一次,随后这个Spring将会将这个Bean对象放在自己的IOC容器中。主要用在@Configuration注解的类里,也可以用在@Component注解的类里。添加的bean的id为方法名

实例:

在src根目录下创建一个AppConfig的配置类,这个配置类也就是管理一个或多个bean 的配置类,并在其内部声明一个myBean的bean,并创建其对应的实体类。


@Configuration
public class AppConfig {
    // 使用@Bean 注解表明myBean需要交给Spring进行管理
    // 未指定bean 的名称,默认采用的是 "方法名" + "首字母小写"的配置方式
    @Bean
    public MyBean myBean(){
        return new MyBean();
    }
}
public class MyBean {
 
    public MyBean(){
        System.out.println("MyBean Initializing");
    }
}

在对应的test文件夹下创建一个测试类SpringBeanApplicationTests,测试上述代码的正确性


public class SpringBeanApplicationTests {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        context.getBean("myBean");
    }
}

源码分析:

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Bean {
    @AliasFor("name")
    String[] value() default {};

    @AliasFor("value")
    String[] name() default {};

    /** @deprecated */
    @Deprecated
    Autowire autowire() default Autowire.NO;

    boolean autowireCandidate() default true;

    String initMethod() default "";

    String destroyMethod() default "(inferred)";
}

-value:name属性的别名,在不需要其他属性时使用,也就是说value 就是默认值

-name:此bean 的名称,或多个名称,主要的bean的名称加别名。如果未指定,则bean的名称是带注解方法的名称。如果指定了,方法的名称就会忽略,如果没有其他属性声明的话,bean的名称和别名可能通过value属性配置

-autowire :此注解的方法表示自动装配的类型,返回一个Autowire类型的枚举,
 

疑惑?

@Bean与@Componet的区别和联系?

@Component 和 @Bean 是两种使用注解来定义bean的方式。

@Component(和@Service和@Repository)用于自动检测和使用类路径扫描自动配置bean。注释类和bean之间存在隐式的一对一映射(即每个类一个bean)。

@Bean用于显式声明单个bean,而不是让Spring像上面那样自动执行它。它将bean的声明与类定义分离,并允许您精确地创建和配置bean。

如果想将第三方的类变成组件装配到你的应用中,你又没有没有源代码,也就没办法使用@Component进行自动配置,这种时候使用@Bean就比较合适了。不过同样的也可以通过xml方式来定义(如果你不嫌麻烦的话)。

另外@Bean注解的方法返回值是对象,可以在方法中为对象设置属性。

@CopmponentScan

定义扫描的路径从中找出标识了需要装配的类自动装配到spring的bean容器中。@ComponentScan注解默认就会装配标识了@Controller,@Service,@Repository,@Component注解的类到spring容器中,创建一个配置类,在配置类上添加 @ComponentScan 注解。该注解默认会扫描该类所在的包下所有的配置类

实例

配置类

package com.spring.aop.springaop.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * 主配置类  包扫描com.spring.aop.springaop
 *
 * @author lmx
 * @date 2022年2月20日
 */
@ComponentScan(value="com.spring.aop.springaop")
@Configuration
public class MainScanConfig {
}

测试程序

package com.spring.aop.springaop;

import com.spring.aop.springaop.config.MainScanConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

@SpringBootApplication
public class SpringaopdemoApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringaopdemoApplication.class, args);
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainScanConfig.class);
		String[] definitionNames = applicationContext.getBeanDefinitionNames();
		System.out.println("-------------------------------------------------------");
		for (String name : definitionNames) {
			System.out.println(name);
		}
	}

}

这里解释一下AnnotationConfigApplicationContext是一个用来管理注解bean的容器

容器创建过程

Spring源码解析 – AnnotationConfigApplicationContext容器创建过程 - 互联网荒漠 - 博客园

getBeanDefinitionNames方法

Spring getBeanDefinitionNames方法:获取JavaBean名称

结果

-------------------------------------------------------
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainScanConfig
configurationBean
myadvice
springaopdemoApplication
hellocontroller
org.springframework.boot.autoconfigure.AutoConfigurationPackages
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration
propertySourcesPlaceholderConfigurer
org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration
taskExecutorBuilder
applicationTaskExecutor
org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor

源码分析:

Spring注解——使用@ComponentScan自动扫描组件 - 简书

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.springframework.context.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.core.annotation.AliasFor;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
    @AliasFor("basePackages")
    String[] value() default {};

    @AliasFor("value")
    String[] basePackages() default {};

    Class<?>[] basePackageClasses() default {};

    Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;

    Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;

    ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;

    String resourcePattern() default "**/*.class";

    boolean useDefaultFilters() default true;

    ComponentScan.Filter[] includeFilters() default {};

    ComponentScan.Filter[] excludeFilters() default {};

    boolean lazyInit() default false;

    @Retention(RetentionPolicy.RUNTIME)
    @Target({})
    public @interface Filter {
        FilterType type() default FilterType.ANNOTATION;

        @AliasFor("classes")
        Class<?>[] value() default {};

        @AliasFor("value")
        Class<?>[] classes() default {};

        String[] pattern() default {};
    }
}

-valule 指定要扫描的包

-excludeFilters 按照规则排除某些包的扫描 

@ComponentScan(value = "io.mieux", excludeFilters = {@Filter(type = FilterType.ANNOTATION, classes = {Controller.class})})

-includeFilters 按照规则选择某些包的扫描

@ComponentScan(value = "io.mieux", includeFilters = {@Filter(type = FilterType.ANNOTATION, classes = {Controller.class})})

 -usedefaultFileter 是否使用默认的过滤器

@Configuration

@Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContextAnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器。

注意:@Configuration注解的配置类有如下要求:

  1. @Configuration不可以是final类型;
  2. @Configuration不可以是匿名类;
  3. 嵌套的configuration必须是静态类。

@Configuration标注在类上,相当于把该类作为spring的xml配置文件中的,作用为:配置spring容器(应用上下文)

@Configuration启动容器+@Bean注册Bean,@Bean下管理bean的生命周期

@Configuration启动容器+@Component注册Bean

实例

看这篇就够了

Spring @Configuration注解_leoxyk的专栏-CSDN博客_@configuration注解

源码分析

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.springframework.context.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
import org.springframework.stereotype.Component;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
    @AliasFor(
        annotation = Component.class
    )
    String value() default "";

    boolean proxyBeanMethods() default true;
}

待补充

@Autowired

@Autowired 注释,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。 

 其实在启动spring IoC时,容器自动装载了一个AutowiredAnnotationBeanPostProcessor后置处理器,当容器扫描到@Autowied、@Resource(是CommonAnnotationBeanPostProcessor后置处理器处理的)或@Inject时,就会在IoC容器自动查找需要的bean,并装配给该对象的属性。

 在使用@Autowired时,首先在容器中查询对应类型的bean

    如果查询结果刚好为一个,就将该bean装配给@Autowired指定的数据

    如果查询的结果不止一个,那么@Autowired会根据名称来查找。

    如果查询的结果为空,那么会抛出异常。解决方法时,使用required=false

实例


   @Autowired
   public void setSpellChecker( SpellChecker spellChecker ){
      this.spellChecker = spellChecker;
   }
@Autowired
private UserRepository userRepository;

 源码分析

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.springframework.beans.factory.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
    boolean required() default true;
}

-required 表示注入的时候,该bean必须存在,否则就会注入失败

Lombok常用的注解

Lombok常用注解 - 草木物语 - 博客园

 \

@Retention

注解@Retention用来修饰注解,是注解的注解,称为元注解。 

@Retention作用详析 - 简书

源码分析

package java.lang.annotation;

/**
 * Indicates how long annotations with the annotated interface are to
 * be retained.  If no Retention annotation is present on
 * an annotation interface declaration, the retention policy defaults to
 * {@code RetentionPolicy.CLASS}.
 *
 * <p>A Retention meta-annotation has effect only if the
 * meta-annotated interface is used directly for annotation.  It has no
 * effect if the meta-annotated interface is used as a member interface in
 * another annotation interface.
 *
 * @author  Joshua Bloch
 * @since 1.5
 * @jls 9.6.4.2 @Retention
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    /**
     * Returns the retention policy.
     * @return the retention policy
     */
    RetentionPolicy value();
}

Retention注解有一个属性value,是RetentionPolicy枚举类型,决定了Retention注解应该如何去保持。RetentionPolicy有3个值:CLASS RUNTIME SOURCE

  • RetentionPolicy.SOURCE:注解只保留在源文件中,编译时注解会被遗弃;
  • RetentionPolicy.CLASS:注解会保留到class文件,当class文件被Load时被遗弃,这是注解默认的生命周期;
  • RetentionPolicy.RUNTIME:注解不仅被保存到class文件中,Load之后,仍然存在;
    这3个生命周期分别对应于:源文件---> .class文件 ---> 内存中的字节码

@ControllerAdvice

ControllerAdvice本质上是一个Component,因此也会被当成组建扫描,一视同仁,扫扫扫

我们可以使用@ControllerAdvice来声明一些全局性的东西,最常见的是结合@ExceptionHandler注解用于全局异常的处理。

@ControllerAdvice,是Spring3.2提供的新注解,它是一个Controller增强器,可对controller中被 @RequestMapping注解的方法加一些逻辑处理。最常用的就是异常处理

@ControllerAdvice是在类上声明的注解,其用法主要有三点:

@ExceptionHandler注解标注的方法:用于捕获Controller中抛出的不同类型的异常,从而达到异常全局处理的目的;
@InitBinder注解标注的方法:用于请求中注册自定义参数的解析,从而达到自定义请求参数格式的目的;
@ModelAttribute注解标注的方法:表示此方法会在执行目标Controller方法之前执行 。
实例

 随便写一个异常的controller

package myblog.myblog.web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class IndexController {

    @GetMapping("/hello")
    public String index() {
        int a= 9/0;
        return "index";
    }

}

写异常的拦截

package myblog.myblog.handler;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;

@ControllerAdvice
public class ControllerExceptionHandler {

    private  Logger logger = LoggerFactory.getLogger(this.getClass());

    @ExceptionHandler(Exception.class)
    public ModelAndView exceptionHandler(HttpServletRequest request,Exception e) {
        logger.error("Request URL:{},Exception:{}",request.getRequestURI(),e);
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("url",request.getRequestURL());
        modelAndView.addObject("exception",e);
        modelAndView.setViewName("error/error");
        return modelAndView;


    }
}

这里html页面就自己瞎写写就行

结果

源码分析

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.springframework.web.bind.annotation;

import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
import org.springframework.stereotype.Component;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface ControllerAdvice {
    @AliasFor("basePackages")
    String[] value() default {};

    @AliasFor("value")
    String[] basePackages() default {};

    Class<?>[] basePackageClasses() default {};

    Class<?>[] assignableTypes() default {};

    Class<? extends Annotation>[] annotations() default {};
}

basepackages:指定扫描的包

basepackageclasses:传进去扫描的类

assignableTypes:传进去几个扫描的类

理解注解@ControllerAdvice | 闷瓜蛋子的BLOGhttps://fookwood.com/spring-boot-tutorial-11-ca

(后面不写源码分析了)

@ResponseStatus

可以通过@ResponseStatus注解和自定义异常来配合使用返回自定义响应状态码和自定义错误信息给客户端。@ResponseStatus注解有两种用法,一种是加载自定义异常类上,一种是加在目标方法中

实例

ResponseStatus的简单实用方法 - 灰信网(软件开发博客聚合)https://www.freesion.com/article/14861370952/

JPA相关注解

JPA顾名思义就是Java Persistence API的意思,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。

@Entity 

表明是一个实体类 ,@Entity定义对象将会成为被JPA管理的实体,将映射到指定的数据库表

实例

@Entity
@Table(name = "t_user")
public class User {}

@Table 

对应的数据表名

实例

@Entity
@Table(name = "t_user")
public class User {}

@Id 

定义主键

@Id 标注用于声明一个实体类的属性映射为数据库的主键列。该属性通常置于属性声明语句之前,可与声明语句同行,也可写在单独行上。 
@Id标注也可置于属性的getter方法之前。

实例

    @Id
    @GeneratedValue
    private  Long id;

@GeneratedValue

主键生成策略

@GeneratedValue 用于标注主键的生成策略,通过strategy 属性指定。默认情况下,JPA 自动选择一个最适合底层数据库的主键生成策略:SqlServer对应identity,MySQL 对应 auto increment。 
在javax.persistence.GenerationType中定义了以下几种可供选择的策略: 
–IDENTITY:采用数据库ID自增长的方式来自增主键字段,Oracle 不支持这种方式; 
–AUTO: JPA自动选择合适的策略,是默认选项; 
–SEQUENCE:通过序列产生主键,通过@SequenceGenerator 注解指定序列名,MySql不支持这种方式 
–TABLE:通过表产生主键,框架借由表模拟序列产生主键,使用该策略可以使应用更易于数据库移植。

@Table(name="CUSTOMERS")
@Entity
public class Customer {
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Id
    private Integer id;
    private String name;
    private String email;
    private int age;
 
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }

@Temporal

用来设置Date类型的属性映射到对应精度的字段

数据库的时间字段类型有date、time、datetime。
@Temporal()注解:一般用于实体类,帮助java的Date类型进行格式化
第一种:@Temporal(TemporalType.DATE)——>实体类会封装成“yyyy-MM-dd”的 Date类型。
第二种:@Temporal(TemporalType.TIME)——>实体类会封装成“hh-MM-ss”的Date类型。
第三种:@Temporal(TemporalType.TIMESTAMP)——>实体会封装成完整的时间“yyyy-MM-dd hh:MM:ss”的Date类型
实例

用在字段上

@Temporal(TemporalType.TIMESTAMP)
@Column(name = “regist_time”)
private Date registTime;

 用在get方法上

@Temporal(TemporalType.TIMESTAMP)
public Date getRegistTime(){undefined
return registTime;
}
注:在jsp里控制不显示毫秒:

@OneToMany,@ManyToOne,@ManyToMany

(1)@ManyToOne(多对一)单向:不产生中间表,但可以用@Joincolumn(name="  ")来指定生成外键的名字,外键在多的一方表中产生!

(2)@OneToMany(一对多)单向:会产生中间表,此时可以用@onetoMany @Joincolumn(name=" ")避免产生中间表,并且指定了外键的名字(别看          @joincolumn在一中写着,但它存在在多的那个表中)

(3)@OneToMany ,ManyToOne 双向(两个注解一起用的):如果不在@OneToMany中加mappedy属性就会产生中间表,此时通常在@ManyToOne的注            解下再添上注解@Joincolumn(name=" ")来指定外键的名字(说明:多的一方为关系维护端,关系维护端负责外键记录的更新,关系被维护端没有权利更新          外键记录)!(@OneToMany(mappedBy="一对多中,多中一的属性")出现mapby为被维护端|||默认为延迟加载)

  (4) @ManyToMany  注释:表示此类是多对多关系的一边,mappedBy 属性定义了此类为双向关系的维护端,注意:mappedBy 属性的值为此关系的另一端的属性名。

下面我觉得应该选择其中一个先进行源码分析,看看有哪些参数

/*
 * Copyright (c) 2008, 2019 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Linda DeMichiel - 2.1
//     Linda DeMichiel - 2.0

package javax.persistence;

import java.lang.annotation.Target;
import java.lang.annotation.Retention;
import javax.persistence.CascadeType;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static javax.persistence.FetchType.LAZY;

/**
 * Specifies a many-valued association with one-to-many multiplicity.
 * 
 * <p> If the collection is defined using generics to specify the 
 * element type, the associated target entity type need not be 
 * specified; otherwise the target entity class must be specified.
 * If the relationship is bidirectional, the
 * <code> mappedBy</code> element must be used to specify the relationship field or
 * property of the entity that is the owner of the relationship.
 *
 * <p> The <code>OneToMany</code> annotation may be used within an embeddable class
 * contained within an entity class to specify a relationship to a
 * collection of entities. If the relationship is bidirectional, the
 * <code> mappedBy</code> element must be used to specify the relationship field or
 * property of the entity that is the owner of the relationship.
 *
 * When the collection is a <code>java.util.Map</code>, the <code>cascade</code> 
 * element and the <code>orphanRemoval</code> element apply to the map value.
 *
 * <pre>
 *
 *    Example 1: One-to-Many association using generics
 *
 *    // In Customer class:
 *
 *    &#064;OneToMany(cascade=ALL, mappedBy="customer")
 *    public Set&#060;Order&#062; getOrders() { return orders; }
 *
 *    In Order class:
 *
 *    &#064;ManyToOne
 *    &#064;JoinColumn(name="CUST_ID", nullable=false)
 *    public Customer getCustomer() { return customer; }
 *
 *
 *    Example 2: One-to-Many association without using generics
 *
 *    // In Customer class:
 *
 *    &#064;OneToMany(targetEntity=com.acme.Order.class, cascade=ALL,
 *                mappedBy="customer")
 *    public Set getOrders() { return orders; }
 *
 *    // In Order class:
 *
 *    &#064;ManyToOne
 *    &#064;JoinColumn(name="CUST_ID", nullable=false)
 *    public Customer getCustomer() { return customer; }
 *
 *
 *    Example 3: Unidirectional One-to-Many association using a foreign key mapping
 *
 *    // In Customer class:
 *
 *    &#064;OneToMany(orphanRemoval=true)
 *    &#064;JoinColumn(name="CUST_ID") // join column is in table for Order
 *    public Set&#060;Order&#062; getOrders() {return orders;}
 *    
 * </pre>
 *
 * @since 1.0
 */
@Target({METHOD, FIELD}) 
@Retention(RUNTIME)

public @interface OneToMany {

    /**
     * (Optional) The entity class that is the target
     * of the association. Optional only if the collection
     * property is defined using Java generics.
     * Must be specified otherwise.
     *
     * <p> Defaults to the parameterized type of
     * the collection when defined using generics.
     */
    Class targetEntity() default void.class;

    /** 
     * (Optional) The operations that must be cascaded to 
     * the target of the association.
     * <p> Defaults to no operations being cascaded.
     *
     * <p> When the target collection is a {@link java.util.Map
     * java.util.Map}, the <code>cascade</code> element applies to the
     * map value.
     */
    CascadeType[] cascade() default {};

    /** (Optional) Whether the association should be lazily loaded or
     * must be eagerly fetched. The EAGER strategy is a requirement on
     * the persistence provider runtime that the associated entities
     * must be eagerly fetched.  The LAZY strategy is a hint to the
     * persistence provider runtime.
     */
    FetchType fetch() default LAZY;

    /** 
拥有关系的字段。除非关系是单向的,否则是必需的。
     */
    String mappedBy() default "";

    /**
     * (Optional) Whether to apply the remove operation to entities that have
     * been removed from the relationship and to cascade the remove operation to
     * those entities.
     * @since 2.0
     */
    boolean orphanRemoval() default false;
}

orphanRemoval:(可选)是否将删除操作应用于已从关系中删除的实体,并将删除操作级联到这些实体。

mappedBy:的意思就是“被映射”,即mappedBy这方不用管关联关系,关联关系交给另一方处理。指代拥有关系的字段。除非关系是单向的,否则是必需的(@manytomany)。被标注的一方是被维护的一方,是从表。注意拥有方改变,被拥有方不一定改变。但是当被拥有方改变,拥有方一定改变。这部分很绕!

fetch:懒加载/急切加载(可选)关联是应该延迟加载还是必须急切获取。 EAGER 策略是对持久性提供程序运行时的要求,即必须急切地获取关联的实体。 LAZY 策略是对持久性提供程序运行时的提示。

cascade:(可选)必须级联到关联目标的操作。默认为没有级联操作。当目标集合是 java.util.Map 时,级联元素适用于映射值。

CascadeType.PERSIST

级联新增,保存父对象时会新建其中包含的子对象

CascadeType.MERGE

级联修改,保存父对象时会更新其中所包含的子对象数据

CascadeType.REMOVE

级联删除,当删除关联关系时会将子对象的数据删除

CascadeType.REFRESH

级联刷新,保存关联关系时会更新子对象和数据库中一致(意思是你在父对象中添加一个只包含ID的子对象,也可以保存进去)

CascadeType.ALL

包含上述所有操作
 

实例

当然你也可以定义在字段上

    @OneToMany(mappedBy = "type")
    private List <Blog> blogs=new ArrayList<Blog>();

当然你也可以定义在get方法上上

在Person 里面定义的注解:

@OneToOne(cascade={CascadeType.ALL},optional=true) 
public IDCard getIdCard() { 
         return idCard; 
}

在IDCard 里面定义的注释: 
@OneToOne(cascade=CascadeType.ALL,mappedBy="idCard" , optional=false) 
public Person getPerson() { 
       return person; 
} 

多了一个mappedBy这个方法,它表示什么呢?它表示当前所在表和Person的关系是定义在Person里面的idCard这个成员上面的,它表示此表是一对一关系中的从表,也就是关系是在person表里面维护的 ,这一点很重要 . Person表是关系的维护者,owner side,有主导权,它有个外键指向IDCard。 
我们也可以让主导权在IDCard上面,也就是让它产生一个指向Person的外键,这也是可以的,但是最好是让Person来维护整个关系,这样更符合我们正常的思维 .

@JoinColumn

用来指定与所操作实体或者实体集合相关的数据库表中的列字段。指定外键的名称。外键列的名称。它所在的表取决于上下文。如果连接是针对使用外键映射策略的 OneToOne 或 ManyToOne 映射,则外键列在源实体的表中或可嵌入的。如果连接是针对使用外键映射策略的单向 OneToMany 映射,则外键位于目标实体的表中。如果连接是用于多对多映射或用于使用连接表的 OneToOne 或双向 ManyToOneOneToMany 映射,则外键位于连接表中。如果连接用于元素集合,则外键位于集合表中。默认值(仅在使用单个连接列时适用):以下内容的连接:引用关系属性或引用实体或可嵌入类的字段的名称; "_";引用的主键列的名称。如果实体中没有这样的引用关系属性或字段,或者如果连接是针对元素集合的,则连接列名称由以下内容的串联形成:实体名称; "_";引用的主键列的名称。

这边我也一知半解,待补充

@Column : 映

射表对应的字段名

@Basic : 表示该属性是表字段的映射。 如果实体的字段上没有任何注解默认就是@Basic

@Transient : 表示该属性不是表字段的映射

@Lob : 将属性映射成支持的大对象类型 ,如Clob、Blob

@IdClass 联合主键,一般不用也不推荐用

@Enumerated 直接映射枚举类型的字段

@ModelAttribute

1.用在方法的参数

注解在参数上,会将客户端传递过来的参数按名称注入到指定对象中,
并且会将这个对象自动加入ModelMap中

<form action="../register" method="post">
姓名:<input type="text" name="name" id="name"><br/>
生日:<input type="text" id="birthday" name="birthday"><br>
<input id="submit" type="submit" value="提交"/>
</form>

@RequestMapping(value="/register")
	public String register(@ModelAttribute User user,Model model) {
		System.out.println(user.getBirthday());
		model.addAttribute("user", user);
		return "success";
	}

2.用在Controller的方法上

注解在方法上,会在每一个@RequestMapping标注的方法前执行,
如果有返回值,则自动将该返回值加入到ModelMap中,这是本地向控制器方法传递参数的一种方式。

/*
	 * 在控制器类的处理方法执行前执行指定的方法
	 */
	@ModelAttribute
	public User getUser(Model model) {
		User user=new User("吕蒙","123",new Address("江苏","南京"));
		model.addAttribute("user", user);
		return user;
	}
	
	@RequestMapping("/modelAttribute")
	public String modelAttribute(User user) {
		System.out.println(user);
		return "success";
	}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值