Why code from "Spring in action 5" don't work (keyHolder.getKey() return null, but entity is saved in DB)?
private long savePizzaInfo(Pizza pizza) {
pizza.setCreatedAt(new Date());
PreparedStatementCreator psc =
new PreparedStatementCreatorFactory(
"insert into PIZZA (name, createdAt) values (?, ?)",
Types.VARCHAR, Types.TIMESTAMP
).newPreparedStatementCreator(
Arrays.asList(
pizza.getName(),
new Timestamp(pizza.getCreatedAt().getTime())));
KeyHolder keyHolder = new GeneratedKeyHolder();
template.update(psc, keyHolder);
return keyHolder.getKey().longValue();
}
My DB Table:
CREATE TABLE PIZZA
(
ID bigint DEFAULT (NEXT VALUE FOR
PUBLIC.SYSTEM_SEQUENCE_12CA966F_4FFD_469C_BA69_80BB93916EF3) AUTO_INCREMENT
PRIMARY KEY NOT NULL,
NAME varchar(50) NOT NULL,
CREATEDAT timestamp NOT NULL
);
CREATE UNIQUE INDEX PRIMARY_KEY_4 ON PIZZA (ID);
You have to instruct PreparedStatementCreatorFactory instance to return the generated keys:
PreparedStatementCreatorFactory preparedStatementCreatorFactory = new PreparedStatementCreatorFactory(
"insert into PIZZA (name, createdAt) values (?, ?)",
Types.VARCHAR, Types.TIMESTAMP
);
// By default, returnGeneratedKeys = false so change it to true
preparedStatementCreatorFactory.setReturnGeneratedKeys(true);
PreparedStatementCreator psc =
preparedStatementCreatorFactory.newPreparedStatementCreator(
Arrays.asList(
pizza.getName(),
new Timestamp(pizza.getCreatedAt().getTime())));
You need to specify your prepared statement
notice the Statement.RETURN_GENERATED_KEYS in the code bellow
you need something like this
final PreparedStatementCreator psc = new PreparedStatementCreator() {
#Override
public PreparedStatement createPreparedStatement(final Connection connection) throws SQLException {
final PreparedStatement ps = connection.prepareStatement("INSERT INTO `names` (`name`) VALUES (?)",
Statement.RETURN_GENERATED_KEYS);
ps.setString(1, name);
return ps;
}
};
Why not use SimpleJdbcInsert instead?
dbcInsert = new SimpleJdbcInsert(jdbcTemplate);
jdbcInsert.withTableName("TABLE_NAME").usingGeneratedKeyColumns(
"Primary_key");
Map<String, Object> parameters = new HashMap<>();
parameters.put("Column_NAME1", bean.getval1());
parameters.put("Column_NAME2", bean.getval2());
// execute insert
Number key = jdbcInsert.executeAndReturnKey(new MapSqlParameterSource(
parameters));
// convert Number to Int using ((Number) key).intValue()
return ((Number) key).intValue();
Related
saveProfit method
public void saveProfit() throws SQLException {
ObservableList<Bread> bread = FXCollections.observableArrayList();
Connection conn = null;
PreparedStatement ps = null;
Statement statement = null;
ResultSet resultSet = null;
try {
conn = DriverManager.getConnection ("jdbc:mysql://localhost:3306/bakery", "root", "a3756421");
statement = conn.createStatement();
resultSet = statement.executeQuery("SELECT * FROM bread");
while (resultSet.next()) {
Bread newBread = new Bread(
resultSet.getString("breadName"),
resultSet.getString("breadType"),
resultSet.getString("breadFlavour"),
resultSet.getInt("breadStock"),
resultSet.getInt("breadPrice"));
newBread.setBreadId(resultSet.getInt("breadId"));
bread.add(newBread);
}
for(Bread b : bread){
String sql = "insert into best5(pname, profit) values (?,?)";
ps = conn.prepareStatement(sql);
ps.setString(1,b.getBreadName());
ps.setInt(2, b.getBreadPrice()*b.getBreadStock());
}
for(Bread b : bread){
String sql = "insert into worst5(pname, profit) values (?,?)";
ps = conn.prepareStatement(sql);
ps.setString(1,b.getBreadName());
ps.setInt(2, b.getBreadPrice()*b.getBreadStock());
}
}
}
Bread object
public class Bread {
private String breadName, breadFlavour, breadType;
private int breadStock, breadPrice, breadId;
private File imageFile;
private Image photo;
public Bread(String breadName, String breadType, String breadFlavour,int breadPrice, int breadStock) {
setBreadName(breadName);
setBreadType(breadType);
setBreadFlavour(breadFlavour);
setBreadPrice(breadPrice);
setBreadStock(breadStock);
setImageFile(new File("./src/Images/foodDefault.png"));
}
bread table
create table bread (
breadId INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
breadName VARCHAR(30),
breadType VARCHAR(30),
breadFlavour VARCHAR(30),
breadStock INT,
breadPrice DOUBLE,
imageFile VARCHAR(100));
best5 table
create table best5 (
id INT not null primary key auto_increment,
pname VARCHAR(30),
profit INT);
worst5 table is basically the same with different name.
So, I am trying to loop the insert into best5(pname, profit) values(?,?) to store data from bread table. But, it seems like only the first row of bread table is stored into best5 table and the rest is ignored. What am I doing wrong? I am new to javafx and MySQL. Please correct my mistakes.
I have the RAW(16) PK column in Oracle, and trying to insert into it using JDBC:
PreparedStatement stmt = connection.prepareStatement("insert into COUNTRY (id, state, version, code, name, nationality, issuing_entity, country) values (?, ?, ?, ?, ?, ?, ?, ?)");
UUID id = UUID.randomUUID();
stmt.setObject(1, id, Types.BINARY);
However, I am getting an exception:
java.sql.SQLException: Invalid column type
at oracle.jdbc.driver.OraclePreparedStatement.setObjectCritical(OraclePreparedStatement.java:8494)
at oracle.jdbc.driver.OraclePreparedStatement.setObjectInternal(OraclePreparedStatement.java:7995)
at oracle.jdbc.driver.OraclePreparedStatement.setObject(OraclePreparedStatement.java:8559)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.setObject(OraclePreparedStatementWrapper.java:225)
at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.setObject(HikariProxyPreparedStatement.java)
at rw.gov.dgie.framework.test.AbstractTestCaseWithDB.tryToInsertCountry(AbstractTestCaseWithDB.java:78)
at rw.gov.dgie.framework.test.AbstractTestCaseWithDB.dbSetup(AbstractTestCaseWithDB.java:62)
at test.rw.gov.dgie.bms.terr.service.TestCountryService.init(TestCountryService.java:37)
I am getting the same exception when trying to use DbSetup for inserting test data.
Is there a way to make JDBC insert UUIDs into RAW(16) column?
I am using Oracle JDBC 12.2.0.1.0.
You must convert the UUID to a byte array. See the method asBytes how to do it.
After it the binding is a s simple as using setBytes.
Example
def stmt = con.prepareStatement("insert into TAB_UUID (id, uuid) values (?,?)")
// bind
stmt.setInt(1,1)
def uuid = UUID.randomUUID()
stmt.setBytes(2,asBytes(uuid))
def rowCount = stmt.executeUpdate()
Here just for case the link doesn't work the conversion method UUID to byte array
public static byte[] asBytes(UUID uuid) {
ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
bb.putLong(uuid.getMostSignificantBits());
bb.putLong(uuid.getLeastSignificantBits());
return bb.array();
}
Oracle has no real UUID datatype and dealing with RAW(16) is really a PITA.
What we do, is to pass the UUID as a string to a SQL statement that uses hextoraw():
String sql = "insert into foo (id) values (hextoraw(?))";
PreparedStatement pstmt = connection.prepareStatement(sql);
UUID uid = UUID.randomUUID();
pstmt.setString(1, uid.toString().replaceAll("-", ""));
getJdbcTemplate().update("INSERT INTO abc(abc_id, abc_uuid, "
+ "VALUES (?, ?)",
abcId, uuidToBytes(abcUuid))
Here's a helper method to converet UUID type to bytes.
private byte[] uuidToBytes(final UUID uuid) {
if (Objects.isNull(uuid)) {
return null;
}
final byte[] uuidAsBytes = new byte[16];
ByteBuffer.wrap(uuidAsBytes)
.order(ByteOrder.BIG_ENDIAN)
.putLong(uuid.getMostSignificantBits())
.putLong(uuid.getLeastSignificantBits());
return uuidAsBytes;
}
JdbcTemplate provides different methods for performing a DML operations like insert. Please, consider for instance update.
#MarmiteBomber provides in his/her answer all the necessary information for performing what you need, please, only wrap the code appropriately in the different artifacts defined by Spring.
For example, you can use PreparedStatementCreator, something like:
jdbcTemplate.update(new PreparedStatementCreator() {
#Override
public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
PreparedStatement ps = con.prepareStatement("insert into TAB_UUID (id, uuid) values (?,?)");
ps.setInt(1,1);
UUID uuid = UUID.randomUUID();
ps.setBytes(2,asBytes(uuid));
return ps;
}
});
The code can be simplified using lambdas to:
jdbcTemplate.update(con -> {
PreparedStatement ps = con.prepareStatement("insert into TAB_UUID (id, uuid) values (?,?)");
ps.setInt(1,1);
UUID uuid = UUID.randomUUID();
ps.setBytes(2,asBytes(uuid));
return ps;
});
If you prefer, you can use PreparedStatementSetter instead:
jdbcTemplate.update("insert into TAB_UUID (id, uuid) values (?,?)", new PreparedStatementSetter() {
#Override
public void setValues(PreparedStatement ps) throws SQLException {
ps.setInt(1,1);
UUID uuid = UUID.randomUUID();
ps.setBytes(2, asBytes(uuid));
}
});
Again, the code can be simplified with lambdas:
jdbcTemplate.update("insert into TAB_UUID (id, uuid) values (?,?)", ps -> {
ps.setInt(1,1);
UUID uuid = UUID.randomUUID();
ps.setBytes(2, asBytes(uuid));
});
In both examples you explicitly invoke setBytes in the underlying prepared statement and use the asBytes method from the Marmite answer.
I have an EMPLOYEE table that has 4 fields; ID, NAME, AGE, SALARY. ID is unique and auto-increment.
Below is the code to insert a row in the table, using Spring's JDBCTemplate. Please suggest, how can I auto increment ID field.
String sql = "insert into employee values (?,?,?,?)"
jdbcTemplate.update( sql, ID, bean.getName(), bean.getAge(), bean.getSalary())
I see, you tag your question Oracle, use Oracle sequence then.
String sql = "insert into Employee values (id_seq.nextval, ?, ?, ?)";
jdbcTemplate.update(sql, bean.getName(), bean.getAge(), bean.getSalary());
Ref: How to create Sequence in Oracle.
Just add following code to your domain:
Ref: http://docs.spring.io/spring/docs/2.5.x/reference/jdbc.html#jdbc-auto-genereted-keys
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
final String INSERT_SQL = "insert into my_test (name) values(?)";
final String name = "Rob";
KeyHolder keyHolder = new GeneratedKeyHolder();
jdbcTemplate.update(
new PreparedStatementCreator() {
public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
PreparedStatement ps =
connection.prepareStatement(INSERT_SQL, new String[] {"id"});
ps.setString(1, name);
return ps;
}
},
keyHolder);
Trying to create CRUD application using jdbc and mysql. I have Person.class and two tables in Database:
class Person {
String name;
String surname;
List<String> phones;
}
Tables:
`phone`
(
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`owner` INT UNSIGNED NOT NULL,
`number` VARCHAR(50) NOT NULL,
CONSTRAINT `PK_phone` PRIMARY KEY (`id`)
)
`person`
(
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`surname` VARCHAR(150) NOT NULL,
`name` VARCHAR(150) NOT NULL,
CONSTRAINT `PK_phonebook` PRIMARY KEY (`id`)
)
ALTER TABLE `phone`
ADD CONSTRAINT `FK_phone_person`
FOREIGN KEY (`owner`) REFERENCES `person` (`id`) ON DELETE Cascade ON UPDATE Cascade
;
SET FOREIGN_KEY_CHECKS=1 ;
How i can add person with field List phones to database using Servlets???
For example: Harry Smith +37521987902
+56727172713
+45679012214
The idea is simple, you can use this way
Insert your person
get the id of that person
insert the list of phone
You can use it like this :
try {
Class.forName(driver);
Connection connection = DriverManager.getConnection(DB_URL, DB_username, DB_password);
String query = "INSERT INTO person (surname, name) values(?, ?)";
PreparedStatement preparedStatement = connection.prepareStatement(query);
preparedStatement.setString(1, "hello");
preparedStatement.setString(2, "jdbc");
int affectedRows = preparedStatement.executeUpdate();
long id = 0;
if (affectedRows > 0) {
ResultSet generatedKeys = preparedStatement.getGeneratedKeys();
if (generatedKeys.next()) {
id = generatedKeys.getLong(1);
} else {
throw new SQLException("Creating user failed, no ID obtained.");
}
}
connection.setAutoCommit(false);
PreparedStatement ps = connection.prepareStatement("INSERT INTO phone (owner, number) values(?, ?)");
for (String phone : listePhone) {
preparedStatement.setLong(1, id);
preparedStatement.setString(2, phone);
ps.addBatch();
}
ps.executeBatch();
connection.commit();
}
You can learn how to execute multiple statement in one shot, using statement-batching
I want to insert two rows into master and detail table.
Master and detail table with autoincremented id.
CREATE TABLE MI_User (
id_user NUMBER(11) NOT NULL,
age NUMBER(3),
name_user varchar2(128),
constraint USER_PK PRIMARY KEY (id_user));
CREATE TABLE Friends (
id_friend NUMBER(11) not null,
name VARCHAR2(64),
id_user NUMBER(11) NOT NULL,
constraint FRIEND_PK PRIMARY KEY (id_friend)
);
Model classes are:
public class User {
private String id;
private Integer age;
private String name;
private ArrayList<Friend> friends;
}
public class Friend {
private Long id_user;
private String name;
}
There is example from Hibernate:
tx = session.beginTransaction();
User user = new User(name, age);
employeeID = (Integer) session.save(employee);
tx.commit();
I try to insert with JDBS:
conn = DriverManager
.getConnection("jdbc:oracle:thin:#localhost:1521:xe", "hr", "hr");
ps = conn
.prepareStatement("INSERT INTO MI_USER (BALANCE, AGE, NAME_USER, GENDER, COMPANY, EMAIL, ADDRESS)\n" +
" VALUES (?, ?, ?, ?, ?, ?, ?)");
ps.setDouble(1, user.getDoubleBallans());
ps.setInt(2, user.getAge());
ps.setString(3, user.getName());
ps.executeUpdate();
How to get id_user and insert row into detail table?
I think you can use ps.getGeneratedKeys() method and send Statement.RETURN_GENERATED_KEYS as second parameter in conn.prepareStatement() method.