Hibernate: Refrain update on Many-to-Many insert - sql

Problem
I use hibernate to store data in an MySQL database. I now want to store a Company and one of its Branches.
The company:
#Entity
#Table(name="company")
public class Company {
#Id
#GeneratedValue
#Column(name="id")
private int id;
#Column(name="name")
private String name;
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name="company_branch_join",
joinColumns={#JoinColumn(name="company_id")},
inverseJoinColumns={#JoinColumn(name="branch_id")})
private Set<CompanyBranch> branches;
// Getters and setters...
}
And the branch:
#Entity
#Table(name="company_branch")
public class CompanyBranch {
#Id
#GeneratedValue
#Column(name="id")
private int id;
#Column(name="branch")
private String branch;
#ManyToMany(mappedBy="branches", cascade = CascadeType.ALL)
private Set<Company> companies;
// Getters and setters...
}
Question
The code works and i can insert the data in the join table. The problem is the override policy regarding the branches. My branch table in the database is already filled with branches and its IDs so i don't want to modify the data. However on an company-insert the branches associated with the company get stored again and override the data with the same ID in the database. How can I prevent this behavior?
CompanyBranch cb1 = new CompanyBranch();
cb1.setId(1);
cb1.setBranch("Manufacturing");
CompanyBranch cb2 = new CompanyBranch();
cb2.setId(2);
cb2.setBranch("DONT-INSERT");
Company c = new Company();
c.setName("[Random-Company-Name]");
c.addBranch(cb1);
c.addBranch(cb2);
CompanyManager cm = new CompanyManagerImpl();
cm.saveCompany(c);
The branch table before execution looks like this:
| id | branch |
+----+----------------+
| 1 | Manufacturing |
| 2 | IT |
|... | ... |
The table should not change. But after execution it looks like this:
| id | branch |
+----+----------------+
| 1 | Manufacturing |
| 2 | DONT-INSERT |
|... | ... |

Instead of creating new branch instances with the new operator, retrieve a reference to them using EntityManager.getReference(), e.g.:
CompanyBranch cb1 = entityManager.getReference(CompanyBranch.class, 1);

Related

Can not persist null values (nullable=true)

I need to insert a null value, instead of empty string into my H2-Database.
My entity looks like this:
#Entity
#Getter
#Setter
#Builder
#AllArgsConstructor
#NoArgsConstructor
public class Link extends Auditable implements Serializable {
private static final long serialVersionUID = -5337989744648444109L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#NotEmpty(message = "title is required")
#Column(length = 50)
private String title;
#Column(unique = true, nullable = true)
private String url;
}
and my sql-statment with values, which will be generated from Hibernate looks like
insert
into
link
(link_id, created_by, creation_date, title, url)
values
(null, ?, ?, ?, ?,) -
session_id=2B491C6BFFE4F66BD63C6453E234D991 user_ip=0:0:0:0:0:0:0:1 2022-12-21 14:21:21,232 |
https-jsse-nio-5550-exec-9 | TRACE | o.h.t.d.sql.BasicBinder | binding
parameter 1 as [VARCHAR] - [mymail#test.com] -
session_id=2B491C6BFFE4F66BD63C6453E234D991 user_ip=0:0:0:0:0:0:0:1 2022-12-21 14:21:21,232 |
https-jsse-nio-5550-exec-9 | TRACE | o.h.t.d.sql.BasicBinder | binding
parameter [2] as [TIMESTAMP] - [2022-12-21T14:21:21.231038300] -
session_id=2B491C6BFFE4F66BD63C6453E234D991 user_ip=0:0:0:0:0:0:0:1 2022-12-21 14:21:21,233 |
https-jsse-nio-5550-exec-9 | TRACE | o.h.t.d.sql.BasicBinder | binding
parameter [3] as [VARCHAR] - [Tessst] -
session_id=2B491C6BFFE4F66BD63C6453E234D991 user_ip=0:0:0:0:0:0:0:1 2022-12-21 14:21:21,233 |
https-jsse-nio-5550-exec-9 | TRACE | o.h.t.d.sql.BasicBinder | binding
parameter [4] as [VARCHAR] - [null] -
session_id=2B491C6BFFE4F66BD63C6453E234D991 user_ip=0:0:0:0:0:0:0:1
The last parameter [4] will be filled with null value, but i still have in my H2-Database empty string.
I've tested, that i can insert manually null values into this column with naitve sql statement.
As i've updated SpringBoot from 2.4.5 to 2.7.7, i don't have this bug anymore

Query Ignite cache created in Java with sqlline

I am using ignite's CacheQueryExample:
public class CacheQueryExample {
/** Organizations cache name. */
private static final String ORG_CACHE = CacheQueryExample.class.getSimpleName() + "Organizations";
/** Persons collocated with Organizations cache name. */
private static final String PERSON_CACHE = CacheQueryExample.class.getSimpleName() + "Persons";
/**
* Executes example.
*
* #param args Command line arguments, none required.
* #throws Exception If example execution failed.
*/
public static void main(String[] args) throws Exception {
try (Ignite ignite = Ignition.start("examples/config/example-ignite.xml")) {
System.out.println();
System.out.println(">>> Cache query example started.");
CacheConfiguration<Long, Organization> orgCacheCfg = new CacheConfiguration<>(ORG_CACHE);
orgCacheCfg.setCacheMode(CacheMode.PARTITIONED); // Default.
orgCacheCfg.setIndexedTypes(Long.class, Organization.class);
...
Using sqlline, the following tables are created:
+-----------+--------------------------------+-----------------------------+------------+---------+----------+------------+-----------+---------------------------+---------------+
| TABLE_CAT | TABLE_SCHEM | TABLE_NAME | TABLE_TYPE | REMARKS | TYPE_CAT | TYPE_SCHEM | TYPE_NAME | SELF_REFERENCING_COL_NAME | REF_GENERATIO |
+-----------+--------------------------------+-----------------------------+------------+---------+----------+------------+-----------+---------------------------+---------------+
| IGNITE | CacheQueryExampleOrganizations | ORGANIZATION | TABLE | | | | | | |
| IGNITE | CacheQueryExamplePersons | PERSON | TABLE
How do I query these tables in sqlline? I have tried the following and none works:
0: jdbc:ignite:thin://127.0.0.1:10800> select * from person;
Error: Failed to parse query. Table "PERSON" not found; SQL statement:
select * from person [42102-197] (state=42000,code=1001)
0: jdbc:ignite:thin://127.0.0.1:10800> select * from CacheQueryExamplePersons.person;
Error: Failed to parse query. Schema "CACHEQUERYEXAMPLEPERSONS" not found; SQL statement:
select * from CacheQueryExamplePersons.person [90079-197] (state=42000,code=1001)
And logging to sqlline for the specific schema:
0: jdbc:ignite:thin://127.0.0.1:10800/CacheQu> select * from person;
Error: Failed to set schema for DB connection for thread [schema=CACHEQUERYEXAMPLEPERSONS] (state=50000,code=1)
Try enclosing the table scheme name with double quotes.

How do i get the Specflow scenario outline example data to a table

Is there any way to get the scenario context outline example values i mean all the values in to a table
Scenario Outline: Create a Matter
Given I enter "< parameter1 >"
Then I enter "<parameter2>"
Then I enter "<parameter3>"
Then I enter "<parameter4>"
Then review all the parameters entered above in this final step
Examples:
| parameter1 | Paramter2|Parameter3|Parameter4|....|parameter14|
| value |value2 |value3 |value4 |....|value14|
in the above scenario is there any way to get all the example values in step4 to a table
I know I can set ScenarioContext.Current[parameter1] = value in each step
In my case I have 14 parameters which are used in each step but in the final step i need to use all the 14 parameters
is there any way I get the example values in to table.
I don't want to break in to smaller scenario
like below
Scenario: breaking in to smaller chunks
Given I enter the following
| parameter1 | Paramter2|
| value |value2|
Here is something I use that may help. Andreas is the expert though on this stuff and he probably has a better idea. Since your format was less than ideal, I used a basic scenario.
Change it to a "Scenario" and Drop the "Scenario Outline".
The feature looks like this:
Scenario: Validate Shipping Fees
When the user enters the State then we can verify the city and shipping fee
| City | State | Shipping |
| Boulder | Colorado | 6.00 |
| Houston | Texas | 8.00 |
Add the Table.
public class ShippingTable
{
public string City { get; set; }
public string State { get; set; }
public string Shipping { get; set; }
}
Then in your step:
[When(#"the user enters the State then we can verify the city and shipping fee")]
public void WhenTheUserEnterTheStateThenWeCanVerifyTheCityAndShippingFee(Table table)
{
var CityState = table.CreateSet<ShippingTable>();
foreach (var row in CityState)
{
try
{
Pages.CheckoutPage.SelectState(row.State);
Pages.CheckoutPage.SelectCity(row.City);
var recdPrice = Pages.CheckoutPage.GetShippingPrice;
Assert.AreEqual(row.shipping, recdPrice);
}
catch (Exception)
{
throw new Exception("This is jacked up");
}
}
}

How to make method in crudRepository to find any elements using list ids?

There is application on Spring + jpa + jpa Crud repository + hibernate-envers
So, I have a table UserRecord with any fields
Table UserRecord
id name surname age version
Table UserRecord_AUD
id name surname age version REV REVINFO
So, when I add new user it writes into UserRecord table.
If I change age, and try to write, new version of user writes into UserRecord and old version of user moves into UserRecord_AUD table with same id.
all saved entities have own records in UserRecord_AUD
My task is get all entities from UserRecord_AUD by id's list.
Example
===============================
Table UserRecord
11-1 Ivan Ivanov 23 2
22-2 Natasha Ivanova 22 1
===============================
Table UsersRecord_AUD
11-1 Ivan Ivanov 9 0
11-1 Ivan Ivanov 9 1
22-2 Natasha Ivanova 22 0
===============================
I have repository:
#Repository
public interface UserRepository extends CrudRepository<UserRecord, String>
{}
I need in custom method, which can find all users from table UserRecord_AUD by id -list
instead call any times
repository.find(id);
I need to call
repository.find(ids);
How to make that:
I tried to:
#Query(value = "select id, name, surname, age, REV as VERSION, IDCALC from USERRECORD_AUD where PR_KEY in (:ids)", nativeQuery = true)
List<UserRecord> findHistoryByIds(List<String> ids);
But there is exception
Name for parameter binding must not be null or empty! On JDKs < 8, you
need to use #Param for named parameters, on JDK 8 or better, be sure
to compile with -parameters.; nested exception is
java.lang.IllegalArgumentException: Name for parameter binding must
not be null or empty! On JDKs < 8, you need to use #Param for named
parameters, on JDK 8 or better, be sure to compile with -parameters.
My JPA entity is
#Entity
#Audited
#Table(name = "UserRecord")
#NoArgsConstructor(access = AccessLevel.PUBLIC)
#AllArgsConstructor
#Getter
#Setter
#Access(AccessType.FIELD)
public class UserRecord {
#Id
#GeneratedValue(generator = "uuid")
#GenericGenerator(name = "uuid", strategy = "uuid2")
#Column(name = "id")
private String id;
#Column(name = "name", length = 100, unique = false)
private String name;
#Column(name = "surname", length = 100, nullable = false)
private String surname;
#Column(name = "age", length = 100, nullable = false)
private String age;
#Version
private int version;
In case of indexed parameter, use indexes
#Query(value = "select id, name, surname, age, REV as VERSION, IDCALC from USERRECORD_AUD where PR_KEY in (?1)", nativeQuery = true)
List<RiskMetricRecord> findHistoryByIds(List<String> ids);
In case of named parameter, use #Param
#Query(value = "select id, name, surname, age, REV as VERSION, IDCALC from USERRECORD_AUD where PR_KEY in :ids", nativeQuery = true)
List<RiskMetricRecord> findHistoryByIds(#Param("ids") List<String> ids);

org.springframework.jdbc.BadSqlGrammarException: bad SQL grammar

I am getting the following error in my code:
org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad
SQL grammar [insert into bulletins (date, name, subject, note, approved) values
(?, ?, ?, ?, ?)]; nested exception is com.mysql.jdbc.exceptions.MySQLSyntaxError
Exception: Unknown column 'date' in 'field list'
This line is in my Spring controller.
bulletinDAO.writeBulletin(bulletin);
The actual place in my DAO class where I'm trying to write using Hibernate.
public void writeBulletin(Bulletin bulletin) {
try {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
session.save(bulletin);
tx.commit();
} catch (Exception e) {
System.out.println(e.toString());
}
}
Here is my model class.
#Entity
#Table(name="login")
public class Bulletin {
#Id
#Column(name="id")
#GeneratedValue
private int id;
#Column(name="bulletin_date")
private String date;
#Column(name="name")
private String name;
#Column(name="subject")
private String subject;
#Column(name="note")
private String note;
#Column(name="approved")
private boolean approved;
// Getters and setters follow
}
Finally, here is the layout of the table.
+---------------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+---------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| bulletin_date | varchar(10) | YES | | NULL | |
| name | varchar(30) | YES | | NULL | |
| subject | varchar(50) | YES | | NULL | |
| note | varchar(2500) | YES | | NULL | |
| approved | tinyint(1) | YES | | NULL | |
+---------------+---------------+------+-----+---------+----------------+
There must be something wrong with your getters and setters.
I would recommend changing the property name from date to bulletinDate. And then set & get it correctly...
#Column(name="bulletin_date")
private String bulletinDate;
public String getBulletinDate() {
return bulletinDate;
}
public void setBulletinDate(String bulletin_date) {
this.bulletinDate = bulletin_date;
}
Your issue is here
[insert into bulletins (date, name, subject, note, approved)]
Whereas you need bullletin_date.
From experience i needed to rebuild the project completely to ensure that right column name is referenced.
Clear your project cache and rebuild it.
Let me know how you go and i'll help further if it doesn't help.