目录
@OneToMany,@ManyToOne,@ManyToMany
@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
注解的方法,这些方法将会被AnnotationConfigApplicationContext
或AnnotationConfigWebApplicationContext
类进行扫描,并用于构建bean
定义,初始化Spring
容器。
注意:@Configuration
注解的配置类有如下要求:
- @Configuration不可以是
final
类型; - @Configuration不可以是匿名类;
- 嵌套的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常用的注解
\
@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:
*
* @OneToMany(cascade=ALL, mappedBy="customer")
* public Set<Order> getOrders() { return orders; }
*
* In Order class:
*
* @ManyToOne
* @JoinColumn(name="CUST_ID", nullable=false)
* public Customer getCustomer() { return customer; }
*
*
* Example 2: One-to-Many association without using generics
*
* // In Customer class:
*
* @OneToMany(targetEntity=com.acme.Order.class, cascade=ALL,
* mappedBy="customer")
* public Set getOrders() { return orders; }
*
* // In Order class:
*
* @ManyToOne
* @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:
*
* @OneToMany(orphanRemoval=true)
* @JoinColumn(name="CUST_ID") // join column is in table for Order
* public Set<Order> 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";
}