Java web——Hibernate入门经典与注解式开发

旧城等待, 2024-03-30 16:38 106阅读 0赞

一、Hibernate框架

  • Hibernate是一种ORM框架,全称为 Object_Relative DateBase-Mapping,在Java对象与关系数据库之间建立某种映射,以实现直接存取Java对象
  • 使用Hibernate框架就不用我们写很多繁琐的SQL语句,从而简化我们的开发

1.为什么要使用Hibernate?

既然Hibernate是关于Java对象和关系数据库之间的联系的话,也就是我们MVC中的数据持久层->在编写程序中的DAO层(数据访问层)

首先,我们来回顾一下我们在DAO层写程序的历程吧:

在DAO层操作XML,将数据封装到XML文件上,读写XML文件数据实现CRUD 在DAO层使用原生JDBC连接数据库,实现CRUD 嫌弃JDBC的ConnectionStatementResultSet等对象太繁琐,使用对原生JDBC的封装组件—>DbUtils组件 我们来看看使用DbUtils之后,程序的代码是怎么样的:

public class CategoryDAOImpl implements zhongfucheng.dao.CategoryDao {

@Override
public void addCategory(Category category) {

QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());

String sql = “INSERT INTO category (id, name, description) VALUES(?,?,?)”;
try {
queryRunner.update(sql, new Object[]{category.getId(), category.getName(), category.getDescription()});

} catch (SQLException e) {
throw new RuntimeException(e);
}
}

@Override
public Category findCategory(String id) {
QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());
String sql = “SELECT * FROM category WHERE id=?”;

try {
Category category = (Category) queryRunner.query(sql, id, new BeanHandler(Category.class));

return category;

} catch (SQLException e) {
throw new RuntimeException(e);
}

}

@Override
public List getAllCategory() {
QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());
String sql = “SELECT * FROM category”;

try {
List categories = (List) queryRunner.query(sql, new BeanListHandler(Category.class));

return categories;
} catch (SQLException e) {
throw new RuntimeException(e);
}

}
}

其实使用DbUtils时,DAO层中的代码编写是很有规律的:

  • 当插入数据的时候:就将JavaBean对象拆分(拆分为id、name…),拼装成SQL语句
  • 当查询数据的时候,用SQL把数据库表中的列组合(id列、name列…),拼装成JavaBean对象
  • 也就是说:javaBean对象和数据表中的列存在映射关系!如果程序能够自动生成SQL语句就好了….那么Hibernate就实现了这个功能
  • 简单来说:我们使用Hibernate框架就不用我们写很多繁琐的SQL语句,从而简化我们的开发

Hibernate快速入门 学习一个框架无非就是三个步骤:

  • 引入jar开发包
  • 配置相关的XML文件
  • 熟悉API 引入相关jar包

Hibernate3.6的版本:hibernate3.jar核心 + required 必须引入的(6个) + jpa 目录 + 数据库驱动包

2.编写对象和对象映射

  • 编写一个User对象->User.java

    public class User {

    1. private int id;
    2. private String username;
    3. private String password;
    4. private String cellphone;
    5. //各种setter和getter

    }

  • 编写对象映射->User.hbm.xml(一般它和JavaBean对象放在同一目录下)

    • 我们是不知道该XML是怎么写的,可以搜索一下Hibernate文件夹中后缀为.hbm.xml。看看它们是怎么写的。然后复制一份过来

    <?xml version=”1.0”?>
    <!DOCTYPE hibernate-mapping PUBLIC

    1. "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    2. "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    1. <class name="A" lazy="true" table="aaa">
    2. <id name="id">
    3. <generator class="native"/>
    4. </id>
  1. <key column="a_id"/>
  2. <list-index column="idx"/>
  3. <one-to-many class="B"/>
  4. </class>
  5. <class name="B" lazy="true" table="bbb">
  6. <id name="id">
  7. <generator class="native"/>
  8. </id>
  9. </class>
  10. </hibernate-mapping>

在上面的模板上修改

  1. <!--在domain包下-->
  2. <hibernate-mapping package="zhongfucheng.domain">
  3. <!--类名为User,表名也为User-->
  4. <class name="User" table="user">
  5. <!--主键映射,属性名为id,列名也为id-->
  6. <id name="id" column="id">
  7. <!--根据底层数据库主键自动增长-->
  8. <generator class="native"/>
  9. </id>
  10. <!--非主键映射,属性和列名一一对应-->
  11. <property name="username" column="username"/>
  12. <property name="cellphone" column="cellphone"/>
  13. <property name="password" column="password"/>
  14. </class>
  15. </hibernate-mapping>
  • 如果使用Intellij Idea生成的Hibernate可以指定生成出主配置文件hibernate.cfg.xml,它是要放在src目录下的
  • 如果不是自动生成的,我们可以在Hibernate的hibernate-distribution-3.6.0.Final\project\etc这个目录下可以找到

测试上述 编写对象文件 和对象映射文件 配置成功

  1. package zhongfucheng.domain;
  2. import org.hibernate.SessionFactory;
  3. import org.hibernate.Transaction;
  4. import org.hibernate.cfg.Configuration;
  5. import org.hibernate.classic.Session;
  6. /**
  7. * Created by ozc on 2017/5/6.
  8. */
  9. public class App {
  10. public static void main(String[] args) {
  11. //创建对象
  12. User user = new User();
  13. user.setPassword("123");
  14. user.setCellphone("122222");
  15. user.setUsername("nihao");
  16. //获取加载配置管理类
  17. Configuration configuration = new Configuration();
  18. //不给参数就默认加载hibernate.cfg.xml文件,
  19. configuration.configure();
  20. //创建Session工厂对象
  21. SessionFactory factory = configuration.buildSessionFactory();
  22. //得到Session对象
  23. Session session = factory.openSession();
  24. //使用Hibernate操作数据库,都要开启事务,得到事务对象
  25. Transaction transaction = session.getTransaction();
  26. //开启事务
  27. transaction.begin();
  28. //把对象添加到数据库中
  29. session.save(user);
  30. //提交事务
  31. transaction.commit();
  32. //关闭Session
  33. session.close();
  34. }
  35. }
  • JavaBean的主键类型只能是int类型,因为在映射关系中配置是自动增长的,String类型是不能自动增长的
  • 如果是你设置了String类型,又使用了自动增长,那么就会报出下面的错误

    Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table ‘zhongfucheng.user’ does

执行完程序后,Hibernate就为我们创建对应的表,并把数据存进了数据库了

二、Hibernate相关类

  1. public static void main(String[] args) {
  2. //创建对象
  3. User user = new User();
  4. user.setPassword("123");
  5. user.setCellphone("122222");
  6. user.setUsername("nihao");
  7. //获取加载配置管理类
  8. Configuration configuration = new Configuration();
  9. //不给参数就默认加载hibernate.cfg.xml文件,
  10. configuration.configure();
  11. //创建Session工厂对象
  12. SessionFactory factory = configuration.buildSessionFactory();
  13. //得到Session对象
  14. Session session = factory.openSession();
  15. //使用Hibernate操作数据库,都要开启事务,得到事务对象
  16. Transaction transaction = session.getTransaction();
  17. //开启事务
  18. transaction.begin();
  19. //把对象添加到数据库中
  20. session.save(user);
  21. //提交事务
  22. transaction.commit();
  23. //关闭Session
  24. session.close();
  25. }
  • Configuration 配置管理类:主要管理配置文件的一个类;它拥有一个子类AnnotationConfiguration,也就是说:我们可以使用注解来代替XML配置文件来配置相对应的信息
  • configure方法:configure()方法用于加载配置文件
  • 加载主配置文件的方法

    • 如果指定参数,那么 加载 参数的路径 配置文件
    • 如果不指定参数,默认加载src/目录下的hibernate.cfg.xml
  • buildSessionFactory方法:buildSessionFactory()用于创建Session工厂
  • openSession方法:创建一个Session对象
  • getCurrentSession方法:创建Session对象或取出Session对象
  • Session(一次浏览器和服务器的交互的会话:服务器为了保护用户状态而创建的一个特殊对象):Session是Hibernate最重要的对象,Session维护了一个连接(Connection),只要使用Hibernate操作数据库,都需要用到Session对象
  • beginTransaction方法:开启事务,返回的是一个事务对象,Hibernate规定所有的数据库操作都必须在事务环境下进行,否则报错

通常我们在DAO层中都会有以下的方法,Session也为我们提供了对应的方法来实现!

  • session.save(obj):调用了这个方法就把对象保存在数据库之中
  • session.update(obj):更新一个对象,需要有主键
  • session.saveOrUpdate(obj):保存或者更新的方法

    • 没有设置主键,执行保存
    • 有设置主键,执行更新操作; 如果设置主键不存在报错

    public interface IEmployeeDao {

    1. void save(Employee emp);
    2. void update(Employee emp);
    3. Employee findById(Serializable id);
    4. List<Employee> getAll();
    5. List<Employee> getAll(String employeeName);
    6. List<Employee> getAll(int index, int count);
    7. void delete(Serializable id);

    }

1)主键查询:通过主键来查询数据库的记录,从而返回一个JavaBean对象

  • session.get(javaBean.class, int id):传入对应的class和id就可以查询

    user.setId(1);

    1. user.setPassword("qwer");
    2. user.setCellphone("1111");
    3. user.setUsername("zhongfucheng");
  1. User user1 = (User) session.get(User.class, 1);
  2. System.out.println(user1);

2)HQL查询:即hibernate提供的面向对象的查询语言

  • 查询的是对象以及对象的属性【它查询的是对象以及属性,因此是区分大小写的】
  • 查询的是表以及列【不区分大小写】
  • HQL是面向对象的查询语言,可以用来查询全部的数据

3)QBC查询:完全面向对象的查询

  • HQL查询是需要SQL的基础的,因为还是要写少部分的SQL代码
  • QBC查询就是完全的面向对象查询…但是呢,我们用得比较少

4)本地SQL查询:使用原生的SQL来进行复杂查询

  • 它有一个缺陷:它是不能跨平台的…因此我们在主配置文件中应已经配置数据库的“方言“了

三、Hibernate注解开发

  • PO类(持久化对象:和数据持久层打交道)注解配置:**对于PO类中所有属性,如果你不写注解,默认情况下也会在表中生成对应的列,列的名称就是属性的名称,列的类型也即属性的类型**
  • 首先在src目录下创建一个cn.itheima.domain包,并在该包下创建一个Book实体类,由于Book实体类中写有注解配置,所以就不用编写那个映射配置文件

    @Entity // 定义了一个实体
    @Table(name=”t_book”,catalog=”hibernateTest”)
    public class Book {

    @Id // 这表示一个主键
    // @GeneratedValue 相当于native主键生成策略
    @GeneratedValue(strategy=GenerationType.IDENTITY) // 相当于identity主键生成策略
    private Integer id; // 主键

    @Column(name=”c_name”, length=30, nullable=true)
    private String name;

    @Temporal(TemporalType.TIMESTAMP) // 是用来定义日期类型
    private Date publicationDate; // 出版日期

    @Type(type=”double”) // 允许你去指定Hibernate里面的一些类型
    private Double price; // 价格,如果没有添加注解,也会自动的生成在表中

    public Integer getId() {

    1. return id;

    }
    public void setId(Integer id) {

    1. this.id = id;

    }
    public String getName() {

    1. return name;

    }
    public void setName(String name) {

    1. this.name = name;

    }
    public Date getPublicationDate() {

    1. return publicationDate;

    }
    public void setPublicationDate(Date publicationDate) {

    1. this.publicationDate = publicationDate;

    }
    public Double getPrice() {

    1. return price;

    }
    public void setPrice(Double price) {

    1. this.price = price;

    }
    }

详解Book实体类中的注解

  1. @Entity:声明一个实体。
  2. @Table:来描述类与表之间的对应关系。
  3. @Entity // 定义了一个实体
  4. @Table(name="t_book",catalog="hibernateTest")
  5. public class Book {
  6. ......
  7. }
  8. @id:声明一个主键。
  9. @GeneratedValue:用它来声明一个主键生成策略。
  10. //默认情况是native主键生成策略。
  11. //可以选择的主键生成策略有:AUTO、IDENTITY、SEQUENCE
  12. @Id // 这表示一个主键
  13. // @GeneratedValue 相当于native主键生成策略
  14. // 相当于identity主键生成策略
  15. @GeneratedValue(strategy=GenerationType.IDENTITY)
  16. private Integer id; // 主键
  17. @Column:定义列。
  18. @Column(name="c_name", length=30, nullable=true)
  19. private String name;
  20. @Temporal(TemporalType.TIMESTAMP) // 是用来定义日期类型
  21. private Date publicationDate; // 出版日期
  22. //日期类型可以选择的有:
  23. * TemporalType.DATA:只有年月日。
  24. * TemporalType.TIME:只有小时分钟秒。
  25. * TemporalType.TIMESTAMP:有年月日小时分钟秒。
  26. @Type:可允许你去指定Hibernate里面的一些类型。
  27. @Type(type="double") // 允许你去指定Hibernate里面的一些类型
  28. private Double price; // 价格,如果没有添加注解,也会自动的生成在表中
  • 最后我们在src目录下创建一个cn.itheima.test包,在该包下编写一个HibernateAnnotationTest单元测试类,并在该类中编写一个用于测试PO类的注解开发的方法:

    public class HibernateAnnotationTest {

    1. // 测试PO的注解开发
    2. @Test
    3. public void test1() {
    4. Session session = HibernateUtils.openSession();
    5. session.beginTransaction();
    6. Book b = new Book();
    7. b.setName("情书");
    8. b.setPrice(56.78);
    9. b.setPublicationDate(new Date());
    10. session.save(b);
    11. session.getTransaction().commit();
    12. session.close();
    13. }

    }

  • 在cn.itheima.domain包下再编写一个Person实体类,同样使用注解配置(主键生成策略为UUID类型,设定类的属性不在表中映射)

    @Entity
    @Table(name=”t_person”, catalog=”hibernateTest”)
    public class Person {

    1. // 生成UUID的主键生成策略
    2. @Id
    3. @GenericGenerator(name="myuuid", strategy="uuid")
    4. // 声明一种主键生成策略(uuid)
    5. @GeneratedValue(generator="myuuid") // 引用uuid主键生成策略
    6. private String id;
    7. @Type(type="string") // 允许你去指定Hibernate里面的一些类型
    8. private String name;
    9. @Transient
    10. private String msg; // 现在这个属性不想生成在表中
    11. public String getId() {
    12. return id;
    13. }
    14. public void setId(String id) {
    15. this.id = id;
    16. }
    17. public String getName() {
    18. return name;
    19. }
    20. public void setName(String name) {
    21. this.name = name;
    22. }
    23. public String getMsg() {
    24. return msg;
    25. }
    26. public void setMsg(String msg) {
    27. this.msg = msg;
    28. }

    }

最后在HibernateAnnotationTest单元测试类中编写如下一个方法:

  1. public class HibernateAnnotationTest {
  2. // 测试uuid的主键生成策略及不生成表中映射
  3. @Test
  4. public void test2() {
  5. Session session = HibernateUtils.openSession();
  6. session.beginTransaction();
  7. Person p = new Person();
  8. p.setName("李四");
  9. p.setMsg("这是一个好人");
  10. session.save(p);
  11. session.getTransaction().commit();
  12. session.close();
  13. }
  14. }
  • Hibernate关联映射——一对多(多对一),以客户(Customer)和订单(Order)为例;在src目录下创建一个cn.itheima.oneToMany包,并在该包编写这两个实体类:

    • 这里用到了@OneToMany@ManyToOne这两个注解

    // 客户 —— 一的一方

    1. @Entity
    2. @Table(name="t_customer")
    3. public class Customer {
    4. @Id
    5. @GeneratedValue(strategy=GenerationType.IDENTITY)
    6. private Integer id; // 主键
    7. private String name; // 姓名
    8. // 描述客户可以有多个订单
    9. /*
    10. * targetEntity="...":相当于<one-to-many >
    11. */
    12. @OneToMany(targetEntity=Order.class,mappedBy="c")
    13. private Set<Order> orders = new HashSet<Order>();
    14. public Set<Order> getOrders() {
    15. return orders;
    16. }
    17. public void setOrders(Set<Order> orders) {
    18. this.orders = orders;
    19. }
    20. public Integer getId() {
    21. return id;
    22. }
    23. public void setId(Integer id) {
    24. this.id = id;
    25. }
    26. public String getName() {
    27. return name;
    28. }
    29. public void setName(String name) {
    30. this.name = name;
    31. }
    32. }
  1. 订单(Order)类
  2. // 订单 ---- 多的一方
  3. @Entity
  4. @Table(name="t_order")
  5. public class Order {
  6. @Id
  7. @GeneratedValue(strategy=GenerationType.IDENTITY)
  8. private Integer id;
  9. private Double money;
  10. private String receiverInfo; // 收货地址
  11. // 订单与客户关联
  12. @ManyToOne(targetEntity=Customer.class)
  13. @JoinColumn(name="c_customer_id") // 指定外键列
  14. private Customer c; // 描述订单属于某一个客户
  15. public Customer getC() {
  16. return c;
  17. }
  18. public void setC(Customer c) {
  19. this.c = c;
  20. }
  21. public Integer getId() {
  22. return id;
  23. }
  24. public void setId(Integer id) {
  25. this.id = id;
  26. }
  27. public Double getMoney() {
  28. return money;
  29. }
  30. public void setMoney(Double money) {
  31. this.money = money;
  32. }
  33. public String getReceiverInfo() {
  34. return receiverInfo;
  35. }
  36. public void setReceiverInfo(String receiverInfo) {
  37. this.receiverInfo = receiverInfo;
  38. }
  39. }

写测试程序测试一下:

现在我的需求是保存客户时,顺便保存订单,对于这种情况我们需要在Customer类中配置cascade操作,即配置cascade=”save-update”,配置的方式有两种:

  • 第一种方式,可以使用JPA提供的注解。 那么@OneToMany注解就应修改为:

    @OneToMany(targetEntity=Order.class,mappedBy=”c”,cascade=CascadeType.ALL)
    private Set orders = new HashSet();

  • 第二种方式,可以使用Hibernate提供的注解。 那么@OneToMany注解就应修改为:

    @OneToMany(targetEntity=Order.class,mappedBy=”c”)
    @Cascade(CascadeType.SAVE_UPDATE)
    private Set orders = new HashSet();

在HibernateAnnotationTest单元测试类中编写如下方法进行测试:

  1. public class HibernateAnnotationTest {
  2. // 测试one-to-many注解操作(保存客户时级联保存订单)
  3. @Test
  4. public void test3() {
  5. Session session = HibernateUtils.openSession();
  6. session.beginTransaction();
  7. // 1.创建一个客户
  8. Customer c = new Customer();
  9. c.setName("叶子");
  10. // 2.创建两个订单
  11. Order o1 = new Order();
  12. o1.setMoney(1000d);
  13. o1.setReceiverInfo("武汉");
  14. Order o2 = new Order();
  15. o2.setMoney(2000d);
  16. o2.setReceiverInfo("天门");
  17. // 3.建立关系
  18. c.getOrders().add(o1);
  19. c.getOrders().add(o2);
  20. // 4.保存客户,并级联保存订单
  21. session.save(c);
  22. session.getTransaction().commit();
  23. session.close();
  24. }
  25. }

上面这种编写存在一个问题:订单表中没有关联客户的id

  • 因为我们在Customer类中配置了mappedBy=”c”,它代表的是外键的维护由Order方来维护,而Customer不维护,这时你在保存客户时,级联保存订单,是可以的,但是不能维护外键,所以,我们必须在代码中添加订单与客户之间的关系。所以须将test3方法修改为:

    public class HibernateAnnotationTest {

    1. // 测试one-to-many注解操作(保存客户时级联保存订单)
    2. @Test
    3. public void test3() {
    4. Session session = HibernateUtils.openSession();
    5. session.beginTransaction();
    6. // 1.创建一个客户
    7. Customer c = new Customer();
    8. c.setName("叶子");
    9. // 2.创建两个订单
    10. Order o1 = new Order();
    11. o1.setMoney(1000d);
    12. o1.setReceiverInfo("武汉");
    13. Order o2 = new Order();
    14. o2.setMoney(2000d);
    15. o2.setReceiverInfo("天门");
    16. // 3.建立关系
    17. // 原因:是为了维护外键,不然的话,外键就不能正确的生成!!!
    18. o1.setC(c);
    19. o2.setC(c);
    20. // 原因:是为了进行级联操作
    21. c.getOrders().add(o1);
    22. c.getOrders().add(o2);
    23. // 4.保存客户,并级联保存订单
    24. session.save(c);
    25. session.getTransaction().commit();
    26. session.close();
    27. }

    }

  • Hibernate关联映射——多对多,以学生与老师为例;使用@ManyToMany注解来配置多对多,只需要在一端配置中间表,另一端使用mappedBy表示放置外键的维护权。 在src目录下创建一个cn.itheima.manyToMany包,并在该包编写这两个实体类:

学生类

  1. @Entity
  2. @Table(name="t_student")
  3. public class Student {
  4. @Id
  5. @GeneratedValue(strategy=GenerationType.IDENTITY)
  6. private Integer id;
  7. private String name;
  8. @ManyToMany(targetEntity=Teacher.class)
  9. // @JoinTable:使用@JoinTable来描述中间表,并描述中间表中外键与Student、Teacher的映射关系
  10. // joinColumns:它是用来描述Student与中间表的映射关系
  11. // inverseJoinColumns:它是用来描述Teacher与中间表的映射关系
  12. @JoinTable(name="s_t", joinColumns={@JoinColumn(name="c_student_id",referencedColumnName="id")}, inverseJoinColumns={@JoinColumn(name="c_teacher_id")})
  13. private Set<Teacher> teachers = new HashSet<Teacher>();
  14. public Integer getId() {
  15. return id;
  16. }
  17. public void setId(Integer id) {
  18. this.id = id;
  19. }
  20. public String getName() {
  21. return name;
  22. }
  23. public void setName(String name) {
  24. this.name = name;
  25. }
  26. public Set<Teacher> getTeachers() {
  27. return teachers;
  28. }
  29. public void setTeachers(Set<Teacher> teachers) {
  30. this.teachers = teachers;
  31. }
  32. }

老师类

  1. @Entity
  2. @Table(name="t_teacher")
  3. public class Teacher {
  4. @Id
  5. @GeneratedValue(strategy=GenerationType.IDENTITY)
  6. private Integer id;
  7. private String name;
  8. @ManyToMany(targetEntity=Student.class, mappedBy="teachers") // 代表由对方来维护外键
  9. private Set<Student> students = new HashSet<Student>();
  10. public Integer getId() {
  11. return id;
  12. }
  13. public void setId(Integer id) {
  14. this.id = id;
  15. }
  16. public String getName() {
  17. return name;
  18. }
  19. public void setName(String name) {
  20. this.name = name;
  21. }
  22. public Set<Student> getStudents() {
  23. return students;
  24. }
  25. public void setStudents(Set<Student> students) {
  26. this.students = students;
  27. }
  28. }

编写测试程序测试一下。从上面可看出我们将外键的维护权利交由Student类来维护,现在我们演示保存学生时,将老师也级联保存,对于这种情况我们需要在Student类中配置cascade操作,即配置cascade=”save-update”,如下:

  1. @JoinTable(name="s_t", joinColumns={@JoinColumn(name="c_student_id",referencedColumnName="id")},
  2. inverseJoinColumns={@JoinColumn(name="c_teacher_id")})
  3. @Cascade(CascadeType.SAVE_UPDATE)
  4. private Set<Teacher> teachers = new HashSet<Teacher>();

接下来在HibernateAnnotationTest单元测试类中编写如下方法进行测试:

  1. public class HibernateAnnotationTest {
  2. // 测试多对多级联保存(保存学生时同时保存老师)
  3. @Test
  4. public void test4() {
  5. Session session = HibernateUtils.openSession();
  6. session.beginTransaction();
  7. // 1.创建两个老师
  8. Teacher t1 = new Teacher();
  9. t1.setName("Tom");
  10. Teacher t2 = new Teacher();
  11. t2.setName("Fox");
  12. // 2.创建两个学生
  13. Student s1 = new Student();
  14. s1.setName("张丹");
  15. Student s2 = new Student();
  16. s2.setName("叶紫");
  17. // 3.学生关联老师
  18. s1.getTeachers().add(t1);
  19. s1.getTeachers().add(t2);
  20. s2.getTeachers().add(t1);
  21. s2.getTeachers().add(t2);
  22. // 保存学生同时保存老师
  23. session.save(s1);
  24. session.save(s2);
  25. session.getTransaction().commit();
  26. session.close();
  27. }
  28. }

发表评论

表情:
评论列表 (有 0 条评论,106人围观)

还没有评论,来说两句吧...

相关阅读

    相关 注解开发

    注解:在java中就是在类和方法加一个“@注解名”,让类和方法有其他定义;那么在struts2中,也给我们提供了各种注解,用来替换struts.xml的复杂配置,通常可以用来替

    相关 Struts2注解开发常识

    随着项目的不断扩大,配置文件也会越来越臃肿,不利于后期开发与维护,此时注解式编程应景而生。 注解可以放在某个语法单元的头部,语法单元可以是类、接口、属性、方法以及局部变量等。