SSH-hibernate04: One-to-one, one-to-many, many-to-many for beginners

Posted by omprakash on Mon, 20 May 2019 04:52:48 +0200

In this chapter, we will study the relationship of hibernate, that is, one-to-one, one-to-many and many-to-many. This chapter will also be the last chapter of hibernate for beginners.

First of all, one-to-one: a person corresponding to an ID card as a list.

Step 1: The new table persion (person) and card (identity card) are structured as follows. The varchar given by both PIDs is designed to use uuid in the primary key generation strategy.

Step 2: Create two new entity classes under the project / com.entity, correspond to the database, then encapsulate the construct, and remove the pid from the construct. After that, the new hbm.xml files of these two classes are created. In persion.hbm.xml, the primary key generation strategy in < ID /> node is changed to uuid.

    <id name="pid" type="java.lang.String">
            <column name="PID" />
//Change uuid <generator class="uuid" /> </id>

Change the primary key generation strategy in <id/> node in card.hbm.xml to foreign, which is equal to the meaning of foreign key.

<id name="pid" type="java.lang.String">
            <column name="PID" />
            <!-- Primary key generation strategy changed to foreign key -->
            <generator class="foreign">            
            </generator>
        </id>

Step 3: Start building a one-to-one relationship: first define an object of card in the person entity class, remember not to instantiate it, and then encapsulate it.

private Card card;
public Card getCard() { return card; } public void setCard(Card card) { this.card = card; }

Next, define a person object in the card entity class, and don't instantiate it, then encapsulate it.

    private Person person;

    public Person getPerson() {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }

Step 4: It's time to start building a pair of relationships. Add <one-to-one/> node in persion.hbm.xml<class/> node, where the name attribute is the variable name of the card object defined in the persion entity class. _

    <one-to-one name="card" class="com.entity.Card" cascade="all"></one-to-one>

Add <one-to-one/> node to card.hbm.xml<class/> node, where the name attribute value is the variable name of the person object defined in the card entity class.    

<one-to-one name="person" class="com.entity.Person"></one-to-one>

In addition, a parameter < param/> is added to the card.hbm.xml primary key generation strategy, in which the name attribute value is fixed and the person is the variable name of the person object defined in the card entity class.  

<id name="pid" type="java.lang.String">
            <column name="PID" />
            <!-- Primary key generation strategy changed to foreign key -->
            <generator class="foreign">
                <param name="property">person</param>
            </generator>
        </id>

This is the end of the configuration. So somebody must have doubts?

What does cascade="all" in <one-to-one/> in persion.hbm.xml mean?

The cascade attribute is equivalent to the associated attribute of the two tables, with the following attribute values

none: No Association operations are performed in all cases. This is the default value.  

All: Associative operations are performed in all cases

save-update: Associate operations when executing save/update/save OrUpdate.

Delete: The association operation is performed when delete is executed.

all-delete-orphan: When an orphan node is generated in an object graph, it is deleted from the database

Take delete for example, when deleting the person's object data, the corresponding card object data will also be deleted.

Step 5: Add entity class to hibernate.cfg.xml configuration file. Mapping relationship of hbm.xml < mapping/>.

<mapping resource="com/entity/Card.hbm.xml" />
        <mapping resource="com/entity/Person.hbm.xml" />

Step 6: Testing is about to begin: Create a test class with a junit @Test test test test method.

Now that @Tset is used, then use @Before (triggered before method execution) and @Aafter (triggered after method execution), so that we can write duplicate code in these two methods to reduce the amount of code.

private Configuration configuration;

private SessionFactory factory;

  private Session session;


  private Transaction transaction;



@Before
public void Before() { configuration = new Configuration().configure(); factory = configuration.buildSessionFactory(); session = factory.openSession(); transaction = session.beginTransaction(); }

 

@After
    public void after() {
        // Close seeion
        session.close();
        // Close SessionFactory
        factory.close();
    }

Increase: Pay attention to adding values to each other.

    @Test
    public void add() {

  // increase
         Person p = new Person("Ha-ha");
         Card c = new Card("431088192215523305");
         //Mutual establishment
         p.setCard(c);
         c.setPerson(p);
//This is because of the establishment.cascadeRelevance, so just add the end of the relationship. session.save(p); transaction.commit();
}

Enquiries:

    // query
         Person p = session.get(Person.class,
         "4028abee5f2a0142015f2a0144280000");
         System.out.println(p+"--"+p.getCard());



        

I won't test the rest.

Next, I will talk about one-to-many: a province corresponding to multiple cities as an example.

Step 1: Similarly, two new tables, province (province) and city (city), should be built. The structure of the tables is as follows:

Step 2: Create two new entity classes under the project / com.entity, correspond to the database, then encapsulate the construction, and delete the primary key of the table in the parametric construction. After that, the new hbm.xml files of these two classes are created. In province.hbm.xml and city.hbm.xml, the primary key generation strategy in < ID /> nodes is changed to uuid.

Step 3: Define and instantiate the collection of city (multi-end) in the province (one-end) entity class, (set and list) take set as an example. Then it can be encapsulated.

    private Set<City> cities = new HashSet<>();
 
        public Set<City> getCities() {
        return cities;
    }

    public void setCities(Set<City> cities) {
        this.cities = cities;
    }

 

Step 4: Define province (one end) object in city (multi-end) entity class and encapsulate it. Note: At this time, the property of pid (foreign key of one end table in multi-end table) should be removed from the entity class of city (still exists in database table), because the defined province object and the < property/> node corresponding to the pid generated in city.hbm.xml should also be removed.

     private Province province;

     public Province getProvince() {
        return province;
    }

    public void setProvince(Province province) {
        this.province = province;
    }

 

Step 5: Add the following code to the <class/> node in hbm.xml at one end:

<! -- The name of a collection name table table with multiple ends defined in the class at one end of the name - >
<set name="cities" table="city" inverse="true" cascade="save-update"> <key> <! - Primary Key Name at One End <column name="pid" /> </key> <! -- Fully qualified name for a mu lt i-terminal class - > <one-to-many class="com.entity.City" /> </set>

Add the following code to the <class/> node in the multiterminal hbm.xml:

 

<!--name= "Set name defined at one end in a multiterminal class" class= "Fully qualified name of a class at one end"-->
        <many-to-one name="province" class="com.entity.Province">
            <! - Key names in mu lt i-end tables (primary key names at one end)-->
            <column name="pid" />
        </many-to-one>

 

Step 6: Add entity class to hibernate.cfg.xml configuration file. Mapping relation of hbm.xml < mapping/>.

<mapping resource="com/entity/Province.hbm.xml" />
        <mapping resource="com/entity/City.hbm.xml" />

 

This configuration is OK, so the question arises again? What is inverse in hbm.xml < set/> at the end?

 

Inverse: Responsible for controlling relationships, default is false, that is, both ends of the relationship can be controlled, but this will cause some problems, update because both ends control the relationship, so repeated updates. Generally speaking, one end should be set to true. Then the maintenance relationship of the SQL statement is operated on multiple ends.

 

Step 7: Testing: @Test is the same as one-to-one testing.

Increase:

 

         Province p = new Province("Hunan");
         City c = new City("Changsha");
         City c1 = new City("Zhuzhou");
         City c2 = new City("Xiangtan");
//Mutual establishment
         p.getCities().add(c);
         p.getCities().add(c1);
         p.getCities().add(c2);
        
         c.setProvince(p);
         c1.setProvince(p);
         c2.setProvince(p);

         session.save(p);

         transaction.commit();

 

Enquiries:

    City c = (City) session.createQuery("from City where cname=?").setParameter(0, "Changsha").uniqueResult();
        System.out.println(c.getProvince().getPid());

The rest of the methods will not be tested.

Finally, it tells about many-to-many: for example, multiple roles correspond to multiple privileges and multiple privileges correspond to multiple roles:

The first step is to build the table as usual: users, roles, and users_roles. The structure of the table is as follows:

 

Step 2: Create two new entity classes under the project / com.entity. The middle table is not used and corresponds to the database. Then encapsulate the structure and remove the primary key of the table in the parametric structure. After that, the new hbm.xml files of these two classes are created. In hbm.xml, the primary key generation strategy in < id/> node is changed to uuid.

Step 3: Define and instantiate each other's set in these two entity classes, (set and list) Take set as an example. Then it can be encapsulated.

Step 4: Add the following code to users.hbm.xml:

//Name = collection object name table = intermediate table name 
<set name="roles" table="users_role" inverse="true" cascade="save-update">
//This class of primary key names <key column="uid"></key>
//The full path name of the object in the calss set set set is column foreign key name (the primary key name of the object in the set set set) <many-to-many class="com.entity.Role" column="rid" /> </set>

Add the following code to role.hbm.xml:


//Name = collection object name table = intermediate table name 
<set name="users" table="users_role" inverse="true" cascade="save-update">
//This class of primary key names <key column="rid"></key>
//The full path name of the object in the calss set set set is column foreign key name (the primary key name of the object in the set set set) <many-to-many class="com.entity.Users" column="uid" /> </set>

Step 6: Add entity class to hibernate.cfg.xml configuration file. Mapping relation of hbm.xml < mapping/>.

    <mapping resource="com/entity/Users.hbm.xml" />
        <mapping resource="com/entity/role.hbm.xml" />

The final test:

Increase:

         Users u = new Users("Ha-ha");
         Role r = new Role("Grass Chicken Administrator");
         Role r1 = new Role("General Administrator");
         Role r2 = new Role("Garbage Administrator");
        
         u.getRoles().add(r);
         u.getRoles().add(r1);
         u.getRoles().add(r2);
        
         r.getUsers().add(u);
         r1.getUsers().add(u);
         r2.getUsers().add(u);

transaction.commit();

Enquiries:

    Users s = session.get(Users.class, "4028abee5f664493015f6644959b0001");
     for (Role r : s.getRoles()) {
       System.out.println(r);
         }

//List<Users> ls = session.createQuery("from Users u left outer join fetch u.roles r where r.rid='4028abee5f664493015f6644958a0000'").list();
    //    for (Users users : ls) {
     //       System.out.println(users.getRoles());
    //    }

 

This is the end of hibernate!

Topics: Java xml Session Hibernate Attribute