SpringBoot-SpringData-oneToOne

来源:互联网 发布:怎么样开淘宝店视频 编辑:程序博客网 时间:2024/05/18 03:03

前面说了SpringBoot-SpringData-JPA集成
以这个项目为基础,继续SpringData的一些功能

下面说一下一对一关系 @oneToOne


一些概念:

单向关联:一个实体可以获得另一个实体对象双向关联:两个实体可以相关或得对方对象一对一关联:一个实体只能获得一个对方实体的引用

@OneToOne的注解

@Target({METHOD, FIELD}) @Retention(RUNTIME)public@interfaceOneToOne {     Class targetEntity() default void.class;     CascadeType[]cascade()default();     FetchType fetch() default EAGER;     boolean optional() default true;     String mappedBy() default "";}

1,targetEntity 属性表示默认关联的实体类型,默认为当前标注的实体类。
2,cascade属性表示与此实体一对一关联的实体的级联样式类型。
3,fetch属性是该实体的加载方式,默认为即时加载EAGER
4,optional属性表示关联的该实体是否能够存在null值,默认为ture,如果设置为false,则该实体不能为null,
并且要配合使用@JoinColumn标记,将实体关系关系设置为唯一的,不为null而且不能更新

@OneToOne(optional=false)@JoinColumn(name="address_id", unique=true, nullable=false, updatable=false)private AddressEo address;

@JoinColumn注解

@Target({METHOD, FIELD}) @Retention(RUNTIME)public@interfaceJoinColumn {    String name() default "";    String referencedColumnName() default "";    boolean unique() default false;    boolean nullable() default true;    boolean insertable() default true;    booleanupdatabledefaulttrue;    String columnDefinition() default "";    String table() default "";}

1,@JoinColumn注释是保存表与表之间关系的字段
2,如果不设置name,默认name = 关联表的名称+”-“+关联表主键的字段名,在上面实例3,中,默认为“address_id”
默认情况下,关联实体的主键一般是用来做外键的,但如果此时不想用主键作为外键,则需要设置referencedColumnName属性,如:

create table address (    id int(20) not null auto_increament,    ref_id int(20) notn ull,    province varchar(50),    city varchar(50),    postcode varchar(50),    detail varchar(50),    primary key(id))@OneToOne@JoinColumn(name="address_id", referencedColumnName="ref_id")private AddressEO address;

@PrimarKeyJoinColumn

@Target({TYPE, METHOD, FIELD}) @Retention(RUNTIME) public @interface PrimaryKeyJoinColumn {     String name() default "";     String referencedColumnName() default "";     String columnDefinition() default ""; }

模型

以人和身份证一对一关系进为模型
用户和身份证为例模拟SpringData在实际开发中为我们带来的便利


项目目录

项目目录

项目包含用户User表,身份证Card表,及各自的数据库操作层,和一个测试类


domain

表关联方式

a、若使用外键关联,则考虑默认关联,只需要加@OneToOne标记即可。
b、若使用主键关联,则需要配合@PrimaryKeyColumn注释
c、若使用字段关联,则需要配合@JoinColumn注释使用

@Entitypublic class User {    //没有默认构造会报错    public User(){    }    public User(String name, Integer age, Card card) {        this.name = name;        this.age = age;        this.card = card;    }    @Id    @GeneratedValue    private Long id;    @Column(nullable = false)    private String name;    @Column(nullable = false)    private Integer age;    /**     * @OneToOne:一对一关联     * cascade:级联配置     * CascadeType.PERSIST: 级联新建     * CascadeType.REMOVE : 级联删除     * CascadeType.REFRESH: 级联刷新     * CascadeType.MERGE  : 级联更新     * CascadeType.ALL    : 以上全部四项     * @JoinColumn:主表外键字段     * cid:Care所映射的表中的一个字段(会在User表创建一个cid字段,与Care外键关系)     */    @OneToOne(cascade = CascadeType.REFRESH)//使用CascadeType.ALL无法保存成功    @JoinColumn(name = "cid", unique=true)    private Card card;    public Card getCard() {        return card;    }    public void setCard(Card card) {        this.card = card;    }    public Long getId() {        return id;    }    public void setId(Long id) {        this.id = id;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public Integer getAge() {        return age;    }    public void setAge(Integer age) {        this.age = age;    }}

如果不做双向oneToOne,Card表不需要添加user参数及注解

@Entitypublic class Card {    public Card() {    }    public Card(Integer cardId, String cardNumber) {        this.cardNumber = cardNumber;        this.cardId = cardId;    }    @Id    @GeneratedValue(strategy = GenerationType.AUTO)    private Integer cardId;    @Column(nullable = false)    private String cardNumber;    /**     * @OneToOne:一对一关联     * mappedBy = "card":一对一配置参考了card     * mappedBy = "card"中的User类中的getCard()中的Care(去除get)     * 如果User类getCard()改为getIdCard(),这里就要写成:mappedBy = "idCard"     */    @OneToOne(mappedBy = "card", fetch=FetchType.EAGER)    private User user;    public Integer getCardId() {        return cardId;    }    public void setCardId(Integer cardId) {        this.cardId = cardId;    }    public String getCardNumber() {        return cardNumber;    }    public void setCardNumber(String cardNumber) {        this.cardNumber = cardNumber;    }    public User getUser() {        return user;    }    public void setUser(User user) {        this.user = user;    }}

DAO

public interface UserRepository extends JpaRepository<User, Long> {    User findByName(String name);    User findByNameAndAge(String name, Integer age);    @Query("from User u where u.name=:name")    User findUser(@Param("name") String name);}public interface CareRepository extends JpaRepository<Card, Long> {    Card findByCardNumber(String name);}

application.properties

spring.datasource.url=jdbc:mysql://localhost:3306/testspring.datasource.username=rootspring.datasource.password=123spring.datasource.driver-class-name=com.mysql.jdbc.Driverspring.jpa.properties.hibernate.hbm2ddl.auto=update#开启SQL显示spring.jpa.show-sql=true

Test

@RunWith(SpringJUnit4ClassRunner.class)@SpringApplicationConfiguration(DemoApplication.class)public class oneToOneTest {    @Autowired    private UserRepository userRepository;    @Autowired    private CareRepository careRepository;    @Test    public void test() throws Exception {        // 创建测试数据        careRepository.save(new Card(1, "aaabbbccc"));        //保存        Card care1 = new Card();        care1.setCardId(1);        userRepository.save(new User("Test1", 20, care1));        //正向取数        User user = userRepository.findByName("Test1");        Card card = user.getCard();        Assert.assertEquals("aaabbbccc", card.getCardNumber());        //反向取数        Card care = careRepository.findByCardNumber("aaabbbccc");        User user_Temp = care.getUser();        Assert.assertEquals("Test1", user_Temp.getName());    }}

运行结果

运行结果


SpringData输出的SQL:

Hibernate:     insert into card (card_number) values (?)Hibernate:     insert into user (age, cid, name) values (?, ?, ?)Hibernate:     select user0_.id as id1_1_, user0_.age as age2_1_, user0_.cid as cid4_1_, user0_.name as name3_1_         from user user0_         where user0_.name=?Hibernate:     select card0_.card_id as card_id1_0_0_, card0_.card_number as card_num2_0_0_, user1_.id as id1_1_1_, user1_.age as age2_1_1_, user1_.cid as cid4_1_1_, user1_.name as name3_1_1_         from card card0_ left outer join user user1_         on card0_.card_id=user1_.cid         where card0_.card_id=?Hibernate:     select user0_.id as id1_1_1_, user0_.age as age2_1_1_, user0_.cid as cid4_1_1_, user0_.name as name3_1_1_, card1_.card_id as card_id1_0_0_, card1_.card_number as card_num2_0_0_         from user user0_ left outer join card card1_         on user0_.cid=card1_.card_id         where user0_.cid=?Hibernate:     select card0_.card_id as card_id1_0_, card0_.card_number as card_num2_0_         from card card0_         where card0_.card_number=?Hibernate:     select user0_.id as id1_1_1_, user0_.age as age2_1_1_, user0_.cid as cid4_1_1_, user0_.name as name3_1_1_, card1_.card_id as card_id1_0_0_, card1_.card_number as card_num2_0_0_         from user user0_ left outer join card card1_         on user0_.cid=card1_.card_id         where user0_.cid=?

自动创建的数据库

-- ------------------------------  Table structure for `card`-- ----------------------------DROP TABLE IF EXISTS `card`;CREATE TABLE `card` (  `card_id` int(11) NOT NULL AUTO_INCREMENT,  `card_number` varchar(255) NOT NULL,  PRIMARY KEY (`card_id`)) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;-- ------------------------------  Records of `card`-- ----------------------------BEGIN;INSERT INTO `card` VALUES ('1', 'aaabbbccc');COMMIT;-- ------------------------------  Table structure for `user`-- ----------------------------DROP TABLE IF EXISTS `user`;CREATE TABLE `user` (  `id` bigint(20) NOT NULL AUTO_INCREMENT,  `age` int(11) NOT NULL,  `name` varchar(255) NOT NULL,  `cid` int(11) DEFAULT NULL,  PRIMARY KEY (`id`),  UNIQUE KEY `UK_luurgctv320vav1gdny78j1a5` (`cid`),  CONSTRAINT `FK_luurgctv320vav1gdny78j1a5` FOREIGN KEY (`cid`) REFERENCES `card` (`card_id`)) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;-- ------------------------------  Records of `user`-- ----------------------------BEGIN;INSERT INTO `user` VALUES ('1', '20', 'Test1', '1');COMMIT;

结论

可以看到user表中有一个cid字段与Card中的card_id形成了外键关系从Test测试结果看出,双向映射成功,即取User可以拿到Card实例,反之亦然

代码下载:

  CSDN下载
  GitHub下载

0 0