Hibernate关联映射1:一对一主键关联

2张表之间通过主键形成一对一映射关系,如一个人只能有一张身份证:

t_identity_card表建表语句:

CREATE TABLE `t_identity_card` (
  `id` int(11) NOT NULL,
  `identity` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=gb2312;

t_person表建表语句:

CREATE TABLE `t_person` (
  `id` int(11) NOT NULL,
  `name` varchar(255) NOT NULL,
  `age` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  CONSTRAINT `FK_ID` FOREIGN KEY (`id`) REFERENCES `t_identity_card` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=gb2312;

hibernate.cfg.xml:




	
		org.hibernate.dialect.MySQLDialect
		com.mysql.jdbc.Driver
		jdbc:mysql://localhost:3306/mydb
		root
		196428
		
		true
		
		
		
	

单向一对一主键关联:

t_identity_card表:

public class IdentityCard implements Serializable {
	private static final long serialVersionUID = 1L;
	private int id;
	private int identity;
	private Person person;
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public int getIdentity() {
		return identity;
	}
	public void setIdentity(int identity) {
		this.identity = identity;
	}
	public Person getPerson() {
		return person;
	}
	public void setPerson(Person person) {
		this.person = person;
	}
}

由于t_identity_card表使用foreign主键生成策略,故在t_identity_card表的配置文件中必须配置主键生成表t_person,这样在向t_identity_card表中插入数据时才能找到所需的主键值,所以单向一对一主键关联中只有t_person<-t_identity_card,没有t_person->t_identity_card




    
    	
			
				person
			
		
        
        
    

t_person表:

public class Person implements Serializable {
	private static final long serialVersionUID = 1L;
	private int id;
	private String name;
	private int age;
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
}



    
		
			
		
		
        
    

测试一下:

public class Test {
	public static void main(String[] args) {
		Configuration conf = new Configuration();
		SessionFactory sessionFactory = conf.configure().buildSessionFactory();
		Session session = sessionFactory.openSession();
		
		IdentityCard identityCard = new IdentityCard();
		identityCard.setIdentity(123456);
		Person person = new Person();
		person.setId(1);
		person.setName("sean");
		person.setAge(25);
		identityCard.setPerson(person);
		
		Transaction tran = session.beginTransaction();
		session.save(identityCard);
		tran.commit();
		
		IdentityCard identityCard2 = (IdentityCard)session.get(IdentityCard.class, 1);
		Person person2 = identityCard2.getPerson();
		System.out.println(person2.getName());
		
		session.close();
	}
}

测试结果为:

Hibernate: insert into t_identity_card (identity, id) values (?, ?)
sean

只向t_identity_card表中插入了数据,t_person表为空,由于没有设置关联关系的cascade属性,在持久化一张表的时候,并不会级联的持久化另一张表

将t_identity_card表的映射文件中的关联关系修改为:cascade="all" />

Hibernate: select person_.id, person_.name as name1_, person_.age as age1_ 
from t_person person_ where person_.id=?
Hibernate: insert into t_identity_card (identity, id) values (?, ?)
Hibernate: insert into t_person (name, age, id) values (?, ?, ?)
sean

双向一对一主键关联:

这时需要对t_person表的配置做一些修改:

public class Person implements Serializable {
	private static final long serialVersionUID = 1L;
	private int id;
	private String name;
	private int age;
	private IdentityCard identityCard;//新增
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public IdentityCard getIdentityCard() {
		return identityCard;
	}
	public void setIdentityCard(IdentityCard identityCard) {
		this.identityCard = identityCard;
	}
}



    
		
			
		
		
        
    	
    	
    

测试一下:

public class Test {
	public static void main(String[] args) {
		Configuration conf = new Configuration();
		SessionFactory sessionFactory = conf.configure().buildSessionFactory();
		Session session = sessionFactory.openSession();
		
		IdentityCard identityCard = new IdentityCard();
		identityCard.setIdentity(123456);
		Person person = new Person();
		person.setId(1);
		person.setName("sean");
		person.setAge(25);
		
		identityCard.setPerson(person);
		person.setIdentityCard(identityCard);
		
		Transaction tran = session.beginTransaction();
		session.save(identityCard);
		tran.commit();
		
		Person person_tmp = (Person)session.get(Person.class, 1);
		IdentityCard id_card_tmp = person_tmp.getIdentityCard();
		System.out.println(id_card_tmp.getIdentity());
		
		id_card_tmp = (IdentityCard)session.get(IdentityCard.class, 1);
		person_tmp = id_card_tmp.getPerson();
		System.out.println(person_tmp.getName());
		
		session.close();
	}
}

测试结果为:

Hibernate: select person_.id, person_.name as name1_, person_.age 
as age1_ from t_person person_ where person_.id=?
Hibernate: insert into t_identity_card (identity, id) values (?, ?)
Hibernate: insert into t_person (name, age, id) values (?, ?, ?)
123456
sean

Hibernate首先持久化了identityCard对象,将测试代码中的session.save(identityCard)修改为session.save(person),再次测试:

Hibernate: insert into t_person (name, age, id) values (?, ?, ?)
Exception in thread "main" org.hibernate.exception.ConstraintViolationException: 
Could not execute JDBC batch update
......
Caused by: java.sql.BatchUpdateException: Cannot add or update a child row:
a foreign key constraint fails (`mydb`.`t_person`, CONSTRAINT `FK_ID` 
FOREIGN KEY (`id`) REFERENCES `t_identity_card` (`id`))
......

Hibernate这次首先持久化了person对象,由于t_person表中的id字段建立了外键关系,故持久化失败,删除掉t_person表中id字段的外键关系之后,插入正常:

Hibernate: insert into t_person (name, age, id) values (?, ?, ?)
Hibernate: insert into t_identity_card (identity, id) values (?, ?)
123456
sean

可见Hibernate有时不是很智能,save的对象将会首先被持久化,这时要特别注意表上建立的关联关系

转载于:https://www.cnblogs.com/sean-zou/p/3710011.html

你可能感兴趣的:(Hibernate关联映射1:一对一主键关联)